From 3a1579afeee711fb5a7829f28c159e09a7b8990a Mon Sep 17 00:00:00 2001 From: Owen Williams Date: Sat, 4 Jan 2014 23:55:36 -0500 Subject: [PATCH 1/3] First pass at porting SWH plate reverb to Mixxx effect system. --- build/depends.py | 1 + src/effects/effectsmanager.cpp | 20 ++-- src/effects/native/nativebackend.cpp | 2 + src/effects/native/reverbeffect.cpp | 134 ++++++++++++++++++++++++ src/effects/native/reverbeffect.h | 60 +++++++++++ src/effects/native/waveguide_nl.h | 148 +++++++++++++++++++++++++++ 6 files changed, 359 insertions(+), 6 deletions(-) create mode 100644 src/effects/native/reverbeffect.cpp create mode 100644 src/effects/native/reverbeffect.h create mode 100644 src/effects/native/waveguide_nl.h diff --git a/build/depends.py b/build/depends.py index 576269fd0c3..42930a44f90 100644 --- a/build/depends.py +++ b/build/depends.py @@ -558,6 +558,7 @@ def sources(self, build): "effects/native/bitcrushereffect.cpp", "effects/native/flangereffect.cpp", "effects/native/filtereffect.cpp", + "effects/native/reverbeffect.cpp", "engine/effects/engineeffectsmanager.cpp", "engine/effects/engineeffectchain.cpp", diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index 5c3195b8115..ef116ba080f 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -97,25 +97,33 @@ void EffectsManager::setupDefaults() { this, "org.mixxx.effectchain.flanger")); pChain->setName(tr("Flanger")); pChain->setParameter(0.0f); - EffectPointer flanger = instantiateEffect( + EffectPointer pEffect = instantiateEffect( "org.mixxx.effects.flanger"); - pChain->addEffect(flanger); + pChain->addEffect(pEffect); m_pEffectChainManager->addEffectChain(pChain); pChain = EffectChainPointer(new EffectChain( this, "org.mixxx.effectchain.bitcrusher")); pChain->setName(tr("BitCrusher")); pChain->setParameter(0.0f); - flanger = instantiateEffect("org.mixxx.effects.bitcrusher"); - pChain->addEffect(flanger); + pEffect = instantiateEffect("org.mixxx.effects.bitcrusher"); + pChain->addEffect(pEffect); m_pEffectChainManager->addEffectChain(pChain); pChain = EffectChainPointer(new EffectChain( this, "org.mixxx.effectchain.filter")); pChain->setName(tr("Filter")); pChain->setParameter(0.0f); - flanger = instantiateEffect("org.mixxx.effects.filter"); - pChain->addEffect(flanger); + pEffect = instantiateEffect("org.mixxx.effects.filter"); + pChain->addEffect(pEffect); + m_pEffectChainManager->addEffectChain(pChain); + + pChain = EffectChainPointer(new EffectChain( + this, "org.mixxx.effectchain.reverb")); + pChain->setName(tr("Reverb")); + pChain->setParameter(0.0f); + pEffect = instantiateEffect("org.mixxx.effects.reverb"); + pChain->addEffect(pEffect); m_pEffectChainManager->addEffectChain(pChain); } diff --git a/src/effects/native/nativebackend.cpp b/src/effects/native/nativebackend.cpp index 00a4fbd20d3..2b6b9b7e77f 100644 --- a/src/effects/native/nativebackend.cpp +++ b/src/effects/native/nativebackend.cpp @@ -4,12 +4,14 @@ #include "effects/native/flangereffect.h" #include "effects/native/bitcrushereffect.h" #include "effects/native/filtereffect.h" +#include "effects/native/reverbeffect.h" NativeBackend::NativeBackend(QObject* pParent) : EffectsBackend(pParent, tr("Native")) { registerEffect(); registerEffect(); registerEffect(); + registerEffect(); } NativeBackend::~NativeBackend() { diff --git a/src/effects/native/reverbeffect.cpp b/src/effects/native/reverbeffect.cpp new file mode 100644 index 00000000000..fe49a3164ee --- /dev/null +++ b/src/effects/native/reverbeffect.cpp @@ -0,0 +1,134 @@ +#include + +#include "effects/native/reverbeffect.h" +#include "effects/native/waveguide_nl.h" + +#include "mathstuff.h" +#include "sampleutil.h" + +const unsigned int kOutBufSize = 32; + +// static +QString ReverbEffect::getId() { + return "org.mixxx.effects.Reverb"; +} + +// static +EffectManifest ReverbEffect::getManifest() { + EffectManifest manifest; + manifest.setId(getId()); + manifest.setName(QObject::tr("Reverb")); + manifest.setAuthor("The Mixxx Team, SWH Plugins"); + manifest.setVersion("1.0"); + manifest.setDescription("TODO"); + + EffectManifestParameter* time = manifest.addParameter(); + time->setId("time"); + time->setName(QObject::tr("time")); + time->setDescription("Controls the RT60 time of the reverb. Actually " + "controls the size of the plate. The mapping between " + "plate size and RT60 time is just a heuristic, so " + "it's not very accurate."); + time->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); + time->setValueHint(EffectManifestParameter::VALUE_FLOAT); + time->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); + time->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + time->setDefault(0.1); + time->setMinimum(1.0); + time->setMaximum(8.5); + + EffectManifestParameter* damping = manifest.addParameter(); + damping->setId("damping"); + damping->setName(QObject::tr("damping")); + damping->setDescription("Controls the degree that the surface of the plate " + "is damped."); + damping->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); + damping->setValueHint(EffectManifestParameter::VALUE_FLOAT); + damping->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); + damping->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); + damping->setDefault(0.5); + damping->setMinimum(0.0); + damping->setMaximum(1.0); + + return manifest; +} + +ReverbEffect::ReverbEffect(EngineEffect* pEffect, + const EffectManifest& manifest) + : m_pTimeParameter(pEffect->getParameterById("time")), + m_pDampingParameter(pEffect->getParameterById("damping")) { + + m_pWaveguide = (waveguide_nl**)malloc(8 * sizeof(waveguide_nl *)); + m_pWaveguide[0] = waveguide_nl_new(2389, LP_INNER, 0.04f, 0.0f); + m_pWaveguide[1] = waveguide_nl_new(4742, LP_INNER, 0.17f, 0.0f); + m_pWaveguide[2] = waveguide_nl_new(4623, LP_INNER, 0.52f, 0.0f); + m_pWaveguide[3] = waveguide_nl_new(2142, LP_INNER, 0.48f, 0.0f); + m_pWaveguide[4] = waveguide_nl_new(5597, LP_OUTER, 0.32f, 0.0f); + m_pWaveguide[5] = waveguide_nl_new(3692, LP_OUTER, 0.89f, 0.0f); + m_pWaveguide[6] = waveguide_nl_new(5611, LP_OUTER, 0.28f, 0.0f); + m_pWaveguide[7] = waveguide_nl_new(3703, LP_OUTER, 0.29f, 0.0f); + + m_pOut = SampleUtil::alloc(kOutBufSize); +} + +ReverbEffect::~ReverbEffect() { + for (int i = 0; i < 8; i++) { + waveguide_nl_reset(m_pWaveguide[i]); + } + SampleUtil::free(m_pOut); + qDebug() << debugString() << "destroyed"; +} + +void ReverbEffect::process(const QString& group, + const CSAMPLE* pInput, CSAMPLE* pOutput, + const unsigned int numSamples) { + GroupState& group_state = m_groupState[group]; + + CSAMPLE time = m_pTimeParameter ? + m_pTimeParameter->value().toDouble() : 1.0f; + CSAMPLE damping = m_pDampingParameter ? + m_pDampingParameter->value().toDouble() : 0.5f; + + // TODO(owilliams) check ranges? + + unsigned long pos; + const float scale = powf(time * 0.117647f, 1.34f); + const float lpscale = 1.0f - damping * 0.93; + + for (pos=0; pos<8; pos++) { + waveguide_nl_set_delay(m_pWaveguide[pos], + m_pWaveguide[pos]->size * scale); + } + for (pos=0; pos<4; pos++) { + waveguide_nl_set_fc(m_pWaveguide[pos], LP_INNER * lpscale); + } + for (; pos<8; pos++) { + waveguide_nl_set_fc(m_pWaveguide[pos], LP_OUTER * lpscale); + } + + for (pos = 0; pos < numSamples - 1; pos+=2) { + const float alpha = + (m_pOut[0] + m_pOut[2] + m_pOut[4] + m_pOut[6]) * 0.5f + + pInput[pos]; + const float beta = + (m_pOut[1] + m_pOut[9] + m_pOut[14]) * 0.666666666f; + const float gamma = + (m_pOut[3] + m_pOut[8] + m_pOut[11]) * 0.666666666f; + const float delta = + (m_pOut[5] + m_pOut[10] + m_pOut[13]) * 0.666666666f; + const float epsilon = + (m_pOut[7] + m_pOut[12] + m_pOut[15]) * 0.666666666f; + + RUN_WG(0, beta, alpha); + RUN_WG(1, gamma, alpha); + RUN_WG(2, delta, alpha); + RUN_WG(3, epsilon, alpha); + RUN_WG(4, beta, gamma); + RUN_WG(5, gamma, delta); + RUN_WG(6, delta, epsilon); + RUN_WG(7, epsilon, beta); + + pOutput[pos] = beta + pInput[pos]; + pOutput[pos + 1] = beta + pInput[pos + 1]; + } +} diff --git a/src/effects/native/reverbeffect.h b/src/effects/native/reverbeffect.h new file mode 100644 index 00000000000..0de457e3e4c --- /dev/null +++ b/src/effects/native/reverbeffect.h @@ -0,0 +1,60 @@ +// Ported from SWH Plate Reverb 1423. +// This effect is GPL code. + +#ifndef REVERBEFFECT_H +#define REVERBEFFECT_H + +#include + +#include "defs.h" +#include "util.h" +#include "engine/effects/engineeffect.h" +#include "engine/effects/engineeffectparameter.h" +#include "effects/effectprocessor.h" +#include "effects/native/waveguide_nl.h" +#include "sampleutil.h" + +class ReverbEffect : public EffectProcessor { + private: + #define LP_INNER 0.96f + #define LP_OUTER 0.983f + #define RUN_WG(n, junct_a, junct_b) waveguide_nl_process_lin(m_pWaveguide[n], junct_a - m_pOut[n*2+1], junct_b - m_pOut[n*2], m_pOut+n*2, m_pOut+n*2+1) + + public: + ReverbEffect(EngineEffect* pEffect, const EffectManifest& manifest); + virtual ~ReverbEffect(); + + static QString getId(); + static EffectManifest getManifest(); + + // See effectprocessor.h + void process(const QString& group, + const CSAMPLE* pInput, CSAMPLE* pOutput, + const unsigned int numSamples); + + private: + QString debugString() const { + return getId(); + } + + EngineEffectParameter* m_pTimeParameter; + EngineEffectParameter* m_pDampingParameter; + waveguide_nl** m_pWaveguide; + CSAMPLE* m_pOut; + + struct GroupState { + GroupState() + : delayPos(0), + time(0) { + SampleUtil::applyGain(delayBuffer, 0, MAX_BUFFER_LEN); + } + CSAMPLE delayBuffer[MAX_BUFFER_LEN]; + unsigned int delayPos; + unsigned int time; + }; + QMap m_groupState; + + DISALLOW_COPY_AND_ASSIGN(ReverbEffect); +}; + +#endif /* REVERBEFFECT_H */ diff --git a/src/effects/native/waveguide_nl.h b/src/effects/native/waveguide_nl.h new file mode 100644 index 00000000000..70ab23d3a42 --- /dev/null +++ b/src/effects/native/waveguide_nl.h @@ -0,0 +1,148 @@ +#ifndef WAVEGUIDE_NL_H +#define WAVEGUIDE_NL_H + +#include +#include + +struct waveguide_nl { + int size; + float *buffer[2]; + int ptr; + int delay; + float fc; + float lp[2]; + float a1a; + float a1b; + float zm1[2]; +}; + +waveguide_nl *waveguide_nl_new(int size, float fc, float da, float db) +{ + waveguide_nl *wg = (waveguide_nl*)malloc(sizeof(waveguide_nl)); + wg->size = size; + wg->delay = size; + wg->buffer[0] = (float*)calloc(size, sizeof(float)); + wg->buffer[1] = (float*)calloc(size, sizeof(float)); + wg->ptr = 0; + wg->fc = fc; + wg->lp[0] = 0.0f; + wg->lp[1] = 0.0f; + wg->zm1[0] = 0.0f; + wg->zm1[1] = 0.0f; + wg->a1a = (1.0f - da) / (1.0f + da); + wg->a1b = (1.0f - db) / (1.0f + db); + + return wg; +} + +inline void waveguide_nl_reset(waveguide_nl *wg) +{ + memset(wg->buffer[0], 0, wg->size * sizeof(float)); + memset(wg->buffer[1], 0, wg->size * sizeof(float)); + wg->lp[0] = 0.0f; + wg->lp[1] = 0.0f; + wg->zm1[0] = 0.0f; + wg->zm1[1] = 0.0f; +} + +inline void waveguide_nl_free(waveguide_nl *wg) +{ + if (!wg) { + return; + } + free(wg->buffer[0]); + free(wg->buffer[1]); + free(wg); +} + +inline void waveguide_nl_set_delay(waveguide_nl *wg, int delay) +{ + if (delay > wg->size) { + wg->delay = wg->size; + } else if (delay < 1) { + wg->delay = 1; + } else { + wg->delay = delay; + } +} + +inline void waveguide_nl_set_fc(waveguide_nl *wg, float fc) +{ + wg->fc = fc; +} + +inline void waveguide_nl_set_ap(waveguide_nl *wg, float da, float db) +{ + wg->a1a = (1.0f - da) / (1.0f + da); + wg->a1b = (1.0f - db) / (1.0f + db); +} + +inline void waveguide_nl_process_lin(waveguide_nl *wg, float in0, float in1, float *out0, float *out1) +{ + float tmp; + + *out0 = wg->buffer[0][(wg->ptr + wg->delay) % wg->size]; + *out0 = wg->lp[0] * (wg->fc - 1.0f) + wg->fc * *out0; + wg->lp[0] = *out0; + tmp = *out0 * -(wg->a1a) + wg->zm1[0]; + wg->zm1[0] = tmp * wg->a1a + *out0; + *out0 = tmp; + + *out1 = wg->buffer[1][(wg->ptr + wg->delay) % wg->size]; + *out1 = wg->lp[1] * (wg->fc - 1.0f) + wg->fc * *out1; + wg->lp[1] = *out1; + tmp = *out1 * -(wg->a1a) + wg->zm1[1]; + wg->zm1[1] = tmp * wg->a1a + *out1; + *out1 = tmp; + + wg->buffer[0][wg->ptr] = in0; + wg->buffer[1][wg->ptr] = in1; + wg->ptr--; + if (wg->ptr < 0) { + wg->ptr += wg->size; + } +} + +inline void waveguide_nl_process(waveguide_nl *wg, float in0, float in1, float *out0, float *out1) +{ + float tmp; + float a1; + float b; + + *out0 = wg->buffer[0][(wg->ptr + wg->delay) % wg->size]; + *out0 = wg->lp[0] * (wg->fc - 1.0f) + wg->fc * *out0; + wg->lp[0] = *out0; + b = (*out0 + 1.0) * 6.0f; + if (b > 1.0f) { + b = 1.0f; + } else if (b < 0.0f) { + b = 0.0f; + } + a1 = b * wg->a1a + (1.0f - b) * wg->a1b; + tmp = *out0 * -a1 + wg->zm1[0]; + wg->zm1[0] = tmp * a1 + *out0; + *out0 = tmp; + + *out1 = wg->buffer[1][(wg->ptr + wg->delay) % wg->size]; + *out1 = wg->lp[1] * (wg->fc - 1.0f) + wg->fc * *out1; + wg->lp[1] = *out1; + b = (*out1 + 1.0) * 6.0f; + if (b > 1.0f) { + b = 1.0f; + } else if (b < 0.0f) { + b = 0.0f; + } + a1 = b * wg->a1a + (1.0f - b) * wg->a1b; + tmp = *out1 * -a1 + wg->zm1[1]; + wg->zm1[1] = tmp * a1 + *out1; + *out1 = tmp; + + wg->buffer[0][wg->ptr] = in0; + wg->buffer[1][wg->ptr] = in1; + wg->ptr--; + if (wg->ptr < 0) { + wg->ptr += wg->size; + } +} + +#endif From 3d40c4680d415e52aa4e031d404cef44577544e1 Mon Sep 17 00:00:00 2001 From: Owen Williams Date: Sun, 5 Jan 2014 00:00:30 -0500 Subject: [PATCH 2/3] Fix inline issue and typo --- src/effects/native/reverbeffect.cpp | 2 +- src/effects/native/waveguide_nl.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/effects/native/reverbeffect.cpp b/src/effects/native/reverbeffect.cpp index fe49a3164ee..79cec60de5a 100644 --- a/src/effects/native/reverbeffect.cpp +++ b/src/effects/native/reverbeffect.cpp @@ -10,7 +10,7 @@ const unsigned int kOutBufSize = 32; // static QString ReverbEffect::getId() { - return "org.mixxx.effects.Reverb"; + return "org.mixxx.effects.reverb"; } // static diff --git a/src/effects/native/waveguide_nl.h b/src/effects/native/waveguide_nl.h index 70ab23d3a42..dbeca20e191 100644 --- a/src/effects/native/waveguide_nl.h +++ b/src/effects/native/waveguide_nl.h @@ -4,7 +4,7 @@ #include #include -struct waveguide_nl { +typedef struct { int size; float *buffer[2]; int ptr; @@ -14,9 +14,9 @@ struct waveguide_nl { float a1a; float a1b; float zm1[2]; -}; +} waveguide_nl; -waveguide_nl *waveguide_nl_new(int size, float fc, float da, float db) +inline waveguide_nl *waveguide_nl_new(int size, float fc, float da, float db) { waveguide_nl *wg = (waveguide_nl*)malloc(sizeof(waveguide_nl)); wg->size = size; From a1428728e016faebf1bd94fd69fa15732b692e9c Mon Sep 17 00:00:00 2001 From: Owen Williams Date: Sun, 5 Jan 2014 11:51:18 -0500 Subject: [PATCH 3/3] Use GroupState properly. Other notes. --- src/effects/native/reverbeffect.cpp | 74 +++++++++++++++-------------- src/effects/native/reverbeffect.h | 34 +++++++------ 2 files changed, 57 insertions(+), 51 deletions(-) diff --git a/src/effects/native/reverbeffect.cpp b/src/effects/native/reverbeffect.cpp index 79cec60de5a..c8a607d007f 100644 --- a/src/effects/native/reverbeffect.cpp +++ b/src/effects/native/reverbeffect.cpp @@ -6,7 +6,7 @@ #include "mathstuff.h" #include "sampleutil.h" -const unsigned int kOutBufSize = 32; +#define RUN_WG(n, junct_a, junct_b) waveguide_nl_process_lin(group_state.waveguide[n], junct_a - group_state.out[n*2+1], junct_b - group_state.out[n*2], group_state.out+n*2, group_state.out+n*2+1) // static QString ReverbEffect::getId() { @@ -25,29 +25,29 @@ EffectManifest ReverbEffect::getManifest() { EffectManifestParameter* time = manifest.addParameter(); time->setId("time"); time->setName(QObject::tr("time")); - time->setDescription("Controls the RT60 time of the reverb. Actually " - "controls the size of the plate. The mapping between " - "plate size and RT60 time is just a heuristic, so " - "it's not very accurate."); + time->setDescription(QObject::tr("Controls the RT60 time of the reverb. " + "Actually controls the size of the plate. The mapping " + "between plate size and RT60 time is just a " + "heuristic, so it's not very accurate.")); time->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); time->setValueHint(EffectManifestParameter::VALUE_FLOAT); time->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); time->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - time->setDefault(0.1); - time->setMinimum(1.0); + time->setMinimum(0.1); + time->setDefault(1.0); time->setMaximum(8.5); EffectManifestParameter* damping = manifest.addParameter(); damping->setId("damping"); damping->setName(QObject::tr("damping")); - damping->setDescription("Controls the degree that the surface of the plate " - "is damped."); + damping->setDescription(QObject::tr("Controls the degree that the surface " + "of the plate is damped.")); damping->setControlHint(EffectManifestParameter::CONTROL_KNOB_LINEAR); damping->setValueHint(EffectManifestParameter::VALUE_FLOAT); damping->setSemanticHint(EffectManifestParameter::SEMANTIC_UNKNOWN); damping->setUnitsHint(EffectManifestParameter::UNITS_UNKNOWN); - damping->setDefault(0.5); damping->setMinimum(0.0); + damping->setDefault(0.5); damping->setMaximum(1.0); return manifest; @@ -57,32 +57,30 @@ ReverbEffect::ReverbEffect(EngineEffect* pEffect, const EffectManifest& manifest) : m_pTimeParameter(pEffect->getParameterById("time")), m_pDampingParameter(pEffect->getParameterById("damping")) { - - m_pWaveguide = (waveguide_nl**)malloc(8 * sizeof(waveguide_nl *)); - m_pWaveguide[0] = waveguide_nl_new(2389, LP_INNER, 0.04f, 0.0f); - m_pWaveguide[1] = waveguide_nl_new(4742, LP_INNER, 0.17f, 0.0f); - m_pWaveguide[2] = waveguide_nl_new(4623, LP_INNER, 0.52f, 0.0f); - m_pWaveguide[3] = waveguide_nl_new(2142, LP_INNER, 0.48f, 0.0f); - m_pWaveguide[4] = waveguide_nl_new(5597, LP_OUTER, 0.32f, 0.0f); - m_pWaveguide[5] = waveguide_nl_new(3692, LP_OUTER, 0.89f, 0.0f); - m_pWaveguide[6] = waveguide_nl_new(5611, LP_OUTER, 0.28f, 0.0f); - m_pWaveguide[7] = waveguide_nl_new(3703, LP_OUTER, 0.29f, 0.0f); - - m_pOut = SampleUtil::alloc(kOutBufSize); } ReverbEffect::~ReverbEffect() { - for (int i = 0; i < 8; i++) { - waveguide_nl_reset(m_pWaveguide[i]); + for (QMap::iterator it = m_groupState.begin(); + it != m_groupState.end();) { + for (int i = 0; i < 8; i++) { + waveguide_nl_reset((*it)->waveguide[i]); + } + SampleUtil::free((*it)->out); + delete it.value(); + it = m_groupState.erase(it); } - SampleUtil::free(m_pOut); qDebug() << debugString() << "destroyed"; } void ReverbEffect::process(const QString& group, const CSAMPLE* pInput, CSAMPLE* pOutput, const unsigned int numSamples) { - GroupState& group_state = m_groupState[group]; + GroupState* pGroupState = m_groupState.value(group, NULL); + if (pGroupState == NULL) { + pGroupState = new GroupState(); + m_groupState[group] = pGroupState; + } + GroupState& group_state = *pGroupState; CSAMPLE time = m_pTimeParameter ? m_pTimeParameter->value().toDouble() : 1.0f; @@ -96,28 +94,32 @@ void ReverbEffect::process(const QString& group, const float lpscale = 1.0f - damping * 0.93; for (pos=0; pos<8; pos++) { - waveguide_nl_set_delay(m_pWaveguide[pos], - m_pWaveguide[pos]->size * scale); + waveguide_nl_set_delay(group_state.waveguide[pos], + group_state.waveguide[pos]->size * scale); } for (pos=0; pos<4; pos++) { - waveguide_nl_set_fc(m_pWaveguide[pos], LP_INNER * lpscale); + waveguide_nl_set_fc(group_state.waveguide[pos], LP_INNER * lpscale); } for (; pos<8; pos++) { - waveguide_nl_set_fc(m_pWaveguide[pos], LP_OUTER * lpscale); + waveguide_nl_set_fc(group_state.waveguide[pos], LP_OUTER * lpscale); } for (pos = 0; pos < numSamples - 1; pos+=2) { const float alpha = - (m_pOut[0] + m_pOut[2] + m_pOut[4] + m_pOut[6]) * 0.5f - + pInput[pos]; + (group_state.out[0] + group_state.out[2] + + group_state.out[4] + group_state.out[6]) * 0.5f + pInput[pos]; const float beta = - (m_pOut[1] + m_pOut[9] + m_pOut[14]) * 0.666666666f; + (group_state.out[1] + group_state.out[9] + group_state.out[14]) + * 0.666666666f; const float gamma = - (m_pOut[3] + m_pOut[8] + m_pOut[11]) * 0.666666666f; + (group_state.out[3] + group_state.out[8] + group_state.out[11]) + * 0.666666666f; const float delta = - (m_pOut[5] + m_pOut[10] + m_pOut[13]) * 0.666666666f; + (group_state.out[5] + group_state.out[10] + group_state.out[13]) + * 0.666666666f; const float epsilon = - (m_pOut[7] + m_pOut[12] + m_pOut[15]) * 0.666666666f; + (group_state.out[7] + group_state.out[12] + group_state.out[15]) + * 0.666666666f; RUN_WG(0, beta, alpha); RUN_WG(1, gamma, alpha); diff --git a/src/effects/native/reverbeffect.h b/src/effects/native/reverbeffect.h index 0de457e3e4c..81ce62d5e68 100644 --- a/src/effects/native/reverbeffect.h +++ b/src/effects/native/reverbeffect.h @@ -14,12 +14,11 @@ #include "effects/native/waveguide_nl.h" #include "sampleutil.h" -class ReverbEffect : public EffectProcessor { - private: - #define LP_INNER 0.96f - #define LP_OUTER 0.983f - #define RUN_WG(n, junct_a, junct_b) waveguide_nl_process_lin(m_pWaveguide[n], junct_a - m_pOut[n*2+1], junct_b - m_pOut[n*2], m_pOut+n*2, m_pOut+n*2+1) +#define LP_INNER 0.96f +#define LP_OUTER 0.983f +const unsigned int kOutBufSize = 32; +class ReverbEffect : public EffectProcessor { public: ReverbEffect(EngineEffect* pEffect, const EffectManifest& manifest); virtual ~ReverbEffect(); @@ -39,20 +38,25 @@ class ReverbEffect : public EffectProcessor { EngineEffectParameter* m_pTimeParameter; EngineEffectParameter* m_pDampingParameter; - waveguide_nl** m_pWaveguide; - CSAMPLE* m_pOut; struct GroupState { - GroupState() - : delayPos(0), - time(0) { - SampleUtil::applyGain(delayBuffer, 0, MAX_BUFFER_LEN); + GroupState() { + waveguide = (waveguide_nl**)malloc(8 * sizeof(waveguide_nl *)); + waveguide[0] = waveguide_nl_new(2389, LP_INNER, 0.04f, 0.0f); + waveguide[1] = waveguide_nl_new(4742, LP_INNER, 0.17f, 0.0f); + waveguide[2] = waveguide_nl_new(4623, LP_INNER, 0.52f, 0.0f); + waveguide[3] = waveguide_nl_new(2142, LP_INNER, 0.48f, 0.0f); + waveguide[4] = waveguide_nl_new(5597, LP_OUTER, 0.32f, 0.0f); + waveguide[5] = waveguide_nl_new(3692, LP_OUTER, 0.89f, 0.0f); + waveguide[6] = waveguide_nl_new(5611, LP_OUTER, 0.28f, 0.0f); + waveguide[7] = waveguide_nl_new(3703, LP_OUTER, 0.29f, 0.0f); + + out = SampleUtil::alloc(kOutBufSize); } - CSAMPLE delayBuffer[MAX_BUFFER_LEN]; - unsigned int delayPos; - unsigned int time; + waveguide_nl** waveguide; + CSAMPLE* out; }; - QMap m_groupState; + QMap m_groupState; DISALLOW_COPY_AND_ASSIGN(ReverbEffect); };