[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