3 IPlug convoengine example
5 <http://www.taletn.com/>
8 This software is provided 'as-is', without any express or implied
9 warranty. In no event will the authors be held liable for any damages
10 arising from the use of this software.
12 Permission is granted to anyone to use this software for any purpose,
13 including commercial applications, and to alter it and redistribute it
14 freely, subject to the following restrictions:
16 1. The origin of this software must not be misrepresented; you must not
17 claim that you wrote the original software. If you use this software in a
18 product, an acknowledgment in the product documentation would be
19 appreciated but is not required.
20 2. Altered source versions must be plainly marked as such, and must not be
21 misrepresented as being the original software.
22 3. This notice may not be removed or altered from any source distribution.
25 A simple IPlug plug-in effect that shows how to use WDL's fast convolution
32 #include "IPlugConvoEngine.h"
33 #include "IPlug_include_in_plug_src.h"
37 // need xcode/gcc to treat this file as C++ for the Mac RTAS build
38 #include "../../WDL/fft.c"
48 IPlugConvoEngine::IPlugConvoEngine(IPlugInstanceInfo instanceInfo
):
49 IPLUG_CTOR(kNumParams
, 0, instanceInfo
)
56 GetParam(kDry
)->InitDouble("Dry", 1., 0., 1., 0.001);
57 GetParam(kWet
)->InitDouble("Wet", 0.5, 0., 1., 0.001);
59 IGraphics
* pGraphics
= MakeGraphics(this, GUI_WIDTH
, GUI_HEIGHT
);
60 IText
textProps(12, &COLOR_BLACK
, "Verdana", IText::kStyleNormal
, IText::kAlignNear
, 0, IText::kQualityNonAntiAliased
);
61 GenerateKnobGUI(pGraphics
, this, &textProps
, &COLOR_WHITE
, &COLOR_BLACK
, 60, 70);
62 AttachGraphics(pGraphics
);
65 void IPlugConvoEngine::OnParamChange(int paramIdx
)
67 IMutexLock
lock(this);
72 mDry
= GetParam(kDry
)->Value();
76 mWet
= GetParam(kWet
)->Value();
81 void IPlugConvoEngine::Reset()
83 TRACE
; IMutexLock
lock(this);
85 // Detect a change in sample rate.
86 if (GetSampleRate() != mSampleRate
)
88 mSampleRate
= GetSampleRate();
90 // Create a mono impulse response of 250 ms.
91 mImpulse
.SetNumChannels(1);
92 int nSamples
= mImpulse
.SetLength(int(0.250 * mSampleRate
+ 0.5));
95 WDL_FFT_REAL
* buf
= mImpulse
.impulses
[0].Get();
96 memset(buf
, 0, nSamples
* sizeof(WDL_FFT_REAL
));
98 // Set echo taps every ~25 ms.
100 buf
[int(0.1 * (double)nSamples
)] = 0.5;
101 buf
[int(0.2 * (double)nSamples
)] = 0.46875;
102 buf
[int(0.3 * (double)nSamples
)] = 0.4375;
103 buf
[int(0.4 * (double)nSamples
)] = 0.40625;
104 buf
[int(0.5 * (double)nSamples
)] = 0.375;
105 buf
[int(0.6 * (double)nSamples
)] = 0.34375;
106 buf
[int(0.7 * (double)nSamples
)] = 0.3125;
107 buf
[int(0.8 * (double)nSamples
)] = 0.28125;
108 buf
[int(0.9 * (double)nSamples
)] = 0.25;
111 // Tie the impulse response to the convolution engine.
112 mEngine
.SetImpulse(&mImpulse
, 0);
116 void IPlugConvoEngine::ProcessDoubleReplacing(double** inputs
, double** outputs
, int nFrames
)
118 // Send input samples to the convolution engine.
119 #if WDL_FFT_REALSIZE == 8
120 mEngine
.Add(inputs
, nFrames
, 1);
123 // Convert the input samples from doubles to WDL_FFT_REALs.
124 double* in
= inputs
[0];
125 // Use outputs[0] as a temporary buffer.
126 WDL_FFT_REAL
* tmp
= (WDL_FFT_REAL
*)outputs
[0];
127 for (int i
= 0; i
< nFrames
; ++i
) *tmp
++ = *in
++;
128 mEngine
.Add((WDL_FFT_REAL
**)outputs
, nFrames
, 1);
132 double* in
= inputs
[0];
133 double *out_l
= outputs
[0];
134 double *out_r
= outputs
[1];
136 int nAvail
= IPMIN(mEngine
.Avail(nFrames
), nFrames
);
138 // If not enough samples are available yet, then only output the dry
140 for (int i
= 0; i
< nFrames
- nAvail
; ++i
) *out_l
++ = mDry
* *in
++;
142 // Output samples from the convolution engine.
145 // Apply the dry/wet mix (and convert from WDL_FFT_REALs back to
147 WDL_FFT_REAL
* convo
= mEngine
.Get()[0];
148 for (int i
= 0; i
< nAvail
; ++i
) *out_l
++ = *out_r
++ = mDry
* *in
++ + mWet
* *convo
++;
150 // Remove the sample block from the convolution engine's buffer.
151 mEngine
.Advance(nAvail
);