ConvoEngine: Make max channel counts configurable.
[wdl/wdl-ol.git] / IPlugExamples / IPlugConvoEngine / IPlugConvoEngine.cpp
blob4befb27c91ec2ad575358bbd3b93d45151eeb49a
1 /*
3 IPlug convoengine example
4 (c) Theo Niessink 2010
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
26 engine.
30 // WDL-OL Version
32 #include "IPlugConvoEngine.h"
33 #include "IPlug_include_in_plug_src.h"
34 #include "IAutoGUI.h"
36 #ifdef OS_OSX
37 // need xcode/gcc to treat this file as C++ for the Mac RTAS build
38 #include "../../WDL/fft.c"
39 #endif
41 enum EParams
43 kDry,
44 kWet,
45 kNumParams
48 IPlugConvoEngine::IPlugConvoEngine(IPlugInstanceInfo instanceInfo):
49 IPLUG_CTOR(kNumParams, 0, instanceInfo)
50 , mSampleRate(0.)
51 , mWet(1.)
52 , mDry(0.)
54 TRACE;
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);
69 switch (paramIdx)
71 case kDry:
72 mDry = GetParam(kDry)->Value();
73 break;
75 case kWet:
76 mWet = GetParam(kWet)->Value();
77 break;
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));
93 if (nSamples > 0)
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.
99 buf[0] = 0.5;
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);
121 #else
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);
130 #endif
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
139 // signal.
140 for (int i = 0; i < nFrames - nAvail; ++i) *out_l++ = mDry * *in++;
142 // Output samples from the convolution engine.
143 if (nAvail > 0)
145 // Apply the dry/wet mix (and convert from WDL_FFT_REALs back to
146 // doubles).
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);