1 /*
2 rakarrack - a guitar effects software
3
4 Harmonizer.C - Harmonizer
5 Copyright (C) 2008 Josep Andreu
6 Author: Josep Andreu
7
8 Using Stephan M. Bernsee smbPitchShifter engine.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of version 2 of the GNU General Public License
12 as published by the Free Software Foundation.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License (version 2) for more details.
18
19 You should have received a copy of the GNU General Public License
20 (version2) along with this program; if not, write to the Free Software
21 Foundation,
22 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
24 */
25
26
27 #include "Harmonizer.h"
28
29
30
Harmonizer(float * efxoutl_,float * efxoutr_,long int Quality,int DS,int uq,int dq,uint16_t intermediate_bufsize,double sample_rate)31 Harmonizer::Harmonizer (float *efxoutl_, float *efxoutr_, long int Quality, int DS, int uq, int dq,
32 uint16_t intermediate_bufsize, double sample_rate)
33 {
34
35 efxoutl = efxoutl_;
36 efxoutr = efxoutr_;
37 hq = Quality;
38 SAMPLE_RATE = (unsigned int)sample_rate;
39 adjust(DS, intermediate_bufsize);
40 DS_init = 0;
41
42 templ = (float *) malloc (sizeof (float) * intermediate_bufsize);
43 tempr = (float *) malloc (sizeof (float) * intermediate_bufsize);
44
45
46 outi = (float *) malloc (sizeof (float) * intermediate_bufsize);
47 outo = (float *) malloc (sizeof (float) * intermediate_bufsize);
48
49 unsigned int i;
50 for(i=0; i<intermediate_bufsize;i++)
51 {
52 templ[i] = tempr[i] = 0;
53 outi[i] = outo[i] = 0;
54 }
55
56 U_Resample = new Resample(dq);
57 D_Resample = new Resample(uq);
58
59
60 interpbuf = new float[intermediate_bufsize];
61 pl = new AnalogFilter (6, 22000, 1, 0, sample_rate, interpbuf);
62
63 PS = new PitchShifter (window, hq, nfSAMPLE_RATE);
64 PS->ratio = 1.0f;
65
66 Ppreset = 0;
67 PMIDI = 0;
68 mira = 0;
69 setpreset (Ppreset);
70
71
72 cleanup ();
73
74 };
75
76
77
~Harmonizer()78 Harmonizer::~Harmonizer ()
79 {
80 free(templ);
81 free(tempr);
82 free(outi);
83 free(outo);
84 delete U_Resample;
85 delete D_Resample;
86 delete pl;
87 delete PS;
88 delete[] interpbuf;
89
90 };
91
92 void
cleanup()93 Harmonizer::cleanup ()
94 {
95 mira = 0;
96 memset(outi, 0, sizeof(float)*nPERIOD);
97 memset(outo, 0, sizeof(float)*nPERIOD);
98 };
99
100
101 void
applyfilters(float * efxoutl,uint32_t period)102 Harmonizer::applyfilters (float * efxoutl, uint32_t period)
103 {
104 pl->filterout (efxoutl, period);
105 };
106
107
108
109 void
out(float * smpsl,float * smpsr,uint32_t period)110 Harmonizer::out (float *smpsl, float *smpsr, uint32_t period)
111 {
112
113 int i;
114
115 if(!DS_init){
116 adjust(DS_state,period);//readjust now that we know period size
117 }
118 if((DS_state != 0) && (Pinterval !=12)) {
119 U_Resample->out(smpsl,smpsr,templ,tempr,period,u_up);
120 }
121
122
123 for (i = 0; i < nPERIOD; i++) {
124 outi[i] = (templ[i] + tempr[i])*.5;
125 if (outi[i] > 1.0)
126 outi[i] = 1.0f;
127 if (outi[i] < -1.0)
128 outi[i] = -1.0f;
129
130 }
131
132 if ((PMIDI) || (PSELECT))
133 PS->ratio = r_ratio;
134
135 if (Pinterval != 12) {
136 PS->smbPitchShift (PS->ratio, nPERIOD, window, hq, nfSAMPLE_RATE, outi, outo);
137 }
138
139 if((DS_state != 0) && (Pinterval != 12)) {
140 D_Resample->mono_out(outo,templ,nPERIOD,u_down,period);
141 } else {
142 memcpy(templ,smpsl, sizeof(float)*period);
143 }
144
145 applyfilters (templ,period);
146
147 //for (i = 0; i < (signed int)period; i++) {
148 //efxoutl[i] = templ[i] * gain * panning;
149 //efxoutr[i] = templ[i] * gain * (1.0f - panning);
150 //}
151 for (i = 0; i < (signed int)period; i++) {
152 efxoutl[i] = templ[i] * gain * (1.0f - panning);
153 efxoutr[i] = templ[i] * gain * panning;
154 }
155
156 };
157
158
159
160 void
setvolume(int value)161 Harmonizer::setvolume (int value)
162 {
163 this->Pvolume = value;
164 outvolume = (float)Pvolume / 127.0f;
165 };
166
167
168
169 void
setpanning(int value)170 Harmonizer::setpanning (int value)
171 {
172 this->Ppan = value;
173 panning = (float)Ppan / 127.0f;
174 };
175
176
177
178 void
setgain(int value)179 Harmonizer::setgain (int value)
180 {
181 this->Pgain = value;
182 gain = (float)Pgain / 127.0f;
183 gain *=2.0;
184 };
185
186
187 void
setinterval(int value)188 Harmonizer::setinterval (int value)
189 {
190
191 this->Pinterval = value;
192 interval = (float)Pinterval - 12.0f;
193 PS->ratio = powf(2.0f, interval / 12.0f);
194 if (Pinterval % 12 == 0)
195 mira = 0;
196 else
197 mira = 1;
198
199 };
200
201 void
fsetfreq(int value)202 Harmonizer::fsetfreq (int value)
203 {
204
205 fPfreq = value;
206 float tmp = (float)value;
207 pl->setfreq (tmp);
208 }
209
210 void
fsetgain(int value)211 Harmonizer::fsetgain (int value)
212 {
213
214 float tmp;
215
216 this->fPgain = value;
217 tmp = 30.0f * ((float)value - 64.0f) / 64.0f;
218 pl->setgain (tmp);
219
220 }
221
222 void
fsetq(int value)223 Harmonizer::fsetq (int value)
224 {
225
226 float tmp;
227 this->fPq = value;
228 tmp = powf(30.0f, ((float)value - 64.0f) / 64.0f);
229 pl->setq (tmp);
230
231 }
232
233 void
setMIDI(int value)234 Harmonizer::setMIDI (int value)
235 {
236
237 this->PMIDI = value;
238 }
239
240
241 void
adjust(int DS,uint32_t period)242 Harmonizer::adjust(int DS, uint32_t period)
243 {
244
245 DS_state=DS;
246 DS_init = 1;
247 float fSAMPLE_RATE = SAMPLE_RATE;
248 float fPERIOD = period;
249
250
251 switch(DS) {
252
253 case 0:
254 nPERIOD = period;
255 nSAMPLE_RATE = SAMPLE_RATE;
256 nfSAMPLE_RATE = fSAMPLE_RATE;
257 window = 2048;
258 break;
259
260 case 1:
261 nPERIOD = lrintf(fPERIOD*96000.0f/fSAMPLE_RATE);
262 nSAMPLE_RATE = 96000;
263 nfSAMPLE_RATE = 96000.0f;
264 window = 2048;
265 break;
266
267
268 case 2:
269 nPERIOD = lrintf(fPERIOD*48000.0f/fSAMPLE_RATE);
270 nSAMPLE_RATE = 48000;
271 nfSAMPLE_RATE = 48000.0f;
272 window = 2048;
273 break;
274
275 case 3:
276 nPERIOD = lrintf(fPERIOD*44100.0f/fSAMPLE_RATE);
277 nSAMPLE_RATE = 44100;
278 nfSAMPLE_RATE = 44100.0f;
279 window = 2048;
280 break;
281
282 case 4:
283 nPERIOD = lrintf(fPERIOD*32000.0f/fSAMPLE_RATE);
284 nSAMPLE_RATE = 32000;
285 nfSAMPLE_RATE = 32000.0f;
286 window = 2048;
287 break;
288
289 case 5:
290 nPERIOD = lrintf(fPERIOD*22050.0f/fSAMPLE_RATE);
291 nSAMPLE_RATE = 22050;
292 nfSAMPLE_RATE = 22050.0f;
293 window = 1024;
294 break;
295
296 case 6:
297 nPERIOD = lrintf(fPERIOD*16000.0f/fSAMPLE_RATE);
298 nSAMPLE_RATE = 16000;
299 nfSAMPLE_RATE = 16000.0f;
300 window = 1024;
301 break;
302
303 case 7:
304 nPERIOD = lrintf(fPERIOD*12000.0f/fSAMPLE_RATE);
305 nSAMPLE_RATE = 12000;
306 nfSAMPLE_RATE = 12000.0f;
307 window = 512;
308 break;
309
310 case 8:
311 nPERIOD = lrintf(fPERIOD*8000.0f/fSAMPLE_RATE);
312 nSAMPLE_RATE = 8000;
313 nfSAMPLE_RATE = 8000.0f;
314 window = 512;
315 break;
316
317 case 9:
318 nPERIOD = lrintf(fPERIOD*4000.0f/fSAMPLE_RATE);
319 nSAMPLE_RATE = 4000;
320 nfSAMPLE_RATE = 4000.0f;
321 window = 256;
322 break;
323 }
324 u_up= (double)nPERIOD / (double)period;
325 u_down= (double)period / (double)nPERIOD;
326 }
327
328
329
330
331
332 void
setpreset(int npreset)333 Harmonizer::setpreset (int npreset)
334 {
335 const int PRESET_SIZE = 11;
336 const int NUM_PRESETS = 3;
337 int pdata[PRESET_SIZE];
338 int presets[NUM_PRESETS][PRESET_SIZE] = {
339 //Plain
340 {64, 64, 64, 12, 6000, 0, 0, 0, 64, 64, 0},
341 //Octavador
342 {64, 64, 64, 0, 6000, 0, 0, 0, 64, 64, 0},
343 //3mdown
344 {64, 64, 64, 9, 6000, 0, 0, 0, 64, 64, 0}
345 };
346
347
348 if(npreset>NUM_PRESETS-1) {
349
350 Fpre->ReadPreset(14,npreset-NUM_PRESETS+1,pdata);
351 for (int n = 0; n < PRESET_SIZE; n++)
352 changepar (n, pdata[n]);
353 } else {
354
355 for (int n = 0; n < PRESET_SIZE; n++)
356 changepar (n, presets[npreset][n]);
357 }
358
359 Ppreset = npreset;
360
361
362 };
363
364
365
366 void
changepar(int npar,int value)367 Harmonizer::changepar (int npar, int value)
368 {
369
370 switch (npar) {
371 case 0:
372 setvolume (value);
373 break;
374 case 1:
375 setpanning (value);
376 break;
377 case 2:
378 setgain (value);
379 break;
380 case 3:
381 setinterval (value);
382 break;
383 case 4:
384 fsetfreq (value);
385 break;
386 case 5:
387 PSELECT = value;
388 if(!value)
389 setinterval(Pinterval);
390 break;
391 case 6:
392 Pnote = value;
393 break;
394 case 7:
395 Ptype = value;
396 break;
397 case 8:
398 fsetgain (value);
399 break;
400 case 9:
401 fsetq (value);
402 break;
403 case 10:
404 setMIDI (value);
405 if(!value)
406 setinterval(Pinterval);
407 break;
408
409
410
411 }
412
413
414 };
415
416
417 int
getpar(int npar)418 Harmonizer::getpar (int npar)
419 {
420 switch (npar) {
421 case 0:
422 return (Pvolume);
423 break;
424 case 1:
425 return (Ppan);
426 break;
427 case 2:
428 return (Pgain);
429 break;
430 case 3:
431 return (Pinterval);
432 break;
433 case 4:
434 return (fPfreq);
435 break;
436 case 5:
437 return (PSELECT);
438 break;
439 case 6:
440 return (Pnote);
441 break;
442 case 7:
443 return (Ptype);
444 break;
445 case 8:
446 return (fPgain);
447 break;
448 case 9:
449 return (fPq);
450 break;
451 case 10:
452 return (PMIDI);
453 break;
454 default:
455 return (0);
456
457 }
458
459 };
460