Skip to content

Commit d863269

Browse files
committed
Add GainEffect builtin effect
1 parent aecc34e commit d863269

4 files changed

Lines changed: 134 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,7 @@ add_library(
12591259
src/effects/backends/builtin/echoeffect.cpp
12601260
src/effects/backends/builtin/filtereffect.cpp
12611261
src/effects/backends/builtin/flangereffect.cpp
1262+
src/effects/backends/builtin/gaineffect.cpp
12621263
src/effects/backends/builtin/glitcheffect.cpp
12631264
src/effects/backends/builtin/graphiceqeffect.cpp
12641265
src/effects/backends/builtin/linkwitzriley8eqeffect.cpp

src/effects/backends/builtin/builtinbackend.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#ifdef __RUBBERBAND__
2929
#include "effects/backends/builtin/pitchshifteffect.h"
3030
#endif
31+
#include "effects/backends/builtin/gaineffect.h"
3132
#include "effects/backends/builtin/tremoloeffect.h"
3233
#include "effects/backends/builtin/whitenoiseeffect.h"
3334

@@ -66,6 +67,7 @@ BuiltInBackend::BuiltInBackend() {
6667
registerEffect<GlitchEffect>();
6768
registerEffect<CompressorEffect>();
6869
registerEffect<AutoGainControlEffect>();
70+
registerEffect<GainEffect>();
6971
}
7072

7173
std::unique_ptr<EffectProcessor> BuiltInBackend::createProcessor(
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#include "effects/backends/builtin/gaineffect.h"
2+
3+
#include "effects/backends/effectmanifest.h"
4+
#include "engine/effects/engineeffectparameter.h"
5+
#include "util/math.h"
6+
#include "util/rampingvalue.h"
7+
8+
namespace {
9+
inline CSAMPLE tanh_approx(CSAMPLE input) {
10+
return input / (1 + input * input / (3 + input * input / 5));
11+
}
12+
} // namespace
13+
14+
// static
15+
QString GainEffect::getId() {
16+
return "org.mixxx.effects.gain";
17+
}
18+
19+
// static
20+
EffectManifestPointer GainEffect::getManifest() {
21+
EffectManifestPointer pManifest(new EffectManifest());
22+
pManifest->setId(getId());
23+
pManifest->setName(QObject::tr("Gain"));
24+
pManifest->setShortName(QObject::tr("Gain"));
25+
pManifest->setAuthor("The Mixxx Team");
26+
pManifest->setVersion("1.0");
27+
pManifest->setDescription(QObject::tr("Amplifies audio by gain amount"));
28+
pManifest->setEffectRampsFromDry(true);
29+
30+
EffectManifestParameterPointer gain = pManifest->addParameter();
31+
gain->setId("gain");
32+
gain->setName(QObject::tr("Gain"));
33+
gain->setShortName(QObject::tr("Gain"));
34+
gain->setDescription(QObject::tr("The gain of the samples"));
35+
gain->setValueScaler(EffectManifestParameter::ValueScaler::Linear);
36+
gain->setUnitsHint(EffectManifestParameter::UnitsHint::Decibel);
37+
gain->setDefaultLinkType(EffectManifestParameter::LinkType::Linked);
38+
gain->setNeutralPointOnScale(0.0);
39+
gain->setRange(-24.0, 0.0, 24.0);
40+
41+
EffectManifestParameterPointer clip = pManifest->addParameter();
42+
clip->setId("clip");
43+
clip->setName(QObject::tr("Clip"));
44+
clip->setShortName(QObject::tr("Clip"));
45+
clip->setDescription(QObject::tr("Clip samples to within -1 to 1"));
46+
clip->setValueScaler(EffectManifestParameter::ValueScaler::Toggle);
47+
clip->setUnitsHint(EffectManifestParameter::UnitsHint::Unknown);
48+
clip->setRange(0, 0, 1);
49+
50+
return pManifest;
51+
}
52+
53+
void GainEffect::loadEngineEffectParameters(
54+
const QMap<QString, EngineEffectParameterPointer>& parameters) {
55+
m_pGainParameter = parameters.value("gain");
56+
m_pClipParameter = parameters.value("clip");
57+
}
58+
59+
void GainEffect::processChannel(
60+
GainGroupState* pState,
61+
const CSAMPLE* pInput,
62+
CSAMPLE* pOutput,
63+
const mixxx::EngineParameters& engineParameters,
64+
const EffectEnableState enableState,
65+
const GroupFeatureState& groupFeatures) {
66+
Q_UNUSED(groupFeatures);
67+
Q_UNUSED(enableState);
68+
69+
const CSAMPLE_GAIN gain = db2ratio(static_cast<float>(m_pGainParameter->value()));
70+
const auto clip = m_pClipParameter->toBool();
71+
GainGroupState& gs = *pState;
72+
RampingValue<CSAMPLE_GAIN> gain_ramping_value(
73+
gs.previous_gain, gain, engineParameters.samplesPerBuffer());
74+
75+
for (SINT i = 0;
76+
i < engineParameters.samplesPerBuffer();
77+
i++) {
78+
const auto gain_ramped = gain_ramping_value.getNth(i);
79+
pOutput[i] = pInput[i] * gain_ramped;
80+
81+
if (clip) {
82+
pOutput[i] = tanh_approx(pOutput[i]);
83+
}
84+
}
85+
86+
if (enableState == EffectEnableState::Disabling) {
87+
gs.previous_gain = 0;
88+
} else {
89+
gs.previous_gain = gain;
90+
}
91+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#pragma once
2+
3+
#include "effects/backends/effectprocessor.h"
4+
#include "util/class.h"
5+
6+
struct GainGroupState : public EffectState {
7+
public:
8+
GainGroupState(const mixxx::EngineParameters& engineParameters)
9+
: EffectState(engineParameters),
10+
previous_gain(1.0) {
11+
}
12+
~GainGroupState() override = default;
13+
CSAMPLE_GAIN previous_gain;
14+
};
15+
16+
class GainEffect : public EffectProcessorImpl<GainGroupState> {
17+
public:
18+
GainEffect() = default;
19+
~GainEffect() override = default;
20+
21+
static QString getId();
22+
static EffectManifestPointer getManifest();
23+
24+
void processChannel(
25+
GainGroupState* pState,
26+
const CSAMPLE* pInput,
27+
CSAMPLE* pOutput,
28+
const mixxx::EngineParameters& engineParameters,
29+
const EffectEnableState enableState,
30+
const GroupFeatureState& groupFeatures) override;
31+
32+
void loadEngineEffectParameters(
33+
const QMap<QString, EngineEffectParameterPointer>& parameters) override;
34+
35+
private:
36+
EngineEffectParameterPointer m_pGainParameter;
37+
EngineEffectParameterPointer m_pClipParameter;
38+
39+
DISALLOW_COPY_AND_ASSIGN(GainEffect);
40+
};

0 commit comments

Comments
 (0)