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