Audacity 3.2.0
ReverbBase.cpp
Go to the documentation of this file.
1#include "ReverbBase.h"
2#include "ShuttleAutomation.h"
3
5{
7}
8
10{
11}
12
14{
15 static CapturedParameters<
18 parameters;
19 return parameters;
20}
21
22static const struct
23{
26} FactoryPresets[] = {
27 // Room Pre Hf Tone Tone Wet Dry
28 // Stereo Wet
29 // Name Size, Delay, Reverb, Damping, Low, High, Gain,
30 // Gain, Width, Only
31 // general purpose
32 /*i18n-hint: This is the name of an effect preset */
33 { XO("Acoustic"), { 50, 10, 75, 100, 21, 100, -14, 0, 80, false } },
34 /*i18n-hint: This is the name of an effect preset */
35 { XO("Ambience"), { 100, 55, 100, 50, 53, 38, 0, -10, 100, false } },
36 /*i18n-hint: This is the name of an effect preset */
37 { XO("Artificial"), { 81, 99, 23, 62, 16, 19, -4, 0, 100, false } },
38 /*i18n-hint: This is the name of an effect preset */
39 { XO("Clean"), { 50, 10, 75, 100, 55, 100, -18, 0, 75, false } },
40 /*i18n-hint: This is the name of an effect preset */
41 { XO("Modern"), { 50, 10, 75, 100, 55, 100, -15, 0, 75, false } },
42 // vocals
43 /*i18n-hint: This is the name of an effect preset */
44 { XO("Vocal I"), { 70, 20, 40, 99, 100, 50, -12, 0, 70, false } },
45 /*i18n-hint: This is the name of an effect preset */
46 { XO("Vocal II"), { 50, 0, 50, 99, 50, 100, -1, -1, 70, false } },
47 /*i18n-hint: This is the name of an effect preset */
48 { XO("Dance Vocal"), { 90, 2, 60, 77, 30, 51, -10, 0, 100, false } },
49 /*i18n-hint: This is the name of an effect preset */
50 { XO("Modern Vocal"), { 66, 27, 77, 8, 0, 51, -10, 0, 68, false } },
51 /*i18n-hint: This is the name of an effect preset */
52 { XO("Voice Tail"), { 66, 27, 100, 8, 0, 51, -6, 0, 68, false } },
53 // room sizes
54 /*i18n-hint: This is the name of an effect preset */
55 { XO("Bathroom"), { 16, 8, 80, 0, 0, 100, -6, 0, 100, false } },
56 /*i18n-hint: This is the name of an effect preset */
57 { XO("Small Room Bright"), { 30, 10, 50, 50, 50, 100, -1, -1, 100, false } },
58 /*i18n-hint: This is the name of an effect preset */
59 { XO("Small Room Dark"), { 30, 10, 50, 50, 100, 0, -1, -1, 100, false } },
60 /*i18n-hint: This is the name of an effect preset */
61 { XO("Medium Room"), { 75, 10, 40, 50, 100, 70, -1, -1, 70, false } },
62 /*i18n-hint: This is the name of an effect preset */
63 { XO("Large Room"), { 85, 10, 40, 50, 100, 80, 0, -6, 90, false } },
64 /*i18n-hint: This is the name of an effect preset */
65 { XO("Church Hall"), { 90, 32, 60, 50, 100, 50, 0, -12, 100, false } },
66 /*i18n-hint: This is the name of an effect preset */
67 { XO("Cathedral"), { 90, 16, 90, 50, 100, 0, 0, -20, 100, false } },
68 /*i18n-hint: This is the name of an effect preset */
69 { XO("Big Cave"), { 100, 55, 100, 50, 53, 38, 5, -3, 100, false } },
70};
71
72//
73// ReverbBase
74//
75
77
79{
80 return Symbol;
81}
82
84{
85 return XO("Adds ambience or a \"hall effect\"");
86}
87
89{
90 return L"Reverb";
91}
92
93// EffectDefinitionInterface implementation
94
96{
97 return EffectTypeProcess;
98}
99
101{
103}
104
105static size_t BLOCK = 16384;
106
108 : PerTrackEffect::Instance { effect }
109{
110}
111
114{
115 // For descructive processing, fix the number of channels, maybe as 1 not 2
116 auto& rs = GetSettings(settings);
117 mChannels = rs.mStereoWidth ? 2 : 1;
118
119 return InstanceInit(
120 settings, sampleRate, mState, chanMap, /* forceStereo = */ false);
121}
122
125 ChannelNames chanMap, bool forceStereo)
126{
127 auto& rs = GetSettings(settings);
128
129 bool isStereo = false;
130 state.mNumChans = 1;
131 if (
132 (chanMap && chanMap[0] != ChannelNameEOL &&
133 chanMap[1] == ChannelNameFrontRight) ||
134 forceStereo)
135 {
136 isStereo = true;
137 state.mNumChans = 2;
138 }
139
140 state.mP = std::make_unique<Reverb_priv_ex[]>(state.mNumChans);
141
142 for (unsigned int i = 0; i < state.mNumChans; i++)
143 {
145 &state.mP[i].reverb, sampleRate, rs.mWetGain, rs.mRoomSize,
146 rs.mReverberance, rs.mHfDamping, rs.mPreDelay,
147 rs.mStereoWidth * (isStereo ? 1 : 0), rs.mToneLow, rs.mToneHigh, BLOCK,
148 state.mP[i].wet);
149 }
150
151 return true;
152}
153
155{
156 return true;
157}
158
161{
162 SetBlockSize(512);
163 mSlaves.clear();
164
165 mLastAppliedSettings = GetSettings(settings);
166 mLastSampleRate = sampleRate;
167
168 return true;
169}
170
172 EffectSettings& settings, EffectOutputs*, unsigned numChannels,
173 float sampleRate)
174{
175 ReverbBase::Instance slave(mProcessor);
176
177 // The notion of ChannelNames is unavailable here,
178 // so we'll have to force the stereo init, if this is the case
179 //
180 InstanceInit(
181 settings, sampleRate, slave.mState, /*ChannelNames=*/nullptr,
182 /*forceStereo=*/(numChannels == 2));
183
184 mSlaves.push_back(std::move(slave));
185 return true;
186}
187
189{
190 mSlaves.clear();
191 return true;
192}
193
195 size_t group, EffectSettings& settings, const float* const* inbuf,
196 float* const* outbuf, size_t numSamples)
197{
198
199 const auto& incomingSettings = GetSettings(settings);
200 if (!(incomingSettings == mLastAppliedSettings))
201 {
202 const bool onlySimpleOnes =
203 OnlySimpleParametersChanged(incomingSettings, mLastAppliedSettings);
204
205 for (auto& slave : mSlaves)
206 {
207 for (unsigned int i = 0; i < slave.mState.mNumChans; i++)
208 {
209 auto& reverbCore = slave.mState.mP[i].reverb;
210 const auto& is = incomingSettings;
211
212 if (onlySimpleOnes)
213 {
215 &reverbCore, mLastSampleRate, is.mWetGain, is.mReverberance,
216 is.mHfDamping, is.mToneLow, is.mToneHigh);
217 }
218 else
219 {
220 // One of the non-simple parameters changed, so we need to
221 // do a full reinit
223 &reverbCore, mLastSampleRate, is.mWetGain, is.mRoomSize,
224 is.mReverberance, is.mHfDamping, is.mPreDelay,
225 is.mStereoWidth, is.mToneLow, is.mToneHigh);
226 }
227 }
228 }
229
230 mLastAppliedSettings = incomingSettings;
231 }
232
233 if (group >= mSlaves.size())
234 return 0;
235 return InstanceProcess(
236 settings, mSlaves[group].mState, inbuf, outbuf, numSamples);
237}
238
240{
241 for (auto& slave : mSlaves)
242 {
243 for (unsigned int i = 0; i < slave.mState.mNumChans; i++)
244 {
245 reverb_clear(&(slave.mState.mP[i].reverb));
246 }
247 }
248
249 return true;
250}
251
253{
254 return mChannels;
255}
256
258{
259 return mChannels;
260}
261
263 EffectSettings& settings, const float* const* inBlock,
264 float* const* outBlock, size_t blockLen)
265{
266 return InstanceProcess(settings, mState, inBlock, outBlock, blockLen);
267}
268
270 EffectSettings& settings, ReverbState& state, const float* const* inBlock,
271 float* const* outBlock, size_t blockLen)
272{
273 auto& rs = GetSettings(settings);
274
275 const float* ichans[2] = { NULL, NULL };
276 float* ochans[2] = { NULL, NULL };
277
278 for (unsigned int c = 0; c < state.mNumChans; c++)
279 {
280 ichans[c] = inBlock[c];
281 ochans[c] = outBlock[c];
282 }
283
284 float const dryMult = rs.mWetOnly ? 0 : dB_to_linear(rs.mDryGain);
285
286 auto remaining = blockLen;
287
288 while (remaining)
289 {
290 auto len = std::min(remaining, decltype(remaining)(BLOCK));
291 for (unsigned int c = 0; c < state.mNumChans; c++)
292 {
293 // Write the input samples to the reverb fifo. Returned value is the
294 // address of the fifo buffer which contains a copy of the input
295 // samples.
296 state.mP[c].dry =
297 (float*)fifo_write(&state.mP[c].reverb.input_fifo, len, ichans[c]);
298 reverb_process(&state.mP[c].reverb, len);
299 }
300
301 if (state.mNumChans == 2)
302 {
303 for (decltype(len) i = 0; i < len; i++)
304 {
305 for (int w = 0; w < 2; w++)
306 {
307 ochans[w][i] =
308 dryMult * state.mP[w].dry[i] +
309 0.5 * (state.mP[0].wet[w][i] + state.mP[1].wet[w][i]);
310 }
311 }
312 }
313 else
314 {
315 for (decltype(len) i = 0; i < len; i++)
316 {
317 ochans[0][i] = dryMult * state.mP[0].dry[i] + state.mP[0].wet[0][i];
318 }
319 }
320
321 remaining -= len;
322
323 for (unsigned int c = 0; c < state.mNumChans; c++)
324 {
325 ichans[c] += len;
326 ochans[c] += len;
327 }
328 }
329
330 return blockLen;
331}
332
334{
336
337 for (size_t i = 0; i < WXSIZEOF(FactoryPresets); i++)
338 {
339 names.push_back(FactoryPresets[i].name.Translation());
340 }
341
342 return names;
343}
344
347{
348 if (id < 0 || id >= (int)WXSIZEOF(FactoryPresets))
349 {
350 return {};
351 }
352
354
355 return { nullptr };
356}
357
359{
360 // With C++20, all of this can be replaced by =default
361 return (a.mRoomSize == b.mRoomSize) && (a.mPreDelay == b.mPreDelay) &&
362 (a.mReverberance == b.mReverberance) &&
363 (a.mHfDamping == b.mHfDamping) && (a.mToneLow == b.mToneLow) &&
364 (a.mToneHigh == b.mToneHigh) && (a.mWetGain == b.mWetGain) &&
365 (a.mDryGain == b.mDryGain) && (a.mStereoWidth == b.mStereoWidth) &&
366 (a.mWetOnly == b.mWetOnly);
367}
368
370 const ReverbSettings& a, const ReverbSettings& b)
371{
372 // A "simple" reverb parameter is one that when changed, does not require the
373 // reverb allpass/comb filters to be reset. This distinction enables us to
374 // code things so that the user can keep hearing the processed sound while
375 // they tweak one of the simple parameters.
376
377 const bool oneSimpleParameterChanged =
378
379 (a.mReverberance != b.mReverberance) || (a.mHfDamping != b.mHfDamping) ||
380 (a.mToneLow != b.mToneLow) || (a.mToneHigh != b.mToneHigh) ||
381 (a.mWetGain != b.mWetGain);
382
383 const bool allNonSimpleParametersStayedTheSame =
384
385 (a.mRoomSize == b.mRoomSize) && (a.mPreDelay == b.mPreDelay) &&
386 (a.mStereoWidth == b.mStereoWidth);
387
388 return oneSimpleParameterChanged && allNonSimpleParametersStayedTheSame;
389}
int min(int a, int b)
struct State mState
EffectType
@ EffectTypeProcess
ChannelName
@ ChannelNameEOL
@ ChannelNameFrontRight
std::optional< std::unique_ptr< EffectSettingsAccess::Message > > OptionalMessage
XO("Cut/Copy/Paste")
std::vector< RegistryPath > RegistryPaths
Definition: Identifier.h:219
static void reverb_init(reverb_t *p, double sample_rate_Hz, double wet_gain_dB, double room_scale, double reverberance, double hf_damping, double pre_delay_ms, double stereo_depth, double tone_low, double tone_high)
#define dB_to_linear(x)
Definition: Reverb_libSoX.h:29
static void reverb_set_simple_params(reverb_t *p, double sample_rate_Hz, double wet_gain_dB, double reverberance, double hf_damping, double tone_low, double tone_high)
static void reverb_process(reverb_t *p, size_t length)
static void reverb_clear(reverb_t *p)
static void reverb_create(reverb_t *p, double sample_rate_Hz, double wet_gain_dB, double room_scale, double reverberance, double hf_damping, double pre_delay_ms, double stereo_depth, double tone_low, double tone_high, size_t buffer_size, float **out)
static void * fifo_write(fifo_t *f, FIFO_SIZE_T n, void const *data)
Definition: Reverb_libSoX.h:83
bool OnlySimpleParametersChanged(const ReverbSettings &a, const ReverbSettings &b)
Definition: ReverbBase.cpp:369
static size_t BLOCK
Definition: ReverbBase.cpp:105
bool operator==(const ReverbSettings &a, const ReverbSettings &b)
Definition: ReverbBase.cpp:358
static const struct @109 FactoryPresets[]
const TranslatableString name
Definition: ReverbBase.cpp:24
ReverbSettings preset
Definition: ReverbBase.cpp:25
static TranslatableStrings names
Definition: TagsEditor.cpp:153
static Settings & settings()
Definition: TrackInfo.cpp:51
int id
Generates EffectParameterMethods overrides from variadic template arguments.
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
void SetLinearEffectFlag(bool linearEffectFlag)
Definition: EffectBase.cpp:210
RealtimeSince
In which versions of Audacity was an effect realtime capable?
Hold values to send to effect output meters.
Interface for manipulations of an Effect's settings.
static ReverbSettings & GetSettings(EffectSettings &settings)
Assume settings originated from MakeSettings() and copies thereof.
Definition: Effect.h:166
Base class for many of the effects in Audacity.
RealtimeSince RealtimeSupport() const override
Since which version of Audacity has the effect supported realtime?
Definition: ReverbBase.cpp:100
virtual ~ReverbBase()
Definition: ReverbBase.cpp:9
static constexpr EffectParameter WetOnly
Definition: ReverbBase.h:212
static const ComponentInterfaceSymbol Symbol
Definition: ReverbBase.h:66
static constexpr EffectParameter StereoWidth
Definition: ReverbBase.h:203
static constexpr EffectParameter RoomSize
Definition: ReverbBase.h:143
static constexpr EffectParameter HfDamping
Definition: ReverbBase.h:166
OptionalMessage LoadFactoryPreset(int id, EffectSettings &settings) const override
Definition: ReverbBase.cpp:346
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
Definition: ReverbBase.cpp:88
EffectType GetType() const override
Type determines how it behaves.
Definition: ReverbBase.cpp:95
static constexpr EffectParameter PreDelay
Definition: ReverbBase.h:150
static constexpr EffectParameter Reverberance
Definition: ReverbBase.h:157
static constexpr EffectParameter WetGain
Definition: ReverbBase.h:189
static constexpr EffectParameter DryGain
Definition: ReverbBase.h:196
TranslatableString GetDescription() const override
Definition: ReverbBase.cpp:83
static constexpr EffectParameter ToneHigh
Definition: ReverbBase.h:182
RegistryPaths GetFactoryPresets() const override
Report names of factory presets.
Definition: ReverbBase.cpp:333
ComponentInterfaceSymbol GetSymbol() const override
Definition: ReverbBase.cpp:78
static constexpr EffectParameter ToneLow
Definition: ReverbBase.h:175
const EffectParameterMethods & Parameters() const override
Definition: ReverbBase.cpp:13
Holds a msgid for the translation catalog; may also bind format arguments.
wxString Translation() const
Externalized state of a plug-in.
unsigned GetAudioInCount() const override
How many input buffers to allocate at once.
Definition: ReverbBase.cpp:257
bool RealtimeSuspend() override
Definition: ReverbBase.cpp:239
Instance(const PerTrackEffect &effect)
Definition: ReverbBase.cpp:107
bool RealtimeAddProcessor(EffectSettings &settings, EffectOutputs *, unsigned numChannels, float sampleRate) override
Definition: ReverbBase.cpp:171
bool ProcessFinalize(void) noexcept override
Definition: ReverbBase.cpp:154
bool RealtimeInitialize(EffectSettings &settings, double sampleRate) override
Definition: ReverbBase.cpp:159
bool InstanceInit(EffectSettings &settings, double sampleRate, ReverbState &data, ChannelNames chanMap, bool forceStereo)
Definition: ReverbBase.cpp:123
bool ProcessInitialize(EffectSettings &settings, double sampleRate, ChannelNames chanMap) override
Definition: ReverbBase.cpp:112
size_t RealtimeProcess(size_t group, EffectSettings &settings, const float *const *inbuf, float *const *outbuf, size_t numSamples) override
Definition: ReverbBase.cpp:194
size_t InstanceProcess(EffectSettings &settings, ReverbState &data, const float *const *inBlock, float *const *outBlock, size_t blockLen)
Definition: ReverbBase.cpp:269
bool RealtimeFinalize(EffectSettings &settings) noexcept override
Definition: ReverbBase.cpp:188
unsigned GetAudioOutCount() const override
How many output buffers to allocate at once.
Definition: ReverbBase.cpp:252
ReverbState mState
Definition: ReverbBase.h:131
size_t ProcessBlock(EffectSettings &settings, const float *const *inBlock, float *const *outBlock, size_t blockLen) override
Called for destructive effect computation.
Definition: ReverbBase.cpp:262
double mDryGain
Definition: ReverbBase.h:27
double mPreDelay
Definition: ReverbBase.h:21
double mReverberance
Definition: ReverbBase.h:22
double mToneHigh
Definition: ReverbBase.h:25
double mWetGain
Definition: ReverbBase.h:26
double mToneLow
Definition: ReverbBase.h:24
double mHfDamping
Definition: ReverbBase.h:23
double mRoomSize
Definition: ReverbBase.h:20
double mStereoWidth
Definition: ReverbBase.h:28
unsigned mNumChans
Definition: ReverbBase.h:58
std::unique_ptr< Reverb_priv_ex[]> mP
Definition: ReverbBase.h:59