void Song::synthesize(VoiceLibrary library, ofstream& file){ int sampleRate = library.sampleRate; fileio::writeWavHeader( sampleRate, file); Phone phoneNow = library.getPhone(notes[0]); Speech speech = Speech(phoneNow.sample.startToSound(0).compatibleSound( vector<float>(phoneNow.overlap*sampleRate,0) ));//make empty speech to fill. for(int note=0;note<notes.size();note++){ cerr<<notes[note].lyric; //log each lyric float leftoverLength = speech.duration -phoneNow.overlap; Phone phoneNext; if(note+1<notes.size()){ phoneNext = library.getPhone(notes[note+1]); //stretch next note if(phoneNext.preutter>notes[note].length/tempo){ float newPreutter = notes[note].length/tempo; float newOverlap = phoneNext.overlap * newPreutter/phoneNext.preutter; phoneNext.sample.stretch(0,phoneNext.preutter,newPreutter); phoneNext.preutter = newPreutter; phoneNext.overlap = newOverlap; } }else{ phoneNext = Phone(); phoneNext.preutter=phoneNext.overlap=0; } //stretch current note float targetLength = notes[note].length/tempo -phoneNext.preutter +phoneNext.overlap; float vowelLength = min( notes[note].duration/tempo, targetLength ); phoneNow.sample.stretch( phoneNow.preutter, phoneNow.sample.duration, vowelLength ); //add silence between notes if needed float restLength = targetLength - vowelLength; if(restLength!=0){ phoneNow.sample.add( Speech(phoneNow.sample.startToSound(0).compatibleSound( vector<float>(restLength*sampleRate,0) )), 0 ); } //add modified note to previous speech sample speech.add(phoneNow.sample, phoneNow.overlap); //transpose float noteBoundary = leftoverLength +phoneNow.preutter; float writeLength = noteBoundary +notes[note].length/tempo -phoneNext.preutter; float freq1,freq2; freq2 = freqFromNum(notes[note].notenum); if(note!=0){ freq1 = freqFromNum(notes[note-1].notenum); }else{ freq1 = freq2; } function<float (float)> frequency = [noteBoundary,freq1,freq2](float time){ if(time<noteBoundary){ return freq1; }else{ return freq2; } }; speech.transpose(frequency,writeLength); //pop&write fileio::append(speech.pop(writeLength),file); //reassign phoneNow = phoneNext; } fileio::updateWavHeader(file); }