Hi
Thanks for this great piece of Code!
It deals exactly the problem I'm encountering at the moment.
I'm trying to program a DTMF-Generator.
So what I need is some code that is recieving a DTMF-sign (e.g. '3'), generating the appropriate tone consisting of 2 sine-frequencies with a given length and storing that in a wav-file.
The easiest way would be to simply copy your code and don't ask why it's working. But i would like to understand the maths behind the tone-generation.
The basics with sound-theory (distance between semitones/half-tones) is pretty clear. So i generally understand the calculations in the "playSine()"-Method.
But there are some questions left:
1. In the comments given in the code it is mentioned that halfsteps are done from tone A4 (concert pitch). But why is the first sine frequency calcualted with 220Hz as base frequency? That would be an A3. Or am I missing something?
2. I'm not quite sure if i understand the single steps in the code correctly (in WaveformProc there are unfortunatly very few comments), so I will try my own explanation. Please correct my explanations if they are wrong:
In the "data"-array (
with twice the number of 'buckets' as the samplerate (44100) because of two channels (stereo)) you store the added (
and amplified?) amplitudes of both of the sine-waves at the current "sample-bucket". And you set a maximum amplitude of 5000 (
ike a software audio-compressor?) for the added amplitudes?
These steps performed over and over again and if the buffer is "full" (
waveposition >twoPi) you start a the beginning of the data-buffer.
after buffer was written completly, there is a Marshal.copy form the dataa-buffer to the "Pointer-buffer" of WaveformProc, so that bass can play that data in BASS_ChanellPlay().
Was this the right explanation of the data-flow?
3. If i want to write that whole produced data to a wav-file, is the right way some kind of this?
_waveWriter = new WaveWriter( "test.wav", channel, 24, true);
Thanks i advance for any advice!
Basti
edit:
After working some time with this code example from AName, I figured out a little mistake in his code.
In Waveform-Process the for-loop should count up "+2" and not "a++" (due to stereo channel). Code looks then something like this:
private int WaveformProc(int handle, IntPtr buffer, int length, IntPtr user)
{
//store original length of buffer
int waveCalculated = length;
//fill SineData-Array with values of the two added sine waves
for (int a = 0; a < length; a+=2)
{
...
}
//copy added sine data to g_SineChannel if there are still samples to calculate
Marshal.Copy(g_SineData, 0, buffer, length/2);
//copy data to wavewriter
g_WaveWriter.Write(g_SineData, waveCalculated);
//return length of buffer
return waveCalculated;
}
With this correction there is also no dividing of frequency with factor "2" neccessary.
Anyway: Still stays a great piece od code AName. Saved much time for me