size_t EffectBassTreble::InstanceProcess(EffectBassTrebleState & data, float **inBlock, float **outBlock, size_t blockLen) { float *ibuf = inBlock[0]; float *obuf = outBlock[0]; // Set value to ensure correct rounding double oldBass = DB_TO_LINEAR(mBass); double oldTreble = DB_TO_LINEAR(mTreble); data.gain = DB_TO_LINEAR(mGain); // Compute coefficents of the low shelf biquand IIR filter if (data.bass != oldBass) Coefficents(data.hzBass, data.slope, mBass, data.samplerate, kBass, data.a0Bass, data.a1Bass, data.a2Bass, data.b0Bass, data.b1Bass, data.b2Bass); // Compute coefficents of the high shelf biquand IIR filter if (data.treble != oldTreble) Coefficents(data.hzTreble, data.slope, mTreble, data.samplerate, kTreble, data.a0Treble, data.a1Treble, data.a2Treble, data.b0Treble, data.b1Treble, data.b2Treble); for (decltype(blockLen) i = 0; i < blockLen; i++) { obuf[i] = DoFilter(data, ibuf[i]) * data.gain; } return blockLen; }
bool EffectCompressor::NewTrackPass1() { mThreshold = DB_TO_LINEAR(mThresholdDB); mNoiseFloor = DB_TO_LINEAR(mNoiseFloorDB); mNoiseCounter = 100; mAttackInverseFactor = exp(log(mThreshold) / (mCurRate * mAttackTime + 0.5)); mAttackFactor = 1.0 / mAttackInverseFactor; mDecayFactor = exp(log(mThreshold) / (mCurRate * mDecayTime + 0.5)); if(mRatio > 1) mCompression = 1.0-1.0/mRatio; else mCompression = 0.0; mLastLevel = mThreshold; if (mCircle) delete[] mCircle; mCircleSize = 100; mCircle = new double[mCircleSize]; for(int j=0; j<mCircleSize; j++) { mCircle[j] = 0.0; } mCirclePos = 0; mRMSSum = 0.0; return true; }
void EffectDistortion::Leveller() { double noiseFloor = DB_TO_LINEAR(mParams.mNoiseFloor); int numPasses = mParams.mRepeats; double fractionalPass = mParams.mParam1 / 100.0; const int numPoints = 6; const double gainFactors[numPoints] = { 0.80, 1.00, 1.20, 1.20, 1.00, 0.80 }; double gainLimits[numPoints] = { 0.0001, 0.0, 0.1, 0.3, 0.5, 1.0 }; double addOnValues[numPoints]; gainLimits[1] = noiseFloor; /* In the original Leveller effect, behaviour was undefined for threshold > 20 dB. * If we want to support > 20 dB we need to scale the points to keep them non-decreasing. * * if (noiseFloor > gainLimits[2]) { * for (int i = 3; i < numPoints; i++) { * gainLimits[i] = noiseFloor + ((1 - noiseFloor)*((gainLimits[i] - 0.1) / 0.9)); * } * gainLimits[2] = noiseFloor; * } */ // Calculate add-on values addOnValues[0] = 0.0; for (int i = 0; i < numPoints-1; i++) { addOnValues[i+1] = addOnValues[i] + (gainLimits[i] * (gainFactors[i] - gainFactors[1 + i])); } // Positive half of table. // The original effect increased the 'strength' of the effect by // repeated passes over the audio data. // Here we model that more efficiently by repeated passes over a linear table. for (int n = STEPS; n < TABLESIZE; n++) { mTable[n] = ((double) (n - STEPS) / (double) STEPS); for (int i = 0; i < numPasses; i++) { // Find the highest index for gain adjustment int index = numPoints - 1; for (int i = index; i >= 0 && mTable[n] < gainLimits[i]; i--) { index = i; } // the whole number of 'repeats' mTable[n] = (mTable[n] * gainFactors[index]) + addOnValues[index]; } // Extrapolate for fine adjustment. // tiny fractions are not worth the processing time if (fractionalPass > 0.001) { int index = numPoints - 1; for (int i = index; i >= 0 && mTable[n] < gainLimits[i]; i--) { index = i; } mTable[n] += fractionalPass * ((mTable[n] * (gainFactors[index] - 1)) + addOnValues[index]); } } CopyHalfTable(); }
EffectAmplify::EffectAmplify() { mAmp = DEF_Amp; mRatio = DB_TO_LINEAR(mAmp); mRatioClip = 0.0; mCanClip = false; mPeak = 0.0; SetLinearEffectFlag(true); }
bool EffectDistortion::TransferDataFromWindow() { if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow()) { return false; } mThreshold = DB_TO_LINEAR(mParams.mThreshold_dB); return true; }
void EffectAmplify::OnAmpSlider(wxCommandEvent & evt) { double dB = evt.GetInt() / SCL_Amp; mRatio = DB_TO_LINEAR(TrapDouble(dB, MIN_Amp, MAX_Amp)); double dB2 = (evt.GetInt() - 1) / SCL_Amp; double ratio2 = DB_TO_LINEAR(TrapDouble(dB2, MIN_Amp, MAX_Amp)); if (!mClip->GetValue() && mRatio * mPeak > 1.0 && ratio2 * mPeak < 1.0) { mRatio = 1.0 / mPeak; } mAmp = LINEAR_TO_DB(mRatio); mAmpT->GetValidator()->TransferToWindow(); mNewPeak = LINEAR_TO_DB(mRatio * mPeak); mNewPeakT->GetValidator()->TransferToWindow(); CheckClip(); }
void EffectDistortion::ExponentialTable() { double amount = std::min(0.999, DB_TO_LINEAR(-1 * mParams.mParam1)); // avoid divide by zero for (int n = STEPS; n < TABLESIZE; n++) { double linVal = n/(float)STEPS; double scale = -1.0 / (1.0 - amount); // unity gain at 0dB double curve = std::exp((linVal - 1) * std::log(amount)); mTable[n] = scale * (curve -1); } CopyHalfTable(); }
size_t EffectPhaser::InstanceProcess(EffectPhaserState & data, float **inBlock, float **outBlock, size_t blockLen) { float *ibuf = inBlock[0]; float *obuf = outBlock[0]; for (int j = data.laststages; j < mStages; j++) { data.old[j] = 0; } data.laststages = mStages; data.lfoskip = mFreq * 2 * M_PI / data.samplerate; data.phase = mPhase * M_PI / 180; data.outgain = DB_TO_LINEAR(mOutGain); for (decltype(blockLen) i = 0; i < blockLen; i++) { double in = ibuf[i]; double m = in + data.fbout * mFeedback / 101; // Feedback must be less than 100% to avoid infinite gain. if (((data.skipcount++) % lfoskipsamples) == 0) { //compute sine between 0 and 1 data.gain = (1.0 + cos(data.skipcount.as_double() * data.lfoskip + data.phase)) / 2.0; // change lfo shape data.gain = expm1(data.gain * phaserlfoshape) / expm1(phaserlfoshape); // attenuate the lfo data.gain = 1.0 - data.gain / 255.0 * mDepth; } // phasing routine for (int j = 0; j < mStages; j++) { double tmp = data.old[j]; data.old[j] = data.gain * tmp + m; m = tmp - data.gain * data.old[j]; } data.fbout = m; obuf[i] = (float) (data.outgain * (m * mDryWet + in * (255 - mDryWet)) / 255); } return blockLen; }
void EffectAmplify::OnPeakText(wxCommandEvent & WXUNUSED(evt)) { if (!mNewPeakT->GetValidator()->TransferFromWindow()) { EnableApply(false); return; } if (mNewPeak == 0.0) mRatio = mRatioClip; else mRatio = DB_TO_LINEAR(mNewPeak) / mPeak; double ampInit = LINEAR_TO_DB(mRatio); mAmp = TrapDouble(ampInit, MIN_Amp, MAX_Amp); if (mAmp != ampInit) mRatio = DB_TO_LINEAR(mAmp); mAmpT->GetValidator()->TransferToWindow(); mAmpS->SetValue((int) (mAmp * SCL_Amp + 0.5f)); CheckClip(); }
bool EffectCompressor::NewTrackPass1() { mThreshold = DB_TO_LINEAR(mThresholdDB); mNoiseFloor = DB_TO_LINEAR(mNoiseFloorDB); mNoiseCounter = 100; mAttackInverseFactor = exp(log(mThreshold) / (mCurRate * mAttackTime + 0.5)); mAttackFactor = 1.0 / mAttackInverseFactor; mDecayFactor = exp(log(mThreshold) / (mCurRate * mDecayTime + 0.5)); if(mRatio > 1) mCompression = 1.0-1.0/mRatio; else mCompression = 0.0; mLastLevel = mThreshold; mCircleSize = 100; mCircle.reinit( mCircleSize, true ); mCirclePos = 0; mRMSSum = 0.0; return true; }
static void gst_rg_volume_update_gain (GstRgVolume * self) { gdouble target_gain, result_gain, result_volume; gboolean target_gain_changed, result_gain_changed; gst_rg_volume_determine_gain (self, &target_gain, &result_gain); result_volume = DB_TO_LINEAR (result_gain); /* Ensure that the result volume is within the range that the volume element * can handle. Currently, the limit is 10. (+20 dB), which should not be * restrictive. */ if (G_UNLIKELY (result_volume > self->max_volume)) { GST_INFO_OBJECT (self, "cannot handle result gain of %" GAIN_FORMAT " (%0.6f), adjusting", result_gain, result_volume); result_volume = self->max_volume; result_gain = LINEAR_TO_DB (result_volume); } /* Direct comparison is OK in this case. */ if (target_gain == result_gain) { GST_INFO_OBJECT (self, "result gain is %" GAIN_FORMAT " (%0.6f), matching target", result_gain, result_volume); } else { GST_INFO_OBJECT (self, "result gain is %" GAIN_FORMAT " (%0.6f), target is %" GAIN_FORMAT, result_gain, result_volume, target_gain); } target_gain_changed = (self->target_gain != target_gain); result_gain_changed = (self->result_gain != result_gain); self->target_gain = target_gain; self->result_gain = result_gain; g_object_set (self->volume_element, "volume", result_volume, NULL); if (target_gain_changed) g_object_notify ((GObject *) self, "target-gain"); if (result_gain_changed) g_object_notify ((GObject *) self, "result-gain"); }
bool EffectDistortion::LoadFactoryPreset(int id) { if (id < 0 || id >= (int) WXSIZEOF(FactoryPresets)) { return false; } mParams = FactoryPresets[id].params; mThreshold = DB_TO_LINEAR(mParams.mThreshold_dB); if (mUIDialog) { TransferDataToWindow(); } return true; }
size_t EffectWahwah::InstanceProcess(EffectWahwahState & data, float **inBlock, float **outBlock, size_t blockLen) { float *ibuf = inBlock[0]; float *obuf = outBlock[0]; double frequency, omega, sn, cs, alpha; double in, out; data.lfoskip = mFreq * 2 * M_PI / data.samplerate; data.depth = mDepth / 100.0; data.freqofs = mFreqOfs / 100.0; data.phase = mPhase * M_PI / 180.0; data.outgain = DB_TO_LINEAR(mOutGain); for (decltype(blockLen) i = 0; i < blockLen; i++) { in = (double) ibuf[i]; if ((data.skipcount++) % lfoskipsamples == 0) { frequency = (1 + cos(data.skipcount * data.lfoskip + data.phase)) / 2; frequency = frequency * data.depth * (1 - data.freqofs) + data.freqofs; frequency = exp((frequency - 1) * 6); omega = M_PI * frequency; sn = sin(omega); cs = cos(omega); alpha = sn / (2 * mRes); data.b0 = (1 - cs) / 2; data.b1 = 1 - cs; data.b2 = (1 - cs) / 2; data.a0 = 1 + alpha; data.a1 = -2 * cs; data.a2 = 1 - alpha; }; out = (data.b0 * in + data.b1 * data.xn1 + data.b2 * data.xn2 - data.a1 * data.yn1 - data.a2 * data.yn2) / data.a0; data.xn2 = data.xn1; data.xn1 = in; data.yn2 = data.yn1; data.yn1 = out; out *= data.outgain; obuf[i] = (float) out; } return blockLen; }
AUDMAudioFilterNormalize::AUDMAudioFilterNormalize(AUDMAudioFilter * instream,GAINparam *param):AUDMAudioFilter (instream) { float db_out; // nothing special here... switch(param->mode) { case ADM_NO_GAIN: _ratio=1;_scanned=1;printf("[Gain] Gain of 1.0\n");break; case ADM_GAIN_AUTOMATIC: _ratio=1;_scanned=0;printf("[Gain] Automatic gain\n");break; case ADM_GAIN_MANUAL: _scanned=1; db_out = param->gain10/10.0; // Dbout is in 10*DB (!) _ratio = DB_TO_LINEAR(db_out); printf("[Gain] %f db (p=%d)\n", (float)(param->gain10)/10.,param->gain10); printf("[Gain] Linear ratio of : %03.3f\n", _ratio); } _previous->rewind(); };
void EffectAmplify::OnAmpText(wxCommandEvent & WXUNUSED(evt)) { if (!mAmpT->GetValidator()->TransferFromWindow()) { EnableApply(false); return; } mRatio = DB_TO_LINEAR(TrapDouble(mAmp * SCL_Amp, MIN_Amp * SCL_Amp, MAX_Amp * SCL_Amp) / SCL_Amp); mAmpS->SetValue((int) (LINEAR_TO_DB(mRatio) * SCL_Amp + 0.5)); mNewPeak = LINEAR_TO_DB(mRatio * mPeak); mNewPeakT->GetValidator()->TransferToWindow(); CheckClip(); }
bool EffectAmplify::TransferDataFromWindow() { if (!mUIParent->Validate() || !mUIParent->TransferDataFromWindow()) { return false; } mRatio = DB_TO_LINEAR(TrapDouble(mAmp * SCL_Amp, MIN_Amp * SCL_Amp, MAX_Amp * SCL_Amp) / SCL_Amp); mCanClip = mClip->GetValue(); if (!mCanClip && mRatio * mPeak > 1.0) { mRatio = 1.0 / mPeak; } return true; }
bool SetTrackAudioCommand::ApplyInner(const CommandContext & context, Track * t ) { static_cast<void>(context); auto wt = dynamic_cast<WaveTrack *>(t); auto pt = dynamic_cast<PlayableTrack *>(t); if( wt && bHasGain ) wt->SetGain(DB_TO_LINEAR(mGain)); if( wt && bHasPan ) wt->SetPan(mPan/100.0); // These ones don't make sense on the second channel of a stereo track. if( !bIsSecondChannel ){ if( pt && bHasSolo ) pt->SetSolo(bSolo); if( pt && bHasMute ) pt->SetMute(bMute); } return true; }
void EffectWahwah::InstanceInit(EffectWahwahState & data, float sampleRate) { data.samplerate = sampleRate; data.lfoskip = mFreq * 2 * M_PI / sampleRate; data.skipcount = 0; data.xn1 = 0; data.xn2 = 0; data.yn1 = 0; data.yn2 = 0; data.b0 = 0; data.b1 = 0; data.b2 = 0; data.a0 = 0; data.a1 = 0; data.a2 = 0; data.depth = mDepth / 100.0; data.freqofs = mFreqOfs / 100.0; data.phase = mPhase * M_PI / 180.0; data.outgain = DB_TO_LINEAR(mOutGain); }
bool EffectAmplify::TransferDataToWindow() { // limit range of gain double dBInit = LINEAR_TO_DB(mRatio); double dB = TrapDouble(dBInit, MIN_Amp, MAX_Amp); if (dB != dBInit) mRatio = DB_TO_LINEAR(dB); mAmp = LINEAR_TO_DB(mRatio); mAmpT->GetValidator()->TransferToWindow(); mAmpS->SetValue((int) (mAmp * SCL_Amp + 0.5f)); mNewPeak = LINEAR_TO_DB(mRatio * mPeak); mNewPeakT->GetValidator()->TransferToWindow(); mClip->SetValue(mCanClip); CheckClip(); return true; }
EffectDistortion::EffectDistortion() { wxASSERT(kNumTableTypes == WXSIZEOF(kTableTypeStrings)); mParams.mTableChoiceIndx = DEF_TableTypeIndx; mParams.mDCBlock = DEF_DCBlock; mParams.mThreshold_dB = DEF_Threshold_dB; mThreshold = DB_TO_LINEAR(mParams.mThreshold_dB); mParams.mNoiseFloor = DEF_NoiseFloor; mParams.mParam1 = DEF_Param1; mParams.mParam2 = DEF_Param2; mParams.mRepeats = DEF_Repeats; mMakeupGain = 1.0; mbSavedFilterState = DEF_DCBlock; for (int i = 0; i < kNumTableTypes; i++) { mTableTypes.Add(wxGetTranslation(kTableTypeStrings[i])); } SetLinearEffectFlag(false); }
void EffectBassTreble::InstanceInit(EffectBassTrebleState & data, float sampleRate) { data.samplerate = sampleRate; data.slope = 0.4f; // same slope for both filters data.hzBass = 250.0f; // could be tunable in a more advanced version data.hzTreble = 4000.0f; // could be tunable in a more advanced version data.a0Bass = 1; data.a1Bass = 0; data.a2Bass = 0; data.b0Bass = 0; data.b1Bass = 0; data.b2Bass = 0; data.a0Treble = 1; data.a1Treble = 0; data.a2Treble = 0; data.b0Treble = 0; data.b1Treble = 0; data.b2Treble = 0; data.xn1Bass = 0; data.xn2Bass = 0; data.yn1Bass = 0; data.yn2Bass = 0; data.xn1Treble = 0; data.xn2Treble = 0; data.yn1Treble = 0; data.yn2Treble = 0; data.bass = -1; data.treble = -1; data.gain = DB_TO_LINEAR(mGain); }
// // For normalize, we scan the input stream // to check for maximum value //___________________________________________ uint8_t AUDMAudioFilterNormalize::preprocess(void) { int16_t *ptr; uint32_t scanned = 0, ch = 0; AUD_Status status; _ratio = 0; uint32_t percent=0; uint32_t current=0,llength=0; float max[_wavHeader.channels]; _previous->rewind(); DolbySkip(1); printf("\n Seeking for maximum value, that can take a while\n"); llength=_length ; for(int i=0;i<_wavHeader.channels;i++) max[i]=0; while (1) { int ready=_previous->fill(AUD_PROCESS_BUFFER_SIZE>>2,_incomingBuffer,&status); if(!ready) { if(status==AUD_END_OF_STREAM) { break; } else { printf("Unknown cause : %d\n",status); ADM_assert(0); } } ADM_assert(!(ready %_wavHeader.channels)); int index=0; float current; // printf("*\n"); int sample= ready /_wavHeader.channels; for(int j=0;j<sample;j++) for(int chan=0;chan<_wavHeader.channels;chan++) { current=fabs(_incomingBuffer[index++]); if(current>max[chan]) max[chan]=current; } scanned+=ready; } _previous->rewind(); float mx=0; for(int chan=0;chan<_wavHeader.channels;chan++) { if(max[chan]>mx) mx=max[chan]; printf("[Normalize] maximum found for channel %d : %f\n", chan,max[chan]); } printf("[Normalize] Using : %0.4f as max value \n", mx); double db_in, db_out=-3; if (mx>0.001) db_in = LINEAR_TO_DB(mx); else db_in = -20; // We consider -20 DB to be noise printf("--> %2.2f db / %2.2f \n", db_in, db_out); // search ratio _ratio=1; float db_delta=db_out-db_in; printf("[Normalize]Gain %f dB\n",db_delta); _ratio = DB_TO_LINEAR(db_delta); printf("\n Using ratio of : %f\n", _ratio); _scanned = 1; DolbySkip(0); _previous->rewind(); return 1; }
// this currently does an exponential fade bool EffectAutoDuck::ApplyDuckFade(int trackNumber, WaveTrack* t, double t0, double t1) { bool cancel = false; sampleCount start = t->TimeToLongSamples(t0); sampleCount end = t->TimeToLongSamples(t1); float *buf = new float[kBufSize]; sampleCount pos = start; int fadeDownSamples = t->TimeToLongSamples( mOuterFadeDownLen + mInnerFadeDownLen); if (fadeDownSamples < 1) fadeDownSamples = 1; int fadeUpSamples = t->TimeToLongSamples( mOuterFadeUpLen + mInnerFadeUpLen); if (fadeUpSamples < 1) fadeUpSamples = 1; float fadeDownStep = mDuckAmountDb / fadeDownSamples; float fadeUpStep = mDuckAmountDb / fadeUpSamples; while (pos < end) { sampleCount len = end - pos; if (len > kBufSize) len = kBufSize; t->Get((samplePtr)buf, floatSample, pos, len); for (sampleCount i = pos; i < pos + len; i++) { float gainDown = fadeDownStep * (i - start); float gainUp = fadeUpStep * (end - i);; float gain; if (gainDown > gainUp) gain = gainDown; else gain = gainUp; if (gain < mDuckAmountDb) gain = mDuckAmountDb; buf[i - pos] *= DB_TO_LINEAR(gain); } t->Set((samplePtr)buf, floatSample, pos, len); pos += len; float curTime = t->LongSamplesToTime(pos); float fractionFinished = (curTime - mT0) / (mT1 - mT0); if (TotalProgress( (trackNumber + 1 + fractionFinished) / (GetNumWaveTracks() + 1) )) { cancel = true; break; } } delete[] buf; return cancel; }
bool EffectAutoDuck::Process() { sampleCount i; if (GetNumWaveTracks() == 0 || !mControlTrack) return false; bool cancel = false; sampleCount start = mControlTrack->TimeToLongSamples(mT0 + mOuterFadeDownLen); sampleCount end = mControlTrack->TimeToLongSamples(mT1 - mOuterFadeUpLen); if (end <= start) return false; // the minimum number of samples we have to wait until the maximum // pause has been exceeded double maxPause = mMaximumPause; // We don't fade in until we have time enough to actually fade out again if (maxPause < mOuterFadeDownLen + mOuterFadeUpLen) maxPause = mOuterFadeDownLen + mOuterFadeUpLen; sampleCount minSamplesPause = mControlTrack->TimeToLongSamples(maxPause); double threshold = DB_TO_LINEAR(mThresholdDb); // adjust the threshold so we can compare it to the rmsSum value threshold = threshold * threshold * kRMSWindowSize; int rmsPos = 0; float rmsSum = 0; float *rmsWindow = new float[kRMSWindowSize]; for (i = 0; i < kRMSWindowSize; i++) rmsWindow[i] = 0; float *buf = new float[kBufSize]; bool inDuckRegion = false; // initialize the following two variables to prevent compiler warning double duckRegionStart = 0; sampleCount curSamplesPause = 0; // to make the progress bar appear more natural, we first look for all // duck regions and apply them all at once afterwards AutoDuckRegionArray regions; sampleCount pos = start; while (pos < end) { sampleCount len = end - pos; if (len > kBufSize) len = kBufSize; mControlTrack->Get((samplePtr)buf, floatSample, pos, (sampleCount)len); for (i = pos; i < pos + len; i++) { rmsSum -= rmsWindow[rmsPos]; rmsWindow[rmsPos] = buf[i - pos] * buf[i - pos]; rmsSum += rmsWindow[rmsPos]; rmsPos = (rmsPos + 1) % kRMSWindowSize; bool thresholdExceeded = rmsSum > threshold; if (thresholdExceeded) { // everytime the threshold is exceeded, reset our count for // the number of pause samples curSamplesPause = 0; if (!inDuckRegion) { // the threshold has been exceeded for the first time, so // let the duck region begin here inDuckRegion = true; duckRegionStart = mControlTrack->LongSamplesToTime(i); } } if (!thresholdExceeded && inDuckRegion) { // the threshold has not been exceeded and we are in a duck // region, but only fade in if the maximum pause has been // exceeded curSamplesPause += 1; if (curSamplesPause >= minSamplesPause) { // do the actual duck fade and reset all values double duckRegionEnd = mControlTrack->LongSamplesToTime(i - curSamplesPause); regions.Add(AutoDuckRegion( duckRegionStart - mOuterFadeDownLen, duckRegionEnd + mOuterFadeUpLen)); inDuckRegion = false; } } } pos += len; if (TotalProgress( ((double)(pos-start)) / (end-start) / (GetNumWaveTracks() + 1) )) { cancel = true; break; } } // apply last duck fade, if any if (inDuckRegion) { double duckRegionEnd = mControlTrack->LongSamplesToTime(end - curSamplesPause); regions.Add(AutoDuckRegion( duckRegionStart - mOuterFadeDownLen, duckRegionEnd + mOuterFadeUpLen)); } delete[] buf; delete[] rmsWindow; if (!cancel) { CopyInputTracks(); // Set up mOutputTracks. SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks); Track *iterTrack = iter.First(); int trackNumber = 0; while (iterTrack) { wxASSERT(iterTrack->GetKind() == Track::Wave); WaveTrack* t = (WaveTrack*)iterTrack; for (i = 0; i < (int)regions.GetCount(); i++) { const AutoDuckRegion& region = regions[i]; if (ApplyDuckFade(trackNumber, t, region.t0, region.t1)) { cancel = true; break; } } if (cancel) break; iterTrack = iter.Next(); trackNumber++; } } ReplaceProcessedTracks(!cancel); return !cancel; }
void EffectDistortion::PopulateOrExchange(ShuttleGui & S) { S.AddSpace(0, 5); S.StartVerticalLay(); { S.StartMultiColumn(4, wxCENTER); { mTypeChoiceCtrl = S.Id(ID_Type).AddChoice(_("Distortion type:"), wxT(""), &mTableTypes); mTypeChoiceCtrl->SetValidator(wxGenericValidator(&mParams.mTableChoiceIndx)); S.SetSizeHints(-1, -1); mDCBlockCheckBox = S.Id(ID_DCBlock).AddCheckBox(_("DC blocking filter"), DEF_DCBlock ? wxT("true") : wxT("false")); } S.EndMultiColumn(); S.AddSpace(0, 10); S.StartStatic(_("Threshold controls")); { S.StartMultiColumn(4, wxEXPAND); S.SetStretchyCol(2); { // Allow space for first Column S.AddSpace(250,0); S.AddSpace(0,0); S.AddSpace(0,0); S.AddSpace(0,0); // Upper threshold control mThresholdTxt = S.AddVariableText(defaultLabel[0], false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT); FloatingPointValidator<double> vldThreshold(2, &mParams.mThreshold_dB); vldThreshold.SetRange(MIN_Threshold_dB, MAX_Threshold_dB); mThresholdT = S.Id(ID_Threshold).AddTextBox(wxT(""), wxT(""), 10); mThresholdT->SetName(defaultLabel[0]); mThresholdT->SetValidator(vldThreshold); S.SetStyle(wxSL_HORIZONTAL); double maxLin = DB_TO_LINEAR(MAX_Threshold_dB) * SCL_Threshold_dB; double minLin = DB_TO_LINEAR(MIN_Threshold_dB) * SCL_Threshold_dB; mThresholdS = S.Id(ID_Threshold).AddSlider(wxT(""), 0, maxLin, minLin); mThresholdS->SetName(defaultLabel[0]); S.AddSpace(20, 0); // Noise floor control mNoiseFloorTxt = S.AddVariableText(defaultLabel[1], false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT); FloatingPointValidator<double> vldfloor(2, &mParams.mNoiseFloor); vldfloor.SetRange(MIN_NoiseFloor, MAX_NoiseFloor); mNoiseFloorT = S.Id(ID_NoiseFloor).AddTextBox(wxT(""), wxT(""), 10); mNoiseFloorT->SetName(defaultLabel[1]); mNoiseFloorT->SetValidator(vldfloor); S.SetStyle(wxSL_HORIZONTAL); mNoiseFloorS = S.Id(ID_NoiseFloor).AddSlider(wxT(""), 0, MAX_NoiseFloor, MIN_NoiseFloor); mNoiseFloorS->SetName(defaultLabel[1]); S.AddSpace(20, 0); } S.EndMultiColumn(); } S.EndStatic(); S.StartStatic(_("Parameter controls")); { S.StartMultiColumn(4, wxEXPAND); S.SetStretchyCol(2); { // Allow space for first Column S.AddSpace(250,0); S.AddSpace(0,0); S.AddSpace(0,0); S.AddSpace(0,0); // Parameter1 control mParam1Txt = S.AddVariableText(defaultLabel[2], false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT); FloatingPointValidator<double> vldparam1(2, &mParams.mParam1); vldparam1.SetRange(MIN_Param1, MAX_Param1); mParam1T = S.Id(ID_Param1).AddTextBox(wxT(""), wxT(""), 10); mParam1T->SetName(defaultLabel[2]); mParam1T->SetValidator(vldparam1); S.SetStyle(wxSL_HORIZONTAL); mParam1S = S.Id(ID_Param1).AddSlider(wxT(""), 0, MAX_Param1, MIN_Param1); mParam1S->SetName(defaultLabel[2]); S.AddSpace(20, 0); // Parameter2 control mParam2Txt = S.AddVariableText(defaultLabel[3], false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT); FloatingPointValidator<double> vldParam2(2, &mParams.mParam2); vldParam2.SetRange(MIN_Param2, MAX_Param2); mParam2T = S.Id(ID_Param2).AddTextBox(wxT(""), wxT(""), 10); mParam2T->SetName(defaultLabel[3]); mParam2T->SetValidator(vldParam2); S.SetStyle(wxSL_HORIZONTAL); mParam2S = S.Id(ID_Param2).AddSlider(wxT(""), 0, MAX_Param2, MIN_Param2); mParam2S->SetName(defaultLabel[3]); S.AddSpace(20, 0); // Repeats control mRepeatsTxt = S.AddVariableText(defaultLabel[4], false, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT); IntegerValidator<int>vldRepeats(&mParams.mRepeats); vldRepeats.SetRange(MIN_Repeats, MAX_Repeats); mRepeatsT = S.Id(ID_Repeats).AddTextBox(wxT(""), wxT(""), 10); mRepeatsT->SetName(defaultLabel[4]); mRepeatsT->SetValidator(vldRepeats); S.SetStyle(wxSL_HORIZONTAL); mRepeatsS = S.Id(ID_Repeats).AddSlider(wxT(""), DEF_Repeats, MAX_Repeats, MIN_Repeats); mRepeatsS->SetName(defaultLabel[4]); S.AddSpace(20, 0); } S.EndMultiColumn(); } S.EndStatic(); } S.EndVerticalLay(); return; }
void EffectDistortion::OnThresholdText(wxCommandEvent& /*evt*/) { mThresholdT->GetValidator()->TransferFromWindow(); mThreshold = DB_TO_LINEAR(mParams.mThreshold_dB); mThresholdS->SetValue((int) (mThreshold * SCL_Threshold_dB + 0.5)); }
void EffectDistortion::UpdateControl(control id, bool enabled, wxString name) { wxString suffix = _(" (Not Used):"); switch (id) { case ID_Threshold: /* i18n-hint: Control range. */ if (enabled) suffix = _(" (-100 to 0 dB):"); name += suffix; // Logarithmic slider is set indirectly mThreshold = DB_TO_LINEAR(mParams.mThreshold_dB); mThresholdS->SetValue((int) (mThreshold * SCL_Threshold_dB + 0.5)); mThresholdTxt->SetLabel(name); mThresholdS->SetName(name); mThresholdT->SetName(name); mThresholdS->Enable(enabled); mThresholdT->Enable(enabled); break; case ID_NoiseFloor: /* i18n-hint: Control range. */ if (enabled) suffix = _(" (-80 to -20 dB):"); name += suffix; mNoiseFloorTxt->SetLabel(name); mNoiseFloorS->SetName(name); mNoiseFloorT->SetName(name); mNoiseFloorS->Enable(enabled); mNoiseFloorT->Enable(enabled); break; case ID_Param1: /* i18n-hint: Control range. */ if (enabled) suffix = _(" (0 to 100):"); name += suffix; mParam1Txt->SetLabel(name); mParam1S->SetName(name); mParam1T->SetName(name); mParam1S->Enable(enabled); mParam1T->Enable(enabled); break; case ID_Param2: /* i18n-hint: Control range. */ if (enabled) suffix = _(" (0 to 100):"); name += suffix; mParam2Txt->SetLabel(name); mParam2S->SetName(name); mParam2T->SetName(name); mParam2S->Enable(enabled); mParam2T->Enable(enabled); break; case ID_Repeats: /* i18n-hint: Control range. */ if (enabled) suffix = _(" (0 to 5):"); name += suffix; mRepeatsTxt->SetLabel(name); mRepeatsS->SetName(name); mRepeatsT->SetName(name); mRepeatsS->Enable(enabled); mRepeatsT->Enable(enabled); break; case ID_DCBlock: if (enabled) { mDCBlockCheckBox->SetValue(mbSavedFilterState); mParams.mDCBlock = mbSavedFilterState; } else { mDCBlockCheckBox->SetValue(false); mParams.mDCBlock = false; } mDCBlockCheckBox->Enable(enabled); break; default: break; } }
bool EffectTruncSilence::Analyze(RegionList& silenceList, RegionList& trackSilences, const WaveTrack *wt, sampleCount* silentFrame, sampleCount* index, int whichTrack, double* inputLength /*= NULL*/, double* minInputLength /*= NULL*/) { // Smallest silent region to detect in frames auto minSilenceFrames = sampleCount(std::max( mInitialAllowedSilence, DEF_MinTruncMs) * wt->GetRate()); double truncDbSilenceThreshold = DB_TO_LINEAR( mThresholdDB ); auto blockLen = wt->GetMaxBlockSize(); auto start = wt->TimeToLongSamples(mT0); auto end = wt->TimeToLongSamples(mT1); sampleCount outLength = 0; double previewLength; gPrefs->Read(wxT("/AudioIO/EffectsPreviewLen"), &previewLength, 6.0); // Minimum required length in samples. const sampleCount previewLen( previewLength * wt->GetRate() ); // Keep position in overall silences list for optimization RegionList::iterator rit(silenceList.begin()); // Allocate buffer Floats buffer{ blockLen }; // Loop through current track while (*index < end) { if (inputLength && ((outLength >= previewLen) || (*index - start > wt->TimeToLongSamples(*minInputLength)))) { *inputLength = std::min<double>(*inputLength, *minInputLength); if (outLength >= previewLen) { *minInputLength = *inputLength; } return true; } if (!inputLength) { // Show progress dialog, test for cancellation bool cancelled = TotalProgress( detectFrac * (whichTrack + (*index - start).as_double() / (end - start).as_double()) / (double)GetNumWaveTracks()); if (cancelled) return false; } // Optimization: if not in a silent region skip ahead to the next one double curTime = wt->LongSamplesToTime(*index); for ( ; rit != silenceList.end(); ++rit) { // Find the first silent region ending after current time if (rit->end >= curTime) { break; } } if (rit == silenceList.end()) { // No more regions -- no need to process the rest of the track if (inputLength) { // Add available samples up to previewLength. auto remainingTrackSamples = wt->TimeToLongSamples(wt->GetEndTime()) - *index; auto requiredTrackSamples = previewLen - outLength; outLength += (remainingTrackSamples > requiredTrackSamples)? requiredTrackSamples : remainingTrackSamples; } break; } else if (rit->start > curTime) { // End current silent region, skip ahead if (*silentFrame >= minSilenceFrames) { trackSilences.push_back(Region( wt->LongSamplesToTime(*index - *silentFrame), wt->LongSamplesToTime(*index) )); } *silentFrame = 0; auto newIndex = wt->TimeToLongSamples(rit->start); if (inputLength) { auto requiredTrackSamples = previewLen - outLength; // Add non-silent sample to outLength outLength += ((newIndex - *index) > requiredTrackSamples)? requiredTrackSamples : newIndex - *index; } *index = newIndex; } // End of optimization // Limit size of current block if we've reached the end auto count = limitSampleBufferSize( blockLen, end - *index ); // Fill buffer wt->Get((samplePtr)(buffer.get()), floatSample, *index, count); // Look for silenceList in current block for (decltype(count) i = 0; i < count; ++i) { if (inputLength && ((outLength >= previewLen) || (outLength > wt->TimeToLongSamples(*minInputLength)))) { *inputLength = wt->LongSamplesToTime(*index + i) - wt->LongSamplesToTime(start); break; } if (fabs(buffer[i]) < truncDbSilenceThreshold) { (*silentFrame)++; } else { sampleCount allowed = 0; if (*silentFrame >= minSilenceFrames) { if (inputLength) { switch (mActionIndex) { case kTruncate: outLength += wt->TimeToLongSamples(mTruncLongestAllowedSilence); break; case kCompress: allowed = wt->TimeToLongSamples(mInitialAllowedSilence); outLength += sampleCount( allowed.as_double() + (*silentFrame - allowed).as_double() * mSilenceCompressPercent / 100.0 ); break; // default: // Not currently used. } } // Record the silent region trackSilences.push_back(Region( wt->LongSamplesToTime(*index + i - *silentFrame), wt->LongSamplesToTime(*index + i) )); } else if (inputLength) { // included as part of non-silence outLength += *silentFrame; } *silentFrame = 0; if (inputLength) { ++outLength; // Add non-silent sample to outLength } } } // Next block *index += count; } if (inputLength) { *inputLength = std::min<double>(*inputLength, *minInputLength); if (outLength >= previewLen) { *minInputLength = *inputLength; } } return true; }
static double gst_opus_dec_get_r128_volume (gint16 r128_gain) { return DB_TO_LINEAR (gst_opus_dec_get_r128_gain (r128_gain)); }
bool EffectScienFilter::CalcFilter() { // Set up the coefficients in all the biquads float fNorm = mCutoff / mNyquist; if (fNorm >= 0.9999) fNorm = 0.9999F; float fC = tan (PI * fNorm / 2); float fDCPoleDistSqr = 1.0F; float fZPoleX, fZPoleY; float fZZeroX, fZZeroY; float beta = cos (fNorm*PI); switch (mFilterType) { case kButterworth: // Butterworth if ((mOrder & 1) == 0) { // Even order for (int iPair = 0; iPair < mOrder/2; iPair++) { float fSPoleX = fC * cos (PI - (iPair + 0.5) * PI / mOrder); float fSPoleY = fC * sin (PI - (iPair + 0.5) * PI / mOrder); BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY); mpBiquad[iPair].fNumerCoeffs [0] = 1; if (mFilterSubtype == kLowPass) // LOWPASS mpBiquad[iPair].fNumerCoeffs [1] = 2; else mpBiquad[iPair].fNumerCoeffs [1] = -2; mpBiquad[iPair].fNumerCoeffs [2] = 1; mpBiquad[iPair].fDenomCoeffs [0] = -2 * fZPoleX; mpBiquad[iPair].fDenomCoeffs [1] = square(fZPoleX) + square(fZPoleY); if (mFilterSubtype == kLowPass) // LOWPASS fDCPoleDistSqr *= Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY); else fDCPoleDistSqr *= Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY); // distance from Nyquist } } else { // Odd order - first do the 1st-order section float fSPoleX = -fC; float fSPoleY = 0; BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY); mpBiquad[0].fNumerCoeffs [0] = 1; if (mFilterSubtype == kLowPass) // LOWPASS mpBiquad[0].fNumerCoeffs [1] = 1; else mpBiquad[0].fNumerCoeffs [1] = -1; mpBiquad[0].fNumerCoeffs [2] = 0; mpBiquad[0].fDenomCoeffs [0] = -fZPoleX; mpBiquad[0].fDenomCoeffs [1] = 0; if (mFilterSubtype == kLowPass) // LOWPASS fDCPoleDistSqr = 1 - fZPoleX; else fDCPoleDistSqr = fZPoleX + 1; // dist from Nyquist for (int iPair = 1; iPair <= mOrder/2; iPair++) { float fSPoleX = fC * cos (PI - iPair * PI / mOrder); float fSPoleY = fC * sin (PI - iPair * PI / mOrder); BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY); mpBiquad[iPair].fNumerCoeffs [0] = 1; if (mFilterSubtype == kLowPass) // LOWPASS mpBiquad[iPair].fNumerCoeffs [1] = 2; else mpBiquad[iPair].fNumerCoeffs [1] = -2; mpBiquad[iPair].fNumerCoeffs [2] = 1; mpBiquad[iPair].fDenomCoeffs [0] = -2 * fZPoleX; mpBiquad[iPair].fDenomCoeffs [1] = square(fZPoleX) + square(fZPoleY); if (mFilterSubtype == kLowPass) // LOWPASS fDCPoleDistSqr *= Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY); else fDCPoleDistSqr *= Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY); // distance from Nyquist } } mpBiquad[0].fNumerCoeffs [0] *= fDCPoleDistSqr / (1 << mOrder); // mult by DC dist from poles, divide by dist from zeroes mpBiquad[0].fNumerCoeffs [1] *= fDCPoleDistSqr / (1 << mOrder); mpBiquad[0].fNumerCoeffs [2] *= fDCPoleDistSqr / (1 << mOrder); break; case kChebyshevTypeI: // Chebyshev Type 1 double eps; eps = sqrt (pow (10.0, wxMax(0.001, mRipple) / 10.0) - 1); double a; a = log (1 / eps + sqrt(1 / square(eps) + 1)) / mOrder; // Assume even order to start for (int iPair = 0; iPair < mOrder/2; iPair++) { float fSPoleX = -fC * sinh (a) * sin ((2*iPair + 1) * PI / (2 * mOrder)); float fSPoleY = fC * cosh (a) * cos ((2*iPair + 1) * PI / (2 * mOrder)); BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY); if (mFilterSubtype == kLowPass) // LOWPASS { fZZeroX = -1; fDCPoleDistSqr = Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY); fDCPoleDistSqr /= 2*2; // dist from zero at Nyquist } else { // Highpass - do the digital LP->HP transform on the poles and zeroes ComplexDiv (beta - fZPoleX, -fZPoleY, 1 - beta * fZPoleX, -beta * fZPoleY, &fZPoleX, &fZPoleY); fZZeroX = 1; fDCPoleDistSqr = Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY); // distance from Nyquist fDCPoleDistSqr /= 2*2; // dist from zero at Nyquist } mpBiquad[iPair].fNumerCoeffs [0] = fDCPoleDistSqr; mpBiquad[iPair].fNumerCoeffs [1] = -2 * fZZeroX * fDCPoleDistSqr; mpBiquad[iPair].fNumerCoeffs [2] = fDCPoleDistSqr; mpBiquad[iPair].fDenomCoeffs [0] = -2 * fZPoleX; mpBiquad[iPair].fDenomCoeffs [1] = square(fZPoleX) + square(fZPoleY); } if ((mOrder & 1) == 0) { float fTemp = DB_TO_LINEAR(-wxMax(0.001, mRipple)); // at DC the response is down R dB (for even-order) mpBiquad[0].fNumerCoeffs [0] *= fTemp; mpBiquad[0].fNumerCoeffs [1] *= fTemp; mpBiquad[0].fNumerCoeffs [2] *= fTemp; } else { // Odd order - now do the 1st-order section float fSPoleX = -fC * sinh (a); float fSPoleY = 0; BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY); if (mFilterSubtype == kLowPass) // LOWPASS { fZZeroX = -1; fDCPoleDistSqr = sqrt(Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY)); fDCPoleDistSqr /= 2; // dist from zero at Nyquist } else { // Highpass - do the digital LP->HP transform on the poles and zeroes ComplexDiv (beta - fZPoleX, -fZPoleY, 1 - beta * fZPoleX, -beta * fZPoleY, &fZPoleX, &fZPoleY); fZZeroX = 1; fDCPoleDistSqr = sqrt(Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY)); // distance from Nyquist fDCPoleDistSqr /= 2; // dist from zero at Nyquist } mpBiquad[(mOrder-1)/2].fNumerCoeffs [0] = fDCPoleDistSqr; mpBiquad[(mOrder-1)/2].fNumerCoeffs [1] = -fZZeroX * fDCPoleDistSqr; mpBiquad[(mOrder-1)/2].fNumerCoeffs [2] = 0; mpBiquad[(mOrder-1)/2].fDenomCoeffs [0] = -fZPoleX; mpBiquad[(mOrder-1)/2].fDenomCoeffs [1] = 0; } break; case kChebyshevTypeII: // Chebyshev Type 2 float fSZeroX, fSZeroY; float fSPoleX, fSPoleY; eps = DB_TO_LINEAR(-wxMax(0.001, mStopbandRipple)); a = log (1 / eps + sqrt(1 / square(eps) + 1)) / mOrder; // Assume even order for (int iPair = 0; iPair < mOrder/2; iPair++) { ComplexDiv (fC, 0, -sinh (a) * sin ((2*iPair + 1) * PI / (2 * mOrder)), cosh (a) * cos ((2*iPair + 1) * PI / (2 * mOrder)), &fSPoleX, &fSPoleY); BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY); fSZeroX = 0; fSZeroY = fC / cos (((2 * iPair) + 1) * PI / (2 * mOrder)); BilinTransform (fSZeroX, fSZeroY, &fZZeroX, &fZZeroY); if (mFilterSubtype == kLowPass) // LOWPASS { fDCPoleDistSqr = Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY); fDCPoleDistSqr /= Calc2D_DistSqr (1, 0, fZZeroX, fZZeroY); } else { // Highpass - do the digital LP->HP transform on the poles and zeroes ComplexDiv (beta - fZPoleX, -fZPoleY, 1 - beta * fZPoleX, -beta * fZPoleY, &fZPoleX, &fZPoleY); ComplexDiv (beta - fZZeroX, -fZZeroY, 1 - beta * fZZeroX, -beta * fZZeroY, &fZZeroX, &fZZeroY); fDCPoleDistSqr = Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY); // distance from Nyquist fDCPoleDistSqr /= Calc2D_DistSqr (-1, 0, fZZeroX, fZZeroY); } mpBiquad[iPair].fNumerCoeffs [0] = fDCPoleDistSqr; mpBiquad[iPair].fNumerCoeffs [1] = -2 * fZZeroX * fDCPoleDistSqr; mpBiquad[iPair].fNumerCoeffs [2] = (square(fZZeroX) + square(fZZeroY)) * fDCPoleDistSqr; mpBiquad[iPair].fDenomCoeffs [0] = -2 * fZPoleX; mpBiquad[iPair].fDenomCoeffs [1] = square(fZPoleX) + square(fZPoleY); } // Now, if it's odd order, we have one more to do if (mOrder & 1) { int iPair = (mOrder-1)/2; // we'll do it as a biquad, but it's just first-order ComplexDiv (fC, 0, -sinh (a) * sin ((2*iPair + 1) * PI / (2 * mOrder)), cosh (a) * cos ((2*iPair + 1) * PI / (2 * mOrder)), &fSPoleX, &fSPoleY); BilinTransform (fSPoleX, fSPoleY, &fZPoleX, &fZPoleY); fZZeroX = -1; // in the s-plane, the zero is at infinity fZZeroY = 0; if (mFilterSubtype == kLowPass) // LOWPASS { fDCPoleDistSqr = sqrt(Calc2D_DistSqr (1, 0, fZPoleX, fZPoleY)); fDCPoleDistSqr /= 2; } else { // Highpass - do the digital LP->HP transform on the poles and zeroes ComplexDiv (beta - fZPoleX, -fZPoleY, 1 - beta * fZPoleX, -fZPoleY, &fZPoleX, &fZPoleY); fZZeroX = 1; fDCPoleDistSqr = sqrt(Calc2D_DistSqr (-1, 0, fZPoleX, fZPoleY)); // distance from Nyquist fDCPoleDistSqr /= 2; } mpBiquad[iPair].fNumerCoeffs [0] = fDCPoleDistSqr; mpBiquad[iPair].fNumerCoeffs [1] = -fZZeroX * fDCPoleDistSqr; mpBiquad[iPair].fNumerCoeffs [2] = 0; mpBiquad[iPair].fDenomCoeffs [0] = -fZPoleX; mpBiquad[iPair].fDenomCoeffs [1] = 0; } break; } return true; }