[sdiy] audio effects in C??
Gordon JC Pearc e
gordonjcp at gjcp.net
Fri Feb 17 23:31:08 CET 2012
On 17/02/12 20:59, dan snazelle wrote:
> Ok lets say I have a program (on an Avr or pic) that has a few different variables.
<snip>
Dan, I hope you don't mind me answering your off-list questions on-list.
If you do, tough, it's a bit late now ;-)
The reason I want to tackle it on-list is because I want some
constructive (hopefully) criticism of my project.
Firstly take a look at this article:
http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/
This is what a lot of my AVR synthesis stuff is based on. Where
possible I tried to keep it in line with the Arduino environment but for
the more outré experiments I needed to go to bare metal because things
had already hooked ISRs that I needed.
Okay, now you asked me about fmtoy. Let's look at that:
https://github.com/gordonjcp/gyoza/blob/master/fmtoy/fmtoy.pde
The first few lines define various preprocessor things, and some lookup
tables to go into flash including an 8-bit sine and floating point
pitch-in-Hz table.
Next there's a struct that contains patch data, and an array of values
that comprise the eight "stock" patches - note that N_PATCH is one less
than the number of patches!
We can skip over lots of horrible global variables.
set_env() calculates the envelope parameters from the current patch
set_patch() copies a patch from flash to RAM
In setup() there is some cruft used when I was driving an analogue
resonant filter from fmtoy - yes, it was pretty awesome. No, it didn't
work very well.
Okay, in the main loop there is a *horrible* buggy MIDI parser that
accepts note on, note off, and some continuous controllers. They are
inadequately documented.
Line 366 to 385 calculate the oscillator pitch, envelope levels and
phase and ultimately the timing word for the oscillators
Line 418 and down is the PWM ISR that actually does the sound
generation. Now from reading the sine DDS article you should know that
Arduino pin 11 (PWM2A) is the PWM output and needs to be lowpass
filtered and fed to an amp.
Every 32 times round the loop, we fire the update flag to tell it to
update the voice every (roughly) 1ms
Each operator adds the timing word value to the phase accumulator, and
takes the top bits as the pointer to the sine table. So we calculate
the offset into the table from the phase accumulator plus the feedback
(or Op1) amount, and wrap by taking it modulo 256 (doing & 0xff would
maybe be faster, if the compiler doesn't optimise this).
Line 430 calculates the amount of feedback to apply, by multiplying the
output, adding the feedback, and shifting right by 8 bits to scale it
back down to an unsigned byte.
Line 441 does a trick to keep the DC offset steady even though we're
using unsigned numbers because the AVR8 family only support unsigned int
multiply
Lines 444-447 put it back into a sensible range and ensure that the
output value is clipped rather than going off-scale which would cause it
to "wrap around" with very objectionable noises.
Finally, the value is written to OCR2A where it sets the output PWM
width, and hence the "DAC" voltage.
So you asked me:
1) Where the output is defined - it's defined in setup() and actually
created in the ISR at the end. For practical purposes, noises come out
on pin 11.
2) It looks for MIDI on the serial port. In this case, it actually
receives at 57600bps so you will need something to take MIDI and connect
to a serial port.
Grab this: http://www.gjcp.net/~gordonjcp/alsabridge.c and compile it
with the instructions at the top of the file. It's crap but it works.
You could also hook up an optoisolator and use it with MIDI directly if
you set the baud rate.
3) You could convert it to look for CV and gate. Use the analogue
inputs for CV (I guess you need to clip to 5V, or scale by 2) and work
out the relationship between the input voltage and pitch. Probably 1024
steps will give you accurate enough pitch tracking. Use a GPIO pin for
gate, and remove all the note queuing stuff from lines 211 to 260. Then
figure out where to handle your CV on in there somewhere.
Hope this helps. I welcome any comments or suggestions, but not half as
much as I welcome patches ;-)
--
Gordon JC Pearce MM0YEQ
More information about the Synth-diy
mailing list