May 29, 2023, 01:04:22 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


simple sound generator

Started by sapero, May 01, 2008, 01:35:12 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

sapero

May 01, 2008, 01:35:12 PM Last Edit: May 01, 2008, 01:40:28 PM by sapero
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);
}

pistol350

That's pretty cool!
thank you for sharing this one! :)
Regards,

Peter B.

Haim

Very nice!
Thanks for sharing this.

Haim