This tiny program creates a wave file with all 7 full-tones from 10 octaves, starting from 13.75 Hz.
It does also generate precise sine wave for given frequency and duration.
The amplitude of generated tones can be constant, or modulated by a second half-sine oscilator.
Have fun ;)
#autodefine "OFF"
//#define PULSE_VOLUME
sub main()
{
int hFile = OpenFile("sound octaves.wav", MODE_CREATE | MODE_WRITE);
// mono 44100Hz 16bit
write(hFile, "RIFF????WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00\x44\xac\x00\x00\x88\x58\x01\x00\x02\x00\x10\x00data????", 44);
double toneduration = 0.4; // 0.4s for every tone
double octavestart = 13.75; // start frequency
int OctaveCount = 10; // create 10 octaves
double samplingrate = 44100;
double tonestep = sqrEx(2, 12); // 12 tones in octave
double octaveend = octavestart * __power(2, OctaveCount) * tonestep;
// w:white key, tone; b:black key, halftone
unsigned byte *constOctaveTonesMatrix = "wbwbwwbwbwbw";
unsigned byte *pOctaveTonesMatrix = constOctaveTonesMatrix;
double ToneSineAngle = 0.0;
for (double freq=octavestart; freq<octaveend; freq*=tonestep)
{
int freqPrinted = false;
//print(freq, " Hz");
// 44100 samples - 1 second
// ? samples - toneduration
double NumberOfSamples = toneduration * samplingrate;
// 44100Hz - 22us
// 1000Hz - 1000us
double ToneSineAngleStep = 360.0 / (samplingrate / freq);
// volume - for every tone (in toneduration seconds), the volumeangle should decrease from 90 to 0
#ifdef PULSE_VOLUME
double volumeangle = 180.0;
double volumestep = volumeangle / NumberOfSamples;
#endif
// create the tone
while (NumberOfSamples > 0.0)
{
if (*pOctaveTonesMatrix == 'w') // skip halftones
{
#ifdef PULSE_VOLUME
// the simplest way - tone amplitude looks like a sinusoide
double sample = sind(ToneSineAngle) * (/*volume*/sind(volumeangle) * 32700.0);
if (volumeangle > 0.0) volumeangle -= volumestep;
#else
double sample = sind(ToneSineAngle) * 32700.0;
#endif
word wSample = sample;
write(hFile, &wSample, 2);
if (!freqPrinted) {
print(freq, " Hz");
freqPrinted = true;
}
ToneSineAngle += ToneSineAngleStep;
}
NumberOfSamples -= 1.0;
}
pOctaveTonesMatrix++;
if (!*pOctaveTonesMatrix) {
// next octave
pOctaveTonesMatrix = constOctaveTonesMatrix;
print();
}
}
DWORD rifflen = seek(hFile) - 8;
// update size of RIFF chunk
seek(hFile, 4);
write(hFile, &rifflen, 4);
// update size of data chunk
seek(hFile, 40);
rifflen -= 36;
write(hFile, &rifflen, 4);
// close current file
CloseFile(hFile);
MessageBox(0, "done", "");
}
sub sqrEx(double x,double y),double
{
return __power(x, 1.0 / y);
}
That's pretty cool!
thank you for sharing this one! :)
Very nice!
Thanks for sharing this.
Haim