#include #include //for class ofstream #include //for the sin function #include //for the data types uint32_t, etc. #include //for the strncpy function #include //for class numeric_limits #include //for the accumulate alogorithm using namespace std; //This program automatically creates an output file named sine.wav //Move this file to your public_html directory and then point your browser at // http://storm.cis.fordham.edu/~jsmith/sine.wav //where jsmith is your fordham name. int main() { double half {pow(2.0, 1.0/12.0)}; //half step double whole {half * half}; //1 whole step = 2 half steps double C {261.63}; //do: middle C in Hertz double D {C * whole}; //re double E {D * whole}; //mi double F {E * half}; //fa double G {F * whole}; //sol double A {G * whole}; //la double B {A * whole}; //ti double CC {B * half}; //do struct note { double pitch; //in cycles per second double length; //in seconds }; note a[] { //Beethoven, Ninth Symphony, Fouth Movement {E, 1.0}, //Freude, schöner Götterfunken {F, 0.5}, {G, 0.5}, {G, 0.5}, {F, 0.5}, {E, 0.5}, {D, 0.5}, {C, 0.5}, //Tochter aus Elysium {C, 0.5}, {D, 0.5}, {E, 0.5}, {E, 0.75}, {D, 0.25}, {D, 1.0}, {E, 1.0}, //Wir betreten feuertrunken {F, 0.5}, {G, 0.5}, {G, 0.5}, {F, 0.5}, {E, 0.5}, {D, 0.5}, {C, 0.5}, //Himmlische, dein Heiligtum! {C, 0.5}, {D, 0.5}, {E, 0.5}, {D, 0.75}, {C, 0.25}, {C, 1.0} }; const size_t n {size(a)}; //how many notes //total number of seconds for entire melody double duration {accumulate(begin(a), end(a), 0.0, [](double sum, const note& no) {return sum + no.length;})}; const uint32_t sampleRate {210 * 210}; //Hertz //Store the sine wave data. const int numSamples {static_cast(sampleRate * duration)}; int16_t *data {new int16_t[numSamples]}; int d {0}; //Loop through the notes of the melody. for (int i {0}; i < n; ++i) { //Loop through the samples of each note. for (int s {0}; s < sampleRate * a[i].length; ++s) { double x {a[i].pitch * 2.0 * M_PI * s / sampleRate}; double y {numeric_limits::max() * sin(x)}; data[d] = y; ++d; } //Make the last samples of each note gradually fade out. int lastSamples {500}; for (int t {lastSamples}; t >= 0; --t) { data[d-t] *= static_cast(t)/lastSamples; } } //Create a new data type. struct WAVHeader { char chunkId[4]; //Should be "RIFF" uint32_t chunkSize; //Size of the file minus 8 bytes char format[4]; //Should be "WAVE" char subchunk1Id[4]; //Should be "fmt " uint32_t subchunk1Size; //Size of fmt chunk (16 bytes for PCM) uint16_t audioFormat; //1 for PCM (Pulse-Code Modulation) uint16_t numChannels; //Number of channels (1 mono, 2 stereo) uint32_t sampleRate; //Sample rate (e.g., 44100 Hz) uint32_t byteRate; //SampleRate*NumChannels*BitsPerSample/8 uint16_t blockAlign; //NumChannels * BitsPerSample / 8 uint16_t bitsPerSample; //Bits per sample (e.g., 16) char subchunk2Id[4]; //Should be "data" uint32_t subchunk2Size; //Size of the audio data }; //Create one variable of the new data type. WAVHeader header { {'R', 'I', 'F', 'F'}, //chunkId 0, //chunkSize (assigned later) {'W', 'A', 'V', 'E'}, //format {'f', 'm', 't', ' '}, //subchumk1Id 16, //subchunk1Size 1, //audioformat PCM: Pulse-Code Modulation 1, //numchannels sampleRate, //sampleRate: 44100 Hz sampleRate * 1 * 16 / 8,//byteRate 1 * 16 / 8, //blockAlign 16, //bitsPerSample {'d', 'a', 't', 'a'}, //subchunk2Id 0 //subchunk2Size (assiged later) }; //Fill in the two missing fields of the header structure. header.subchunk2Size = numSamples * header.numChannels * header.bitsPerSample / 8; header.chunkSize = 36 + header.subchunk2Size; //Write the header and the data to the binary output file. ofstream file("sine.wav", ios::binary); if (!file) { cerr << "Couln't open output file.\n"; return EXIT_FAILURE; } file.write(reinterpret_cast(&header), sizeof header); file.write(reinterpret_cast(data), header.subchunk2Size); file.close(); delete[] data; return EXIT_SUCCESS; }