//This might continue over a number of blocks. double VoiceKey::TestEnergy (WaveTrack & t, sampleCount start, sampleCount len) { double sum = 1; auto s = start; //Keep track of start auto originalLen = len; //Keep track of the length of block to process (its not the length of t) const auto blockSize = limitSampleBufferSize( t.GetMaxBlockSize(), len); //Determine size of sampling buffer float *buffer = new float[blockSize]; //Get a sampling buffer while(len > 0) { //Figure out how much to grab auto block = limitSampleBufferSize ( t.GetBestBlockSize(s), len ); t.Get((samplePtr)buffer,floatSample, s,block); //grab the block; //Now, go through the block and calculate energy for(decltype(block) i = 0; i< block; i++) { sum += buffer[i]*buffer[i]; } len -= block; s += block; } delete [] buffer; return sum / originalLen.as_double(); }
//This might continue over a number of blocks. double VoiceKey::TestEnergy (WaveTrack & t, sampleCount start, sampleCount len) { double sum = 1; sampleCount s = start; //Keep track of start sampleCount originalLen = len; //Keep track of the length of block to process (its not the length of t) sampleCount blockSize = t.GetMaxBlockSize(); //Determine size of sampling buffer if( blockSize > len) blockSize = len; float *buffer = new float[blockSize]; //Get a sampling buffer while(len > 0) { sampleCount block = t.GetBestBlockSize(s); //Figure out how much to grab if(block > len) block = len; //Don't grab too much! t.Get((samplePtr)buffer,floatSample, s,block); //grab the block; //Now, go through the block and calculate energy for(int i = 0; i< block; i++) { sum += buffer[i]*buffer[i]; } len -= block; s += block; } delete [] buffer; return sum / originalLen; }
bool EffectNoise::Process() { if (noiseDuration <= 0.0) noiseDuration = sDefaultGenerateLen; //Iterate over each track TrackListIterator iter(mWaveTracks); WaveTrack *track = (WaveTrack *)iter.First(); while (track) { WaveTrack *tmp = mFactory->NewWaveTrack(track->GetSampleFormat(), track->GetRate()); numSamples = (longSampleCount)(noiseDuration * track->GetRate() + 0.5); longSampleCount i = 0; float *data = new float[tmp->GetMaxBlockSize()]; sampleCount block; while(i < numSamples) { block = tmp->GetBestBlockSize(i); if (block > (numSamples - i)) block = numSamples - i; MakeNoise(data, block, track->GetRate(), noiseAmplitude); tmp->Append((samplePtr)data, floatSample, block); i += block; } delete[] data; tmp->Flush(); track->Clear(mT0, mT1); track->Paste(mT0, tmp); delete tmp; //Iterate to the next track track = (WaveTrack *)iter.Next(); } /* save last used values save duration unless value was got from selection, so we save only when user explicitely setup a value */ if (mT1 == mT0) gPrefs->Write(wxT("/CsPresets/NoiseGen_Duration"), noiseDuration); gPrefs->Write(wxT("/CsPresets/NoiseGen_Type"), noiseType); gPrefs->Write(wxT("/CsPresets/NoiseGen_Amp"), noiseAmplitude); mT1 = mT0 + noiseDuration; // Update selection. return true; }
double VoiceKey::TestDirectionChanges(WaveTrack & t, sampleCount start, sampleCount len) { sampleCount s = start; //Keep track of start sampleCount originalLen = len; //Keep track of the length of block to process (its not the length of t) sampleCount blockSize = t.GetMaxBlockSize(); //Determine size of sampling buffer unsigned long directionchanges = 1; sampleFormat lastval=sampleFormat(0); int lastdirection=1; if( blockSize > len) blockSize = len; sampleFormat *buffer = new sampleFormat[blockSize]; //Get a sampling buffer while(len > 0) { sampleCount block = t.GetBestBlockSize(s); //Figure out how much to grab if(block > len) block = len; //Don't grab too much! t.Get((samplePtr)buffer,floatSample, s,block); //grab the block; if (len == originalLen) { //The first time through, set stuff up special. lastval = buffer[0]; } //Now, go through the block and calculate zero crossings for(int i = 0; i< block; i++) { if( sgn(buffer[i]-lastval) != lastdirection) { directionchanges++; lastdirection = sgn(buffer[i] - lastval); } lastval = buffer[i]; } len -= block; s += block; } delete [] buffer; return (double)directionchanges/originalLen; }
double VoiceKey::TestDirectionChanges( const WaveTrack & t, sampleCount start, sampleCount len) { auto s = start; //Keep track of start auto originalLen = len; //Keep track of the length of block to process (its not the length of t) const auto blockSize = limitSampleBufferSize( t.GetMaxBlockSize(), len); //Determine size of sampling buffer unsigned long directionchanges = 1; float lastval=float(0); int lastdirection=1; Floats buffer{ blockSize }; //Get a sampling buffer while(len > 0) { //Figure out how much to grab auto block = limitSampleBufferSize ( t.GetBestBlockSize(s), len ); t.Get((samplePtr)buffer.get(), floatSample, s, block); //grab the block; if (len == originalLen) { //The first time through, set stuff up special. lastval = buffer[0]; } //Now, go through the block and calculate zero crossings for(decltype(block) i = 0; i< block; i++){ if( sgn(buffer[i]-lastval) != lastdirection) { directionchanges++; lastdirection = sgn(buffer[i] - lastval); } lastval = buffer[i]; } len -= block; s += block; } return (double)directionchanges/originalLen.as_double(); }
double VoiceKey::TestSignChanges(WaveTrack & t, sampleCount start, sampleCount len) { auto s = start; //Keep track of start auto originalLen = len; //Keep track of the length of block to process (its not the length of t) const auto blockSize = limitSampleBufferSize( t.GetMaxBlockSize(), len); //Determine size of sampling buffer unsigned long signchanges = 1; int currentsign=0; float *buffer = new float[blockSize]; //Get a sampling buffer while(len > 0) { //Figure out how much to grab auto block = limitSampleBufferSize ( t.GetBestBlockSize(s), len ); t.Get((samplePtr)buffer,floatSample, s,block); //grab the block; if (len == originalLen) { //The first time through, set stuff up special. currentsign = sgn(buffer[0]); } //Now, go through the block and calculate zero crossings for(decltype(block) i = 0; i< block; i++) { if( sgn(buffer[i]) != currentsign) { currentsign = sgn(buffer[i]); signchanges++; } } len -= block; s += block; } delete [] buffer; return (double)signchanges / originalLen.as_double(); }
bool EffectToneGen::Process() { if (length <= 0.0) length = sDefaultGenerateLen; //Iterate over each track TrackListIterator iter(mWaveTracks); WaveTrack *track = (WaveTrack *)iter.First(); while (track) { mSample = 0; WaveTrack *tmp = mFactory->NewWaveTrack(track->GetSampleFormat()); mCurRate = track->GetRate(); tmp->SetRate(mCurRate); longSampleCount numSamples = (longSampleCount)(length * mCurRate + 0.5); longSampleCount i = 0; float *data = new float[tmp->GetMaxBlockSize()]; sampleCount block; while(i < numSamples) { block = tmp->GetBestBlockSize(i); if (block > (numSamples - i)) block = numSamples - i; MakeTone(data, block); tmp->Append((samplePtr)data, floatSample, block); i += block; } delete[] data; tmp->Flush(); track->Clear(mT0, mT1); track->Paste(mT0, tmp); delete tmp; //Iterate to the next track track = (WaveTrack *)iter.Next(); } mT1 = mT0 + length; // Update selection. return true; }
bool EffectNoise::Process() { if (noiseDuration <= 0.0) noiseDuration = sDefaultGenerateLen; //Iterate over each track int ntrack = 0; this->CopyInputWaveTracks(); // Set up mOutputWaveTracks. bool bGoodResult = true; TrackListIterator iter(mOutputWaveTracks); WaveTrack *track = (WaveTrack *)iter.First(); while (track) { WaveTrack *tmp = mFactory->NewWaveTrack(track->GetSampleFormat(), track->GetRate()); numSamples = (longSampleCount)(noiseDuration * track->GetRate() + 0.5); longSampleCount i = 0; float *data = new float[tmp->GetMaxBlockSize()]; sampleCount block; while ((i < numSamples) && bGoodResult) { block = tmp->GetBestBlockSize(i); if (block > (numSamples - i)) block = numSamples - i; MakeNoise(data, block, track->GetRate(), noiseAmplitude); tmp->Append((samplePtr)data, floatSample, block); i += block; //Update the Progress meter if (TrackProgress(ntrack, (double)i / numSamples)) bGoodResult = false; } delete[] data; tmp->Flush(); track->Clear(mT0, mT1); track->Paste(mT0, tmp); delete tmp; if (!bGoodResult) break; //Iterate to the next track ntrack++; track = (WaveTrack *)iter.Next(); } if (bGoodResult) { /* save last used values save duration unless value was got from selection, so we save only when user explicitely setup a value */ if (mT1 == mT0) gPrefs->Write(wxT("/CsPresets/NoiseGen_Duration"), noiseDuration); gPrefs->Write(wxT("/CsPresets/NoiseGen_Type"), noiseType); gPrefs->Write(wxT("/CsPresets/NoiseGen_Amp"), noiseAmplitude); mT1 = mT0 + noiseDuration; // Update selection. } this->ReplaceProcessedWaveTracks(bGoodResult); return bGoodResult; }
bool EffectDtmf::Process() { if (dtmfDuration <= 0.0) return false; //Iterate over each track TrackListIterator iter(mWaveTracks); WaveTrack *track = (WaveTrack *)iter.First(); while (track) { // new tmp track, to fill with dtmf sequence // we will build the track by adding a tone, then a silence, next tone, and so on... WaveTrack *tmp = mFactory->NewWaveTrack(track->GetSampleFormat(), track->GetRate()); // all dtmf sequence durations in samples from seconds numSamplesSequence = (longSampleCount)(dtmfDuration * track->GetRate() + 0.5); numSamplesTone = (longSampleCount)(dtmfTone * track->GetRate() + 0.5); numSamplesSilence = (longSampleCount)(dtmfSilence * track->GetRate() + 0.5); // recalculate the sum, and spread the difference - due to approximations. // Since diff should be in the order of "some" samples, a division (resulting in zero) // is not sufficient, so we add the additional remaining samples in each tone/silence block, // at least until available. int diff = numSamplesSequence - (dtmfNTones*numSamplesTone) - (dtmfNTones-1)*numSamplesSilence; if (diff>dtmfNTones) { // in this case, both these values would change, so it makes sense to recalculate diff // otherwise just keep the value we already have // should always be the case that dtmfNTones>1, as if 0, we don't even start processing, // and with 1 there is no difference to spread (no silence slot)... wxASSERT(dtmfNTones > 1); numSamplesTone += (diff/(dtmfNTones)); numSamplesSilence += (diff/(dtmfNTones-1)); diff = numSamplesSequence - (dtmfNTones*numSamplesTone) - (dtmfNTones-1)*numSamplesSilence; } // this var will be used as extra samples distributor int extra=0; longSampleCount i = 0; longSampleCount j = 0; int n=0; // pointer to string in dtmfString sampleCount block; bool isTone = true; float *data = new float[tmp->GetMaxBlockSize()]; // for the whole dtmf sequence, we will be generating either tone or silence // according to a bool value, and this might be done in small chunks of size // 'block', as a single tone might sometimes be larger than the block // tone and silence generally have different duration, thus two generation blocks // // Note: to overcome a 'clicking' noise introduced by the abrupt transition from/to // silence, I added a fade in/out of 1/250th of a second (4ms). This can still be // tweaked but gives excellent results at 44.1kHz: I haven't tried other freqs. // A problem might be if the tone duration is very short (<10ms)... (?) // // One more problem is to deal with the approximations done when calculating the duration // of both tone and silence: in some cases the final sum might not be same as the initial // duration. So, to overcome this, we had a redistribution block up, and now we will spread // the remaining samples in every bin in order to achieve the full duration: test case was // to generate an 11 tone DTMF sequence, in 4 seconds, and with DutyCycle=75%: after generation // you ended up with 3.999s or in other units: 3 seconds and 44097 samples. // while(i < numSamplesSequence) { if (isTone) // generate tone { // the statement takes care of extracting one sample from the diff bin and // adding it into the tone block until depletion extra=(diff-- > 0?1:0); for(j=0; j < numSamplesTone+extra; j+=block) { block = tmp->GetBestBlockSize(j); if (block > (numSamplesTone+extra - j)) block = numSamplesTone+extra - j; // generate the tone and append MakeDtmfTone(data, block, track->GetRate(), dtmfString[n], j, numSamplesTone); tmp->Append((samplePtr)data, floatSample, block); } i += numSamplesTone; n++; if(n>=dtmfNTones)break; } else // generate silence { // the statement takes care of extracting one sample from the diff bin and // adding it into the silence block until depletion extra=(diff-- > 0?1:0); for(j=0; j < numSamplesSilence+extra; j+=block) { block = tmp->GetBestBlockSize(j); if (block > (numSamplesSilence+extra - j)) block = numSamplesSilence+extra - j; // generate silence and append memset(data, 0, sizeof(float)*block); tmp->Append((samplePtr)data, floatSample, block); } i += numSamplesSilence; } // flip flag isTone=!isTone; } // finished the whole dtmf sequence delete[] data; tmp->Flush(); track->Clear(mT0, mT1); track->Paste(mT0, tmp); delete tmp; //Iterate to the next track track = (WaveTrack *)iter.Next(); } /* save last used values save duration unless value was got from selection, so we save only when user explicitely setup a value */ if (mT1 == mT0) gPrefs->Write(wxT("/CsPresets/DtmfGen_SequenceDuration"), dtmfDuration); gPrefs->Write(wxT("/CsPresets/DtmfGen_String"), dtmfString); gPrefs->Write(wxT("/CsPresets/DtmfGen_DutyCycle"), dtmfDutyCycle); // Update selection: this is not accurate if my calculations are wrong. // To validate, once the effect is done, unselect, and select all, then // see what the selection length is being reported (in sec,ms,samples) mT1 = mT0 + dtmfDuration; return true; }