[sdiy] "lunetta"/CMOS sound-making equivalents in C Programming???
Gordon JC Pearc e
gordonjcp at gjcp.net
Sat Mar 24 11:16:32 CET 2012
On 23/03/12 21:45, dan snazelle wrote:
>
> is this the section responsible?
>
> is MIX the variable which allows some realtime control over the effect?
Somewhat. The comments a little further down explain what's going on,
but essentially the mix control sets the proportion of "wet" signal in
the output.
The sample is broken up into eight "slices" of 3072 bytes each. For
"straight" playback a phase accumulator steps through the sample
byte-by-byte, gets the value, and mixes it into the output. For the
"circuit bent" output, the pointer derived from the phase accumulator is
ANDed with a bitmask.
You'll see lots of bitshifts in here, because it's basically fixed-point.
> ISR(TIMER2_OVF_vect) {
So, this bit is called by the timer overflow interrupt, at 32kHz
> // internal timer
> if(icnt1++> 31) { // slightly faster than 1ms
> do_update=1;
> icnt1=0;
> }
Sets a flag when it's time to do timed stuff in the main loop
> out = 0;
> // calculate the sample output
> // bitmask contains the "bend"
> // mix sets the proportion of "bent" to clean output
> out += (mix*pgm_read_byte_near(wave+sample+(((s_ptr>>8)& bitmask))))>>7;
"wave+sample+(((s_ptr>>8) & bitmask)))) >> 7" could maybe do with one
layer of brackets off.
"wave" points to the base of the wavetable. "sample" is the selected
sample number from 0 to 7 multiplied by 3072, ie. the size of the slice.
"s_ptr" is the phase accumulator - we don't want the lower eight bits,
that's the "fractional part" of the pointer.
"bitmask" would be all ones if you didn't want any "bent" effects, all
zeros if you wanted silence and various patterns in between if you want
strange effects. If you had it all ones bar the lowest two bits, you'd
effectively divide the sample rate by four, for example.
> out += ((127-mix)*pgm_read_byte_near(wave+sample+(s_ptr>>8)))>>7;
Much simpler, "wave", "sample" and "s_ptr" mean the same thing.
Note that here we subtract mix from 127 before multiplying so we get a
crossfade. The eight-bit sample value is multiplied by a 7-bit value,
then shifted right 7 bits (would 8 overflow? It's an unsigned multiply
so maybe not - need to check that!) to discard the "fractional part" again.
> //out = pgm_read_byte_near(wave+sample+(s_ptr>>8));
>
> /*
> // DC restore and clip output
> out += 127;
> out>>=1;
> */
> if (out<0) { out=0; digitalWrite(13, LOW); }
> if (out>0xff) { out=0xff; digitalWrite(13, LOW); }
This will toggle an LED if the output goes negative or offscale,
shouldn't happen
> OCR2A = out;
Stuff it into the Output Compare Register for timer 2 channel A
> s_ptr += s_tword;
Accumulate some phase
> if (s_ptr>786175) s_tword=0;
If we're off the end of the sample, stop.
> }
HTH,
Gordon.
More information about the Synth-diy
mailing list