//------------------------------------------------------------------- // makewave.cpp // // This program generates the Pulse Code Modulation data for a // musical tone of one second's duration having a given pitch, // and stores it as a .wav format file (named 'wavetone.wav'). // // compile using: $ make makewave // // NOTE: The Waveform Audio File Format is a fully-documented, // proprietary format, developed jointly by IBM and Microsoft, // originally for the Windows 3.1 operating system in 1991 and // widely adopted for exchange of broadcast audio information. // Although their specification has been subsequently expanded // and updated, the original document is online as "Multimedia // Programming Interface and Data Specifications 1.0," (1991). // // programmer: ALLAN CRUSE // written on: 11 SEP 2005 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for write(), close() #define SAMPLE_RATE 8000 #define NUM_SAMPLES SAMPLE_RATE unsigned char pulsecode[ NUM_SAMPLES ]; char filename[] = "wavetone.wav"; int main( int argc, char **argv ) { // specify our default parameters for tone generation int sampleRate = SAMPLE_RATE, numSamples = NUM_SAMPLES; int frequency = 440, amplitude = 64, silence = 128; // accept an alternate frequency as a command-line argument if ( argc > 1 ) { int input = atoi( argv[1] ); if ((input > 0)||(input < sampleRate/2)) frequency = input; else { printf( "frequency out-of-range\n" ), exit(1); } } // apply our 'Timer-Counter' model for Square Wave generation int latchValue = sampleRate / frequency; int countValue = 0; for (int sample = 0; sample < NUM_SAMPLES; sample++) { if ( countValue == 0 ) countValue = latchValue; int flipflop = ( countValue < latchValue/2 ) ? -1 : 1; pulsecode[ sample ] = silence + flipflop * amplitude; --countValue; } //---------------------------------------------- // now store the pulse-code data as a .wav file //---------------------------------------------- // setup the .wav file parameters int fmt_ChunkSize = 16; int dataChunkSize = numSamples; int riffChunkSize = 4 + (8+fmt_ChunkSize) + (8+dataChunkSize); int formatTag = 1; int nChannels = 1; int bitsPerSample = 8; int samplesPerSec = sampleRate; int avBytesPerSec = samplesPerSec * nChannels; int frameAlignmnt = nChannels * (bitsPerSample/8); // open the .wav file for writing int fd = open( filename, O_WRONLY | O_CREAT | O_TRUNC, 0666 ); if ( fd < 0 ) { perror( filename ); exit(1); } // write the RIFF chunk write( fd, "RIFF", 4 ); write( fd, &riffChunkSize, 4 ); write( fd, "WAVE", 4 ); // write the FORMAT chunk write( fd, "fmt ", 4 ); write( fd, &fmt_ChunkSize, 4 ); write( fd, &formatTag, 2 ); write( fd, &nChannels, 2 ); write( fd, &samplesPerSec, 4 ); write( fd, &avBytesPerSec, 4 ); write( fd, &frameAlignmnt, 2 ); write( fd, &bitsPerSample, 2 ); // write the DATA chunk write( fd, "data", 4 ); write( fd, &dataChunkSize, 4 ); write( fd, pulsecode, numSamples ); // close the .wav file close( fd ); // show the filename and filesize to our user printf( "\npulse-code data saved as \'%s\' ", filename ); printf( "(%d bytes) \n\n", 8+riffChunkSize ); }