Jimmus:
I plan to dig in and figure out what I need, but there are a few concepts I don't fully understand yet.
There is this comment in dds_audio.cpp which basically describes how it works:
//-------------------------------------------------------------------------------------
// Sound Generation
//-------------------------------------------------------------------------------------
// - uses simple Direct Digital Synthesis to generate the waveform at c. 31.250KHz
// - Notes on how DDS works:
// There's a table of 256 sine values in sinetable[]
// If we have an index into the wave table and, say, add 1 to it every time, we end up
// extracting a sequence of values which is a sine wave.
// Since we are doing this at a fixed frequency - the rate of the Timer2 interrupt
// which is every 32uS - then by adding 1 to the index we would take 256 * 32uS
// to generate one complete sine wave. This would be a total of 8,193uS which would be
// an audio frequency of 122Hz.
// To generate other frequencies, we make bigger steps in the wave table index.
// For example, if we added 32 every time, we would step 0,32,64,96,128,160,192,224,0 (wraps at 256)
// so it only takes 8 * 32uS = 256uS to output an approximation of a sine wave at 3,906Hz
// This is a bit of a crap sinewave output with only 8 steps in it, but we are quite limited
// in this processor only running at 16MHz. However, the result is not too bad when we filter
// the output a bit.
// Frequency resolution is helped by using a 16-bit phase value, the sinetable[] table is indexed
// by the upper 8 bits. So to make 122Hz we would add 256 to phase for each sample.
//
// - Timer 2 ISR is called 31,250 times per second, it writes an 8-bit sample to the PWM output
// - samples are generated by the currently-selected sample function via the function pointer: pSampleFunc
I don't have any "help" yet on the API other than the comments in the header file.
However; in the main DDS_Audio_test.ino sketch there are a number of example 'generators', each generator supplies one audio sample at a time. They are called 32,000 times/second.
The simplest is:
//-----------------------------------------------
// Example generator 1
// - simply generates samples for a 1KHz sinewave
//
uint16_t g1_phase_add= Hz_TO_PHASE_STEP(1000);
uint8_t exampleGenerator1()
{
static uint16_t phase;
phase+= g1_phase_add; // bump the phase
return PHASE_TO_SINE(phase); // return point in sinewave
}
which generates a 1kHz tone. It does this by using the value of 'phase' to step thru a sinewave table at a calculated rate - the size of 'phase_add' determines how fast 'phase' adds up and therefore how fast the sinewave table is stepped through. The faster, the higher the frequency.
One generator could generate, say, 4 separate tones and add them together - so it would be polyphonic (much more than 4 and the processor can't keep up).
e.g.
phase1+= phase1_add; // bump the phase
sine1= PHASE_TO_SINE(phase1); // return point in sinewave
phase2+= phase2_add;
sine2= PHASE_TO_SINE(phase2);
phase3+= phase3_add;
sine3= PHASE_TO_SINE(phase3);
phase4+= phase4_add;
sine4= PHASE_TO_SINE(phase4);
// some magic to add them all together:
return (sine1 >> 2) + (sine2 >> 2) + (sine3 >>2) + (sine4 >>2);
The values of each of the 'phase_add' values can be set in the main loop by: e.g.
phase1_add= Hz_TO_PHASE_STEP( 1200 ); // set for 1200Hz
or
phase1_add= NOTE_C5; // set note C5 (the notes are already defined in 'phase step' form
To actually play something polyphonic will need some fairly complicated additional code in the main loop to time when each note should start and finish.
Hope that makes some sense... if you have any specific questions, just ask.
Yours,
TonyWilk