22#include <wx/simplebook.h>
27#include "../ProjectFileManager.h"
31#include "../widgets/valnum.h"
38 {
XO(
"perceived loudness") },
57{
XO(
"Loudness Normalization") };
80 return XO(
"Sets the loudness of one or more tracks");
85 return L
"Loudness_Normalization";
110 bool bGoodResult =
true;
111 auto topMsg =
XO(
"Normalizing Loudness...\n");
116 for (
auto pTrack : outputs.Get().Selected<
WaveTrack>()) {
118 double trackStart = pTrack->GetStartTime();
119 double trackEnd = pTrack->GetEndTime();
123 const double curT0 = std::max(trackStart,
mT0);
130 auto trackName = pTrack->GetName();
135 topMsg +
XO(
"Analyzing: %s").Format(trackName);
137 const auto channels = pTrack->Channels();
138 auto nChannels =
mStereoInd ? 1 : channels.size();
142 std::optional<EBUR128> loudnessProcessor;
146 loudnessProcessor.emplace(
mCurRate, nChannels);
148 curT0, curT1, 0, &*loudnessProcessor))
156 for (
const auto pChannel : channels) {
157 if (!
GetTrackRMS(*pChannel, curT0, curT1, RMS[idx]))
171 extent = loudnessProcessor->IntegrativeLoudness();
178 extent =
sqrt((RMS[0] * RMS[0] + RMS[1] * RMS[1]) / 2.0);
185 float mult = ratio / extent;
190 if (nChannels == 1 &&
200 if (!
ProcessOne(track, nChannels, curT0, curT1, mult,
nullptr)) {
208 for (
const auto pChannel : channels)
209 if (!(bGoodResult = processOne(*pChannel)))
216 if (!(bGoodResult = processOne(**pTrack->Channels().begin())))
234 S.StartVerticalLay(0);
236 S.StartMultiColumn(2, wxALIGN_CENTER);
238 S.StartVerticalLay(
false);
240 S.StartHorizontalLay(wxALIGN_LEFT,
false);
242 S.AddVariableText(
XO(
"&Normalize"),
false,
243 wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
251 .AddVariableText(
XO(
"t&o"),
false,
252 wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
260 S.StartNotebookPage({});
262 S.StartHorizontalLay(wxALIGN_LEFT,
false);
266 .Name(
XO(
"Loudness LUFS") )
267 .
Validator<FloatingPointValidator<double>>(
269 NumValidatorStyle::ONE_TRAILING_ZERO,
271 .AddTextBox( {}, L
"", 10);
275 .AddVariableText(
XO(
"LUFS"),
false,
276 wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
278 S.EndHorizontalLay();
282 S.StartNotebookPage({});
284 S.StartHorizontalLay(wxALIGN_LEFT,
false);
287 .Name(
XO(
"RMS dB") )
288 .
Validator<FloatingPointValidator<double>>(
290 NumValidatorStyle::ONE_TRAILING_ZERO,
292 .AddTextBox( {}, L
"", 10);
295 .AddVariableText(
XO(
"dB"),
false,
296 wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
298 S.EndHorizontalLay();
306 .AddVariableText( {},
false,
307 wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
309 S.EndHorizontalLay();
313 .AddCheckBox(
XXO(
"Normalize &stereo channels independently"),
317 .Validator<wxGenericValidator>( &
mDualMono )
318 .AddCheckBox(
XXO(
"&Treat mono as dual-mono (recommended)"),
337 wxCommandEvent dummy;
358 bool stereoTrackFound =
false;
359 double maxSampleRate = 0;
364 maxSampleRate = std::max(maxSampleRate, track->GetRate());
367 if(track->NChannels() == 2)
368 stereoTrackFound =
true;
386 const double curT0,
const double curT1,
float &rms)
401 const double curT0,
const double curT1,
const float mult,
427 const size_t remainingLen = (
end - s).as_size_t();
428 blockLen = blockLen > remainingLen ? remainingLen : blockLen;
432 if (pLoudnessProcessor) {
507 return channel.SetFloats(
mTrackBuffer[idx].get(), pos, len);
511 return setOne(track);
514 if (!setOne(*channel))
531 mChoice->GetValidator()->TransferFromWindow();
544 if (!
mUIParent->TransferDataFromWindow())
XXO("&Cut/Copy/Paste Toolbar")
static const EnumValueSymbol kNormalizeTargetStrings[EffectLoudness::nAlgos]
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
TranslatableStrings Msgids(const EnumValueSymbol strings[], size_t nStrings)
Convenience function often useful when adding choice controls.
void reinit(Integral count, bool initialize=false)
Generates EffectParameterMethods overrides from variadic template arguments.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Implements EBU-R128 loudness measurement.
void ProcessSampleFromChannel(float x_in, size_t channel) const
void SetLinearEffectFlag(bool linearEffectFlag)
std::shared_ptr< TrackList > mTracks
static bool EnableApply(wxWindow *parent, bool enable=true)
Enable or disable the Apply button of the dialog that contains parent.
bool TotalProgress(double frac, const TranslatableString &={}) const
int GetNumWaveTracks() const
Performs effect computation.
An Effect to bring the loudness level up to a chosen level.
bool Process(EffectInstance &instance, EffectSettings &settings) override
size_t mTrackBufferCapacity
wxCheckBox * mDualMonoCheckBox
bool AnalyseBufferBlock(EBUR128 &loudnessProcessor)
static const ComponentInterfaceSymbol Symbol
wxCheckBox * mStereoIndCheckBox
wxWeakRef< wxWindow > mUIParent
ComponentInterfaceSymbol GetSymbol() const override
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
void OnUpdateUI(wxCommandEvent &evt)
const EffectParameterMethods & Parameters() const override
TranslatableString GetDescription() const override
bool TransferDataToWindow(const EffectSettings &settings) override
void AllocBuffers(TrackList &outputs)
EffectType GetType() const override
Type determines how it behaves.
static constexpr EffectParameter StereoInd
static constexpr EffectParameter LUFSLevel
bool ProcessBufferBlock(float mult)
static constexpr EffectParameter RMSLevel
static constexpr EffectParameter DualMono
virtual ~EffectLoudness()
void LoadBufferBlock(WaveChannel &track, size_t nChannels, sampleCount pos, size_t len)
bool TransferDataFromWindow(EffectSettings &settings) override
std::unique_ptr< EffectEditor > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
static constexpr EffectParameter NormalizeTo
bool ProcessOne(WaveChannel &track, size_t nChannels, double curT0, double curT1, float mult, EBUR128 *pLoudnessProcessor)
bool StoreBufferBlock(WaveChannel &track, size_t nChannels, sampleCount pos, size_t len)
void OnChoice(wxCommandEvent &evt)
TranslatableString mProgressMsg
static bool GetTrackRMS(WaveChannel &track, double curT0, double curT1, float &rms)
Use this object to copy the input tracks to tentative outputTracks.
Hold values to send to effect output meters.
Interface for manipulations of an Effect's settings.
virtual void Reset(Effect &effect) const =0
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
auto Selected() -> TrackIterRange< TrackType >
Holds a msgid for the translation catalog; may also bind format arguments.
A Validator is an object which checks whether a wxVariant satisfies a certain criterion....
size_t GetBestBlockSize(sampleCount t) const
A hint for sizing of well aligned fetches.
A Track that contains audio waveform data.
sampleCount TimeToLongSamples(double t0) const
Positions or offsets within audio files need a wide type.
bool IsMono(const Channel &channel)
Whether the channel is mono.
WAVE_TRACK_API float GetRMS(const WaveChannel &channel, double t0, double t1, bool mayThrow=true)
BuiltinEffectsModule::Registration< EffectLoudness > reg
const char * end(const char *str) noexcept
__finl float_x4 __vecc sqrt(const float_x4 &a)
const Type min
Minimum value.
const Type max
Maximum value.
Externalized state of a plug-in.