[sdiy] "lunetta"/CMOS sound-making equivalents in C Programming???

dan snazelle subjectivity at hotmail.com
Sat Mar 24 14:19:10 CET 2012



On Mar 24, 2012, at 6:16 AM, Gordon JC Pearc e wrote:

> 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.
> 
\
thanks a lot for the explanation
looks like I will be trying this out over the weekend!

dan


More information about the Synth-diy mailing list