MUS177/206 – window makefile changes for Pd externals

The makefile to compile the example externals from Pd 0.49 needs to be edited in order to work with Visual Studio Community 2017.

Do all of your editing and compilation on a copy of Pd in your \Users folder

The VC definition needs to be changed (as usual) to point to the 64-bit tools in VSC. Your setting will likely be different than mine.

VC="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726"

The PDNTCFLAGS need to be changed to eliminate /WX (treat all warnings as errors, and add a definition for PD_LONGINTTYPE to give PD 64-bit pointers. Without this, the audio example (dspobj~) will crash.

PDNTCFLAGS = /W3 /DNT /DPD /DPD_LONGINTTYPE="long long" /nologo

Now, make sure PDNTLDIR points to the 64 bit library folder by appending “\x64” to the path

PDNTLDIR = $(VC)\lib\x64

Finally, remove references to old names.lib and kernel32.lib and change libc.lib to libcmt.lib

PDNTLIB = $(PDNTLDIR)\libcmt.lib \
..\..\bin\pd.lib

music 176 syllabus – winter 2020

music 176 – custom programming for music – winter 2020

instructor – tom erbe – tre@music.ucsd.edu

thursday: 2 – 5

•••••focus

this quarter we will be learning music DSP programming on bare metal embedded processors with the STM32F processor. to do this we will cover 4 topics.

  1. c/c++ programming
  2. the STM32Fn development environment and SDK
  3. computer music algorithms

••••schedule

as the class is 3 hours long, we will be spending time in each class making sure everyone can recreate the examples on their hardware. bring your laptop, STM development board, earbuds and MIDI keyboard to class.

  1. basics (basics and compilers – setting up a dev environment)
  2. stm 1 – writing embedded code and c rehash
  3. stm 2 – adding sound (first assignment)
  4. dsp code 1 – amplifiers delay and oscillators
  5. dsp code 2 – filters, waveshaping and fm (second assignment)
  6. stm 3 – integrating DSP code into synth framework. MIDI parsing
  7. stm 4 – incorporating files and filesystems (final project assignment)
  8. dsp code 3 – reverb, fft
  9. workshop
  10. class presentation

••••texts – software

these books are very helpful… recommended as reference.

  • C Primer Plus by Stephen Prata
  • Computer Music by Charles Dodge
  • DAFX by Udo Zolzer

•••••my office hours

1-3 tuesday and 10-2 thursday

pm or email me for other hours

tre@music.ucsd.edu

tre@soundhack.com

•••••class requirements

3 projects of increasing complexity…. one is a final project. grad students will be required to use their final project in a piece or for research.

****class notes & assignments

class notes and many examples are on http://synthnotes.ucsd.edu. assignments will be posted on the week assigned.

****example code

additive sawtooth with polyphony – f4disco-midi-saw

same as above with ADSR, 2 oscillator, multiple waveforms, LFO – f4disco-doublesaw

same as above with addition of filters and wave shaping polynomial –f4disco-oscfilt

an example showing sample playback, simple echo and auto-panning – f4disco-sample-echo

7th week example with sample playback and reverb – f4disco-sample-verb

8th week example using compression, timers, ADC – f4disco-sample-timer-mic

9th week example using the LEAF library – f4disco-leaf

MUS177/267 full duplex audio 1

Gettinng full duplex audio to work on the discovery boards is tricky, as they were not designed to do this. We will dig deep into the hardware configuration to find some work-arounds.

STM32F4Discovery

This board has no high fidelity line audio in, so cannot be used for high fidelity full duplex audio. However, it does have many 12 bit ADC inputs and 2 12 bit DAC outputs.

To get an ADC and DAC to work together, they have to be synchronized. In my example code we will use a timer set at 48000 Hz to clock both. We also need a timer which can be used for both the ADC and DAC. If you look at the ADC HAL header file, you will see the following:

/** @defgroup ADC_External_trigger_Source_Regular ADC External Trigger Source Regular  
* @{
*/
/* Note: Parameter ADC_SOFTWARE_START is a software parameter used for        */
/*       compatibility with other STM32 devices.                              */
#define ADC_EXTERNALTRIGCONV_T1_CC1    ((uint32_t)0x00000000U)
#define ADC_EXTERNALTRIGCONV_T1_CC2    ((uint32_t)ADC_CR2_EXTSEL_0)
#define ADC_EXTERNALTRIGCONV_T1_CC3    ((uint32_t)ADC_CR2_EXTSEL_1)
#define ADC_EXTERNALTRIGCONV_T2_CC2    ((uint32_t)(ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_0))
#define ADC_EXTERNALTRIGCONV_T2_CC3    ((uint32_t)ADC_CR2_EXTSEL_2)
#define ADC_EXTERNALTRIGCONV_T2_CC4    ((uint32_t)(ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_0))
#define ADC_EXTERNALTRIGCONV_T2_TRGO   ((uint32_t)(ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1))
#define ADC_EXTERNALTRIGCONV_T3_CC1    ((uint32_t)(ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_0))
#define ADC_EXTERNALTRIGCONV_T3_TRGO   ((uint32_t)ADC_CR2_EXTSEL_3)
#define ADC_EXTERNALTRIGCONV_T4_CC4    ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_0))
#define ADC_EXTERNALTRIGCONV_T5_CC1    ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_1))
#define ADC_EXTERNALTRIGCONV_T5_CC2    ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_0))
#define ADC_EXTERNALTRIGCONV_T5_CC3    ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_2))
#define ADC_EXTERNALTRIGCONV_T8_CC1    ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_0))
#define ADC_EXTERNALTRIGCONV_T8_TRGO   ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1))

And in the DAC HAL header we see:

/** @defgroup DAC_trigger_selection DAC Trigger Selection
  * @{
  */
#define DAC_TRIGGER_NONE                   ((uint32_t)0x00000000U) /*!< Conversion is automatic once the DAC1_DHRxxxx register has been loaded, and not by external trigger */
#define DAC_TRIGGER_T2_TRGO                ((uint32_t)(DAC_CR_TSEL1_2 | DAC_CR_TEN1)) /*!< TIM2 TRGO selected as external conversion trigger for DAC channel */
#define DAC_TRIGGER_T4_TRGO                ((uint32_t)(DAC_CR_TSEL1_2 | DAC_CR_TSEL1_0 | DAC_CR_TEN1)) /*!< TIM4 TRGO selected as external conversion trigger for DAC channel */
#define DAC_TRIGGER_T5_TRGO                ((uint32_t)(DAC_CR_TSEL1_1 | DAC_CR_TSEL1_0 | DAC_CR_TEN1)) /*!< TIM5 TRGO selected as external conversion trigger for DAC channel */
#define DAC_TRIGGER_T6_TRGO                ((uint32_t)DAC_CR_TEN1) /*!< TIM6 TRGO selected as external conversion trigger for DAC channel */
#define DAC_TRIGGER_T7_TRGO                ((uint32_t)(DAC_CR_TSEL1_1 | DAC_CR_TEN1)) /*!< TIM7 TRGO selected as external conversion trigger for DAC channel */
#define DAC_TRIGGER_T8_TRGO                ((uint32_t)(DAC_CR_TSEL1_0 | DAC_CR_TEN1)) /*!< TIM8 TRGO selected as external conversion trigger for DAC channel */

Timer 2 and 8 trigger output are in common for both ADC and DAC. In my example I will use timer 8. Look at functions timer8_init(), adc1_init() and dac1_init() for details.

Finally, notice that in the audio callback I am copying and scaling the input first, then processing audio (an echo in this case), and finally copying and scaling the output. Also, both input and output can be processed in the DAC callback. No need to do it in the ADC callback as they are synchronized by the same clock.

void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef* DacHandle)
{
  int i,j;
  for(i = 0, j = 0; i < 16; i++, j+=2)
  {
    inBuffer[i] = inBuffer[i+1] = (float)(adcBuffer[i] * 0.00048828125f) - 1.0f;
  }
  audioBlock(inBuffer, outBuffer, 16);
  for(i = 0, j = 0; i < 16; i++, j+=2)
  {
    dacBuffer[i] = (int16_t)((outBuffer[j] + outBuffer[j+1] + 2.0f) * 1023.0f);
  }
}

Here is the example code:

f4-adcdac-passthru

STM32F746Discovery

The BSP code supplied with the board is inadequate as it doesn’t allow the line in to be used. I have found a developer who modified the code to do full duplex input and output, but I have yet to try it myself. I will do so by next Thursday. The code is here:

https://community.st.com/thread/19377

MUS177/267 – Sample Playback & “Moog” Filter

Here is the project from today’s class. Sample playback simply requires creating a pointer to the samples at the address used in FLASH (0x08080000 in this case), creating an offset for the first sample played, and incrementing this value until reaching the last sample to be played.

f4disco-sample-button-filter

To write samples in the STM32F4 FLASH (we will write in the second half of FLASH from 0x08080000 to 0x080FFFFE)

  1. prepare a sound file by making it a 16 bit mono WAV at 48k sample rate
  2. there are only 524288 bytes, so limit the sample to 262144 samples or 5.4 seconds
  3. save the sample
  4. using Hexfiend, strip off the WAV header (everything up to the word ‘data’ and the 4 bytes after that)
  5. save as a new file with the suffix “.bin”
  6. alternatively open WAV with SoundHack and save as Headerless, 16bit byte swap and “.bin” suffix
  7. make sure OpenOCD is running and connected to your board
  8. use telnet in a terminal window to connect to OpenOCD – “telnet localhost 4444”
  9. make sure STM32F4 is halted with “reset halt”
  10. write into FLASH with command “flash write_image erase filename.bin 0x08080000″
  11. restart your programs with “reset run”