comparison devuvuzelator-vst.cpp @ 4:d90abfa9585a

* Adaptive method
author Chris Cannam
date Fri, 11 Jun 2010 15:38:44 +0100
parents 8b79175c9f02
children 45bcfa3d5da7
comparison
equal deleted inserted replaced
3:8b79175c9f02 4:d90abfa9585a
10 #include "public.sdk/source/vst2.x/audioeffect.h" 10 #include "public.sdk/source/vst2.x/audioeffect.h"
11 11
12 #define snprintf _snprintf 12 #define snprintf _snprintf
13 #define alloca _alloca 13 #define alloca _alloca
14 14
15 #define FFTSIZE 1024 15 #define FFTSIZE 4096
16 #define WINSIZE 1024
17
18 #include "median.h"
16 19
17 class Devuvuzelator : public AudioEffect 20 class Devuvuzelator : public AudioEffect
18 { 21 {
19 enum { 22 enum {
20 LowParam = 0, 23 FundamentalParam = 1,
21 HighParam = 1, 24 BandwidthParam = 2,
22 FundamentalParam = 2, 25 HarmonicsParam = 3,
23 BandwidthParam = 3, 26 ReductionParam = 4,
24 HarmonicsParam = 4, 27 NumParams = 5
25 ReductionParam = 5,
26 NumParams = 6
27 }; 28 };
28 29
29 public: 30 public:
30 Devuvuzelator(audioMasterCallback cb); 31 Devuvuzelator(audioMasterCallback cb);
31 ~Devuvuzelator(); 32 ~Devuvuzelator();
76 float m_bandwidth; 77 float m_bandwidth;
77 int m_harmonics; 78 int m_harmonics;
78 float m_reduction; 79 float m_reduction;
79 80
80 const int m_fftsize; 81 const int m_fftsize;
82 const int m_winsize;
81 const int m_increment; 83 const int m_increment;
82 int m_fill; 84 int m_fill;
83 int m_read; 85 int m_read;
84 float *m_buffer; 86 float *m_buffer;
85 float *m_outacc; 87 float *m_outacc;
86 double *m_real; 88 double *m_real;
87 double *m_imag; 89 double *m_imag;
88 double *m_window; 90 double *m_window;
91 MedianFilter<double> **m_medians;
89 }; 92 };
90 93
91 // VST params 0->1 94 // VST params 0->1
92 95
93 void 96 void
94 Devuvuzelator::setParameter(VstInt32 index, float value) 97 Devuvuzelator::setParameter(VstInt32 index, float value)
95 { 98 {
96 switch (index) { 99 switch (index) {
97 case 0: m_low = -80 + 80 * value; break; 100 case 0: m_fundamental = 50 + 720 * value; break;
98 case 1: m_high = -80 + 80 * value; break; 101 case 1: m_bandwidth = 20 + 80 * value; break;
99 case 2: m_fundamental = 110 + 440 * value; break; 102 case 2: m_harmonics = int(value * 6 + 0.5); break;
100 case 3: m_bandwidth = 20 + 80 * value; break; 103 case 3: m_reduction = 100 * value; break;
101 case 4: m_harmonics = int(value * 6 + 0.5); break;
102 case 5: m_reduction = 20 * value; break;
103 } 104 }
104 } 105 }
105 106
106 float 107 float
107 Devuvuzelator::getParameter(VstInt32 index) 108 Devuvuzelator::getParameter(VstInt32 index)
108 { 109 {
109 switch (index) { 110 switch (index) {
110 case 0: return (m_low + 80) / 80; 111 case 0: return (m_fundamental - 50) / 720;
111 case 1: return (m_high + 80) / 80; 112 case 1: return (m_bandwidth - 20) / 80;
112 case 2: return (m_fundamental - 110) / 440; 113 case 2: return (m_harmonics / 6.f);
113 case 3: return (m_bandwidth - 20) / 80; 114 case 3: return m_reduction / 100;
114 case 4: return (m_harmonics / 6.f); 115 }
115 case 5: return m_reduction / 20; 116 return 0;
116 }
117 return 0;
118 } 117 }
119 118
120 // NB! The max name length for VST parameter names, labels 119 // NB! The max name length for VST parameter names, labels
121 // (i.e. units) and display values (i.e. string renderings of current 120 // (i.e. units) and display values (i.e. string renderings of current
122 // value) is a rather amazing 8 bytes 121 // value) is a rather amazing 8 bytes
123 122
124 void 123 void
125 Devuvuzelator::getParameterLabel(VstInt32 index, char *label) 124 Devuvuzelator::getParameterLabel(VstInt32 index, char *label)
126 { 125 {
127 const char *units[NumParams] = { 126 const char *units[NumParams] = {
128 "dB",
129 "dB",
130 "Hz", 127 "Hz",
131 "Hz", 128 "Hz",
132 "", 129 "",
133 "dB", 130 "%",
134 }; 131 };
135 132
136 vst_strncpy(label, units[index], kVstMaxParamStrLen); 133 vst_strncpy(label, units[index], kVstMaxParamStrLen);
137 } 134 }
138 135
139 void 136 void
140 Devuvuzelator::getParameterDisplay(VstInt32 index, char *label) 137 Devuvuzelator::getParameterDisplay(VstInt32 index, char *label)
141 { 138 {
142 switch (index) { 139 switch (index) {
143 case 0: snprintf(label, kVstMaxParamStrLen, "%f", m_low); break; 140 case 0: snprintf(label, kVstMaxParamStrLen, "%f", m_fundamental); break;
144 case 1: snprintf(label, kVstMaxParamStrLen, "%f", m_high); break; 141 case 1: snprintf(label, kVstMaxParamStrLen, "%f", m_bandwidth); break;
145 case 2: snprintf(label, kVstMaxParamStrLen, "%f", m_fundamental); break; 142 case 2: snprintf(label, kVstMaxParamStrLen, "%d", m_harmonics); break;
146 case 3: snprintf(label, kVstMaxParamStrLen, "%f", m_bandwidth); break; 143 case 3: snprintf(label, kVstMaxParamStrLen, "%f", m_reduction); break;
147 case 4: snprintf(label, kVstMaxParamStrLen, "%d", m_harmonics); break; 144 }
148 case 5: snprintf(label, kVstMaxParamStrLen, "%f", m_reduction); break;
149 }
150 } 145 }
151 146
152 void 147 void
153 Devuvuzelator::getParameterName(VstInt32 index, char *label) 148 Devuvuzelator::getParameterName(VstInt32 index, char *label)
154 { 149 {
155 const char *names[NumParams] = { 150 const char *names[NumParams] = {
156 "Floor",
157 "Ceiling",
158 "Pitch", 151 "Pitch",
159 "B/W", 152 "B/W",
160 "Partials", 153 "Partials",
161 "Reductn", 154 "Reductn",
162 }; 155 };
167 Devuvuzelator::Devuvuzelator(audioMasterCallback cb) : 160 Devuvuzelator::Devuvuzelator(audioMasterCallback cb) :
168 AudioEffect(cb, 0, NumParams), 161 AudioEffect(cb, 0, NumParams),
169 m_sampleRate(0), 162 m_sampleRate(0),
170 m_input(0), 163 m_input(0),
171 m_output(0), 164 m_output(0),
172 m_low(0),
173 m_high(0),
174 m_fftsize(FFTSIZE), 165 m_fftsize(FFTSIZE),
175 m_increment(m_fftsize/4), 166 m_increment(m_fftsize/4),
176 m_fill(0), 167 m_fill(0),
177 m_read(0) 168 m_read(0)
178 { 169 {
179 m_buffer = new float[m_fftsize]; 170 m_buffer = new float[m_winsize];
180 m_outacc = new float[m_fftsize * 2]; 171 m_outacc = new float[m_winsize * 2];
172 m_window = new double[m_winsize];
181 m_real = new double[m_fftsize]; 173 m_real = new double[m_fftsize];
182 m_imag = new double[m_fftsize]; 174 m_imag = new double[m_fftsize];
183 m_window = new double[m_fftsize]; 175 m_medians = new MedianFilter<double> *[m_fftsize/2+1];
184 176
185 for (int i = 0; i < m_fftsize; ++i) { 177 for (int i = 0; i < m_winsize; ++i) {
186 m_window[i] = 0.5 - 0.5 * cos(2 * M_PI * i / m_fftsize); 178 m_window[i] = 0.5 - 0.5 * cos(2 * M_PI * i / m_winsize);
187 } 179 }
188 180 for (int i = 0; i < m_fftsize/2+1; ++i) {
189 m_low = -40; 181 m_medians[i] = 0;
190 m_high = -20; 182 }
191 m_fundamental = 220; 183
184 m_fundamental = 230;
192 m_bandwidth = 60; 185 m_bandwidth = 60;
193 m_harmonics = 3; 186 m_harmonics = 3;
194 m_reduction = 10; 187 m_reduction = 30;
195 188
196 setUniqueID('qmvz'); 189 setUniqueID('qmvz');
197 setNumInputs(1); 190 setNumInputs(1);
198 setNumOutputs(1); 191 setNumOutputs(1);
199 canProcessReplacing(true); 192 canProcessReplacing(true);
207 delete[] m_buffer; 200 delete[] m_buffer;
208 delete[] m_outacc; 201 delete[] m_outacc;
209 delete[] m_real; 202 delete[] m_real;
210 delete[] m_imag; 203 delete[] m_imag;
211 delete[] m_window; 204 delete[] m_window;
205 for (int i = 0; i < m_fftsize/2+1; ++i) {
206 delete m_medians[i];
207 }
208 delete[] m_medians;
212 } 209 }
213 210
214 void 211 void
215 Devuvuzelator::reset() 212 Devuvuzelator::reset()
216 { 213 {
217 for (int i = 0; i < m_fftsize; ++i) { 214 for (int i = 0; i < m_winsize; ++i) {
218 m_buffer[i] = 0.f; 215 m_buffer[i] = 0.f;
219 } 216 }
220 for (int i = 0; i < m_fftsize*2; ++i) { 217 for (int i = 0; i < m_winsize*2; ++i) {
221 m_outacc[i] = 0.f; 218 m_outacc[i] = 0.f;
222 } 219 }
223 m_fill = 0; 220 m_fill = 0;
224 m_read = 0; 221 m_read = 0;
222 for (int i = 0; i < m_fftsize/2+1; ++i) {
223 if (m_medians[i]) m_medians[i]->reset();
224 }
225 } 225 }
226 226
227 void 227 void
228 Devuvuzelator::runImpl(unsigned long sampleCount) 228 Devuvuzelator::runImpl(unsigned long sampleCount)
229 { 229 {
230 if (!m_input || !m_output) return; 230 if (!m_input || !m_output) return;
231 231
232 int ii = 0; 232 int ii = 0;
233 int oi = 0; 233 int oi = 0;
234 const int sc = sampleCount; 234 const int sc = sampleCount;
235 235
236 while (ii < sc) { 236 while (ii < sc) {
237 237
238 m_output[oi++] = m_outacc[m_read++] / 1.5f; 238 m_output[oi++] = m_outacc[m_read++];
239 239
240 if (m_fill == m_fftsize) { 240 if (m_fill == m_winsize) {
241 241
242 processFrame(); 242 processFrame();
243 243
244 for (int j = m_increment; j < m_fftsize; ++j) { 244 for (int j = m_increment; j < m_winsize; ++j) {
245 m_buffer[j - m_increment] = m_buffer[j]; 245 m_buffer[j - m_increment] = m_buffer[j];
246 } 246 }
247 247
248 for (int j = m_increment; j < m_fftsize*2; ++j) { 248 for (int j = m_increment; j < m_winsize*2; ++j) {
249 m_outacc[j - m_increment] = m_outacc[j]; 249 m_outacc[j - m_increment] = m_outacc[j];
250 } 250 }
251 251
252 for (int j = m_fftsize*2 - m_increment; j < m_fftsize*2; ++j) { 252 for (int j = m_winsize*2 - m_increment; j < m_winsize*2; ++j) {
253 m_outacc[j] = 0.f; 253 m_outacc[j] = 0.f;
254 } 254 }
255 255
256 m_fill -= m_increment; 256 m_fill -= m_increment;
257 m_read -= m_increment; 257 m_read -= m_increment;
263 263
264 void 264 void
265 Devuvuzelator::processFrame() 265 Devuvuzelator::processFrame()
266 { 266 {
267 double *frame = (double *)alloca(m_fftsize * sizeof(double)); 267 double *frame = (double *)alloca(m_fftsize * sizeof(double));
268 int ix = m_fftsize/2;
269 for (int i = 0; i < m_fftsize; ++i) { 268 for (int i = 0; i < m_fftsize; ++i) {
270 frame[ix++] = m_buffer[i] * m_window[i]; 269 frame[i] = 0.0;
270 }
271
272 int ix = m_fftsize - m_winsize/2;
273 while (ix < 0) ix += m_fftsize;
274 for (int i = 0; i < m_winsize; ++i) {
275 frame[ix++] += m_buffer[i] * m_window[i];
271 if (ix == m_fftsize) ix = 0; 276 if (ix == m_fftsize) ix = 0;
272 } 277 }
273 278
274 fft(m_fftsize, false, frame, 0, m_real, m_imag); 279 fft(m_fftsize, false, frame, 0, m_real, m_imag);
275 280
281 } 286 }
282 287
283 double *spare = (double *)alloca(m_fftsize * sizeof(double)); 288 double *spare = (double *)alloca(m_fftsize * sizeof(double));
284 fft(m_fftsize, true, m_real, m_imag, frame, spare); 289 fft(m_fftsize, true, m_real, m_imag, frame, spare);
285 290
286 ix = m_fftsize/2; 291 ix = m_fftsize - m_winsize/2;
287 for (int i = 0; i < m_fftsize; ++i) { 292 while (ix < 0) ix += m_fftsize;
288 m_outacc[m_fftsize + i] += frame[ix++] * m_window[i]; 293 for (int i = 0; i < m_winsize; ++i) {
294 m_outacc[m_winsize + i] += frame[ix++];
289 if (ix == m_fftsize) ix = 0; 295 if (ix == m_fftsize) ix = 0;
290 } 296 }
291 } 297 }
292 298
293 // FFT implementation by Don Cross, public domain. 299 // FFT implementation by Don Cross, public domain.