static inline void gst_rg_volume_determine_gain (GstRgVolume * self, gdouble * target_gain, gdouble * result_gain) { gdouble gain, peak; if (!self->has_track_gain && !self->has_album_gain) { GST_DEBUG_OBJECT (self, "using fallback gain"); gain = self->fallback_gain; peak = 1.0; } else if ((self->album_mode && self->has_album_gain) || (!self->album_mode && !self->has_track_gain)) { gain = self->album_gain; if (G_LIKELY (self->has_album_peak)) { peak = self->album_peak; } else { GST_DEBUG_OBJECT (self, "album peak missing, assuming 1.0"); peak = 1.0; } /* Falling back from track to album gain shouldn't really happen. */ if (G_UNLIKELY (!self->album_mode)) GST_INFO_OBJECT (self, "falling back to album gain"); } else { /* !album_mode && !has_album_gain || album_mode && has_track_gain */ gain = self->track_gain; if (G_LIKELY (self->has_track_peak)) { peak = self->track_peak; } else { GST_DEBUG_OBJECT (self, "track peak missing, assuming 1.0"); peak = 1.0; } if (self->album_mode) GST_INFO_OBJECT (self, "falling back to track gain"); } gain += self->pre_amp; *target_gain = gain; *result_gain = gain; if (LINEAR_TO_DB (peak) + gain > self->headroom) { *result_gain = LINEAR_TO_DB (1. / peak) + self->headroom; } }
void EffectDistortion::OnThresholdSlider(wxCommandEvent& evt) { mThreshold = (double) evt.GetInt() / SCL_Threshold_dB; mParams.mThreshold_dB = wxMax(LINEAR_TO_DB(mThreshold), MIN_Threshold_dB); mThreshold = std::max(MIN_Threshold_Linear, mThreshold); mThresholdT->GetValidator()->TransferToWindow(); }
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(); }
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(); }
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; }
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"); }
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 ContrastDialog::GetDB(float &dB) { float rms = float(0.0); int numberSelecteTracks = 0; // For stereo tracks: sqrt((mean(L)+mean(R))/2) bool isStereo = false; double meanSq = 0.0; AudacityProject *p = GetActiveProject(); SelectedTrackListOfKindIterator iter(Track::Wave, p->GetTracks()); WaveTrack *t = (WaveTrack *) iter.First(); while (t) { numberSelecteTracks++; if (numberSelecteTracks > 1 && !isStereo) { AudacityMessageDialog m(NULL, _("You can only measure one track at a time."), _("Error"), wxOK); m.ShowModal(); return false; } isStereo = t->GetLinked(); wxASSERT(mT0 <= mT1); // Ignore whitespace beyond ends of track. if(mT0 < t->GetStartTime()) mT0 = t->GetStartTime(); if(mT1 > t->GetEndTime()) mT1 = t->GetEndTime(); auto SelT0 = t->TimeToLongSamples(mT0); auto SelT1 = t->TimeToLongSamples(mT1); if(SelT0 > SelT1) { AudacityMessageDialog m(NULL, _("Invalid audio selection.\nPlease ensure that audio is selected."), _("Error"), wxOK); m.ShowModal(); return false; } if(SelT0 == SelT1) { AudacityMessageDialog m(NULL, _("Nothing to measure.\nPlease select a section of a track."), _("Error"), wxOK); m.ShowModal(); return false; } // Don't throw in this analysis dialog rms = ((WaveTrack *)t)->GetRMS(mT0, mT1, false); meanSq += rms * rms; t = (WaveTrack *) iter.Next(); } // TODO: This works for stereo, provided the audio clips are in both channels. // We should really count gaps between clips as silence. rms = (meanSq > 0.0)? sqrt(meanSq/(double)numberSelecteTracks) : 0.0; if(numberSelecteTracks == 0) { AudacityMessageDialog m(NULL, _("Please select an audio track."), _("Error"), wxOK); m.ShowModal(); return false; } // Gives warning C4056, Overflow in floating-point constant arithmetic // -INFINITY is intentional here. // Looks like we are stuck with this warning, as // #pragma warning( disable : 4056) // even around the whole function does not disable it successfully. dB = (rms == 0.0)? -INFINITY : LINEAR_TO_DB(rms); return true; }
void EffectAmplify::PopulateOrExchange(ShuttleGui & S) { if (IsBatchProcessing()) { mPeak = 1.0; } else { if (mPeak > 0.0) { mRatio = 1.0 / mPeak; mRatioClip = mRatio; } else { mRatio = 1.0; } } S.AddSpace(0, 5); S.StartVerticalLay(0); { int precission = 3; // allow (a generous) 3 decimal places for Amplification (dB) // Amplitude S.StartMultiColumn(2, wxCENTER); { FloatingPointValidator<double> vldAmp(precission, &mAmp, NumValidatorStyle::ONE_TRAILING_ZERO); vldAmp.SetRange(MIN_Amp, MAX_Amp); mAmpT = S.Id(ID_Amp).AddTextBox(_("Amplification (dB):"), wxT(""), 12); mAmpT->SetValidator(vldAmp); } S.EndMultiColumn(); // Amplitude S.StartHorizontalLay(wxEXPAND); { S.SetStyle(wxSL_HORIZONTAL); mAmpS = S.Id(ID_Amp).AddSlider( {}, 0, MAX_Amp * SCL_Amp, MIN_Amp * SCL_Amp); mAmpS->SetName(_("Amplification dB")); } S.EndHorizontalLay(); // Peak S.StartMultiColumn(2, wxCENTER); { // One extra decimal place so that rounding is visible to user (see: bug 958) FloatingPointValidator<double> vldNewPeak(precission + 1, &mNewPeak, NumValidatorStyle::ONE_TRAILING_ZERO); double minAmp = MIN_Amp + LINEAR_TO_DB(mPeak); double maxAmp = MAX_Amp + LINEAR_TO_DB(mPeak); // min and max need same precision as what we're validating (bug 963) minAmp = Internat::CompatibleToDouble(Internat::ToString(minAmp, precission +1)); maxAmp = Internat::CompatibleToDouble(Internat::ToString(maxAmp, precission +1)); vldNewPeak.SetRange(minAmp, maxAmp); mNewPeakT = S.Id(ID_Peak).AddTextBox(_("New Peak Amplitude (dB):"), wxT(""), 12); mNewPeakT->SetValidator(vldNewPeak); } S.EndMultiColumn(); // Clipping S.StartHorizontalLay(wxCENTER); { mClip = S.Id(ID_Clip).AddCheckBox(_("Allow clipping"), wxT("false")); if (IsBatchProcessing()) { mClip->Enable(false); mCanClip = true; } } S.EndHorizontalLay(); } S.EndVerticalLay(); return; }
bool ContrastDialog::GetDB(float &dB) { float rms = float(0.0); int numberSelecteTracks = 0; // For stereo tracks: sqrt((mean(L)+mean(R))/2) bool isStereo = false; double meanSq = 0.0; AudacityProject *p = GetActiveProject(); SelectedTrackListOfKindIterator iter(Track::Wave, p->GetTracks()); WaveTrack *t = (WaveTrack *) iter.First(); while (t) { numberSelecteTracks++; if (numberSelecteTracks > 1 && !isStereo) { wxMessageDialog m(NULL, _("You can only measure one track at a time."), _("Error"), wxOK); m.ShowModal(); return false; } isStereo = t->GetLinked(); wxASSERT(mT0 <= mT1); // Ignore whitespace beyond ends of track. if(mT0 < t->GetStartTime()) mT0 = t->GetStartTime(); if(mT1 > t->GetEndTime()) mT1 = t->GetEndTime(); sampleCount SelT0 = t->TimeToLongSamples(mT0); sampleCount SelT1 = t->TimeToLongSamples(mT1); if(SelT0 > SelT1) { wxMessageDialog m(NULL, _("Invalid audio selection.\nPlease ensure that audio is selected."), _("Error"), wxOK); m.ShowModal(); return false; } if(SelT0 == SelT1) { wxMessageDialog m(NULL, _("Nothing to measure.\nPlease select a section of a track."), _("Error"), wxOK); m.ShowModal(); return false; } ((WaveTrack *)t)->GetRMS(&rms, mT0, mT1); meanSq += rms * rms; t = (WaveTrack *) iter.Next(); } // TODO: This works for stereo, provided the audio clips are in both channels. // We should really count gaps between clips as silence. rms = (meanSq > 0.0)? sqrt(meanSq/(double)numberSelecteTracks) : 0.0; if(numberSelecteTracks == 0) { wxMessageDialog m(NULL, _("Please select an audio track."), _("Error"), wxOK); m.ShowModal(); return false; } dB = (rms == 0.0)? -INFINITY : LINEAR_TO_DB(rms); return true; }
void EffectScienFilterPanel::OnPaint(wxPaintEvent & WXUNUSED(evt)) { wxPaintDC dc(this); int width, height; GetSize(&width, &height); if (!mBitmap || mWidth != width || mHeight != height) { if (mBitmap) { delete mBitmap; } mWidth = width; mHeight = height; mBitmap = new wxBitmap(mWidth, mHeight); } wxBrush bkgndBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); wxMemoryDC memDC; memDC.SelectObject(*mBitmap); wxRect bkgndRect; bkgndRect.x = 0; bkgndRect.y = 0; bkgndRect.width = mWidth; bkgndRect.height = mHeight; memDC.SetBrush(bkgndBrush); memDC.SetPen(*wxTRANSPARENT_PEN); memDC.DrawRectangle(bkgndRect); bkgndRect.y = mHeight; memDC.DrawRectangle(bkgndRect); wxRect border; border.x = 0; border.y = 0; border.width = mWidth; border.height = mHeight; memDC.SetBrush(*wxWHITE_BRUSH); memDC.SetPen(*wxBLACK_PEN); memDC.DrawRectangle(border); mEnvRect = border; mEnvRect.Deflate(2, 2); // Pure blue x-axis line memDC.SetPen(wxPen(theTheme.Colour(clrGraphLines), 1, wxSOLID)); int center = (int) (mEnvRect.height * mDbMax / (mDbMax - mDbMin) + 0.5); AColor::Line(memDC, mEnvRect.GetLeft(), mEnvRect.y + center, mEnvRect.GetRight(), mEnvRect.y + center); //Now draw the actual response that you will get. //mFilterFunc has a linear scale, window has a log one so we have to fiddle about memDC.SetPen(wxPen(theTheme.Colour(clrResponseLines), 3, wxSOLID)); double scale = (double) mEnvRect.height / (mDbMax - mDbMin); // pixels per dB double yF; // gain at this freq double loLog = log10(mLoFreq); double step = log10(mHiFreq) - loLog; step /= ((double) mEnvRect.width - 1.0); double freq; // actual freq corresponding to x position int x, y, xlast = 0, ylast = 0; for (int i = 0; i < mEnvRect.width; i++) { x = mEnvRect.x + i; freq = pow(10.0, loLog + i * step); //Hz yF = mEffect->FilterMagnAtFreq (freq); yF = LINEAR_TO_DB(yF); if (yF < mDbMin) { yF = mDbMin; } yF = center-scale * yF; if (yF > mEnvRect.height) { yF = (double) mEnvRect.height - 1.0; } if (yF < 0.0) { yF = 0.0; } y = (int) (yF + 0.5); if (i != 0 && (y < mEnvRect.height - 1 || ylast < mEnvRect.y + mEnvRect.height - 1)) { AColor::Line(memDC, xlast, ylast, x, mEnvRect.y + y); } xlast = x; ylast = mEnvRect.y + y; } memDC.SetPen(*wxBLACK_PEN); mEffect->mfreqRuler->ruler.DrawGrid(memDC, mEnvRect.height + 2, true, true, 0, 1); mEffect->mdBRuler->ruler.DrawGrid(memDC, mEnvRect.width + 2, true, true, 1, 2); dc.Blit(0, 0, mWidth, mHeight, &memDC, 0, 0, wxCOPY, FALSE); memDC.SelectObject(wxNullBitmap); }
// // 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; }