On 29/10/12 15:11, bimmerfan222 wrote:
> Thanks for the info and your thoughts..
>
> yea, you guys are probably right about just getting a full Ensoniq
> synth instead of trying to rebuild one from an Apples guts.
>
> I found it an interesting readup though.. and that buchty site is
> definately the motherload of info on it.
Get a Mirage, learn Forth and 6809 assembler. I'll give you the rest.
> I am curious though.. are the 16/32 bit PICs from Microchip using a
> similar form of osc method of sound generation?
>
> The evidently use ports called "output compare/PWM"
>
> Would the programming methods similar?
Not in the least. PWM - pulse width modulation - is familiar to us from
synthesis as an effect. With microcontrollers it is used to do
something similar to a DAC. If you connect an LED to a PWM pin, with
PWM set to 50% the LED will be at half brightness, with it set to 25% it
will be at quarter brightness and so on. You pedantic bastards can all
shut the hell up about the linearity of light intensity.
If you do the PWM fast enough you can no longer hear the carrier (say if
it's at 32kHz) but if you filter that carrier off you get a varying DC
voltage from the pulse width. Now, the "output compare" stuff works
because you have a counter and you compare the value of that with your
desired PWM level. So, start with your output pin high and the counter
at zero, count until you reach 128 and the comparator matches, toggle
the pin low and keep counting until 255 (because we're using an 8-bit
counter for this example), and the counter wraps back to zero so reset
the pin back to high. And, here lies the clever bit.
When that overflow interrupt fires to say we've wrapped, the ISR
contains a routine that calculates the next value for the sample you
want to play. Let me demonstrate:
https://github.com/gordonjcp/gyoza/blob/master/acidmatic/acidmatic.pdeLine 242 is where the ISR starts. This is called every 31.25μs when the
32kHz timer interrupt fires. Line 245 to 248 set a flag roughly every
990μs which signals that we should run the envelope calculations.
line 251-252, phaccu is the phase accumulator. It is a 32-bit value
which has the timing word tword_m added to it for every sample. The
timing word is calculated from 2∗∗32 (the size of the word) times the
desired frequency divided by sample rate) - I ∗think∗, I can't quite
remember how I wrote that bit. Anyway you end up with the upper eight
bits of phaccu being a sawtooth wave at the desired output frequency,
which we get into an 8-bit value icnt by shifting right 24 times.
line 255 clips it into a squarewave at not quite full scale, to avoid
overdriving the next bit...
... which is line 260-262, a fastish integer implementation of a biquad
lowpass.
line 265 sets the output level by multiplying the filter output by gain
(from 0 to 127) and shifting it back down to 0-255, and finally...
line 266 loads the value into the output compare register, where it sets
the PWM switching point.
Whew. Did I mention this all happens in a shade over 31 microseconds?
I haven't got recordings of this exact code, but its predecessor sounded
like this:
http://www.gjcp.net/~gordonjcp/mp3s/arduinoacid.oggThe drum samples were played by the same Arduino using a similar trick.
In that repository you'll see another sketch called fmtoy, which sounds
like this:
http://www.gjcp.net/~gordonjcp/mp3s/fmtoy.oggSimple 2-op FM synthesis implemented in a 16MHz AVR, with 8-bit sample
playback hence the gritty aliasing.
Right, now one of you clever little sods can take that code and work out
how to use it to make a replacement for the Poly800 oscillator chip.
--
Gordon JC Pearce MM0YEQ