#include "cwCommon.h" #include "cwLog.h" #include "cwCommonImpl.h" #include "cwTest.h" #include "cwMem.h" #include "cwFile.h" #include "cwText.h" #include "cwObject.h" #include "cwFileSys.h" #include "cwAudioFile.h" #include "cwMath.h" #include "cwVectOps.h" #include "cwMidi.h" #include "cwDspTypes.h" #include "cwDsp.h" #include "cwAudioTransforms.h" #include "cwWaveTableBank.h" #include "cwWaveTableNotes.h" cw::rc_t cw::wt_note::gen_note( wt_bank::handle_t wtbH, unsigned instr_idx, unsigned midi_pitch, unsigned velocity, srate_t srate, sample_t** audioChA, unsigned audioChN, unsigned audioFrmN ) { rc_t rc = kOkRC; unsigned chN = audioChN; // output audio channels const wt_bank::multi_ch_wt_seq_t* mcs = nullptr; // wave table ptr sample_t* aM = nullptr; // temp. audio buffer const unsigned kDspFrmN = 64; // default frame request count unsigned reqFrmN = 0; // count of sample frames requestdd unsigned retFrmN = 0; // countof sample frames returned unsigned audioChFrmIdx = 0; // current audio frame index into audioChA[] audiofile::handle_t afH; // multi-channel wave table oscillator struct dsp::multi_ch_wt_seq_osc::obj_str osc; // get the requested wave table if((rc = wt_bank::get_wave_table( wtbH, instr_idx, midi_pitch, velocity, mcs )) != kOkRC ) { goto errLabel; } // if the wave table has fewer channels than the output audio buffer if( mcs->chN < chN ) chN = mcs->chN; // TODO: VERIFY srate == SAMPLE RATE OF WAVETABLES // mcs->valid_srate(srate) // allocate and setup xthe oscillator if((rc = create(&osc,chN,mcs)) != kOkRC ) { rc = cwLogError(rc,"multi-ch-wt-seq-osc create failed."); goto errLabel; } // allocate a tempory audio buffer aM = mem::allocZ(chN*kDspFrmN); // for each sample in the output signal while( retFrmN==reqFrmN && audioChFrmIdx < audioFrmN ) { // calc. the count of requested output audio frames on this iteration reqFrmN = std::min(kDspFrmN,audioFrmN-audioChFrmIdx); // generate reqFrmN output samples with the oscillator if((rc = process(&osc, aM, chN, reqFrmN, retFrmN)) != kOkRC ) goto errLabel; // copy the generated signals into the output signal for(unsigned i=0; idelta_sec; unsigned beg_frm_idx = (unsigned)floor(secs*srate); unsigned dur_frm_cnt = (unsigned)floor(n->dur_sec*srate); if( beg_frm_idx > outFrmN ) { // TODO: assert(0); } if( beg_frm_idx + dur_frm_cnt > outFrmN ) { // TODO: assert(0); } for(unsigned j=0; jinstr_idx, n->pitch, n->velocity, srate, chA, outChN, dur_frm_cnt)) != kOkRC ) { rc = cwLogError(rc,"Generate note failed on 'instr:%i pitch:%i vel:%i.",n->instr_idx, n->pitch, n->velocity); goto errLabel; } } errLabel: cwLogInfo("Generated %6.1f seconds of audio.",secs); return rc; } cw::rc_t cw::wt_note::gen_notes( wt_bank::handle_t wtbH, const note_t* noteA, unsigned noteN, srate_t srate, unsigned audioChN, const char* out_audio_fname, unsigned audio_bits) { rc_t rc = kOkRC; unsigned audioFrmN = 0; sample_t* audioM = nullptr; double max_sec = 0; sample_t* chA[ audioChN ]; double secs = 0; for(unsigned i=0; i max_sec ) max_sec = secs+noteA[i].dur_sec; } cwLogInfo("Allocated %i notes in %6.1f seconds of audio.",noteN,max_sec); audioFrmN = (unsigned)ceil( max_sec * srate ); audioM = mem::allocZ( audioFrmN * audioChN ); for(unsigned i=0; i max_pitch ) { rc = cwLogError(kInvalidArgRC,"The min pitch:%i is greater than the max pitch:%i.",min_pitch,max_pitch); goto errLabel; } if((rc = wt_bank::create(wtbH,2,wtb_json_fname)) != kOkRC ) { goto errLabel; } if(!filesys::isDir(out_dir)) filesys::makeDir(out_dir); for(unsigned midi_pitch=min_pitch; midi_pitch<=max_pitch; ++midi_pitch) { unsigned velA[ midi::kMidiVelCnt ]; unsigned velCnt = 0; double secs = 0; const unsigned fnameN = 32; char fname[fnameN+1]; // get the sampled velocities for the instr_idx/midi_pitch if((rc = wt_bank::instr_pitch_velocities( wtbH, instr_idx, midi_pitch, velA, midi::kMidiVelCnt, velCnt )) != kOkRC ) { goto errLabel; } // allocate the note records array noteA = mem::resizeZ(noteA,velCnt); // fill in the note record array with one note for each sampled velocity for(unsigned i=0; i