|
| 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 | +} |
0 commit comments