/* ZynAddSubFX - a software synthesizer OscilGen.cpp - Waveform generator for ADnote Copyright (C) 2002-2005 Nasca Octavian Paul Author: Nasca Octavian Paul This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License (version 2 or later) for more details. You should have received a copy of the GNU General Public License (version 2) along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "OscilGen.h" #include "../Effects/Distorsion.h" OscilGen::OscilGen(FFTwrapper *fft_, Resonance *res_):Presets() { setpresettype("Poscilgen"); fft = fft_; res = res_; tmpsmps = new REALTYPE[OSCIL_SIZE]; newFFTFREQS(&outoscilFFTfreqs, OSCIL_SIZE / 2); newFFTFREQS(&oscilFFTfreqs, OSCIL_SIZE / 2); newFFTFREQS(&basefuncFFTfreqs, OSCIL_SIZE / 2); randseed = 1; ADvsPAD = false; defaults(); } OscilGen::~OscilGen() { delete[] tmpsmps; deleteFFTFREQS(&outoscilFFTfreqs); deleteFFTFREQS(&basefuncFFTfreqs); deleteFFTFREQS(&oscilFFTfreqs); } void OscilGen::defaults() { oldbasefunc = 0; oldbasepar = 64; oldhmagtype = 0; oldwaveshapingfunction = 0; oldwaveshaping = 64; oldbasefuncmodulation = 0; oldharmonicshift = 0; oldbasefuncmodulationpar1 = 0; oldbasefuncmodulationpar2 = 0; oldbasefuncmodulationpar3 = 0; oldmodulation = 0; oldmodulationpar1 = 0; oldmodulationpar2 = 0; oldmodulationpar3 = 0; for(int i = 0; i < MAX_AD_HARMONICS; i++) { hmag[i] = 0.0; hphase[i] = 0.0; Phmag[i] = 64; Phphase[i] = 64; } Phmag[0] = 127; Phmagtype = 0; if(ADvsPAD) Prand = 127; //max phase randomness (usefull if the oscil will be imported to a ADsynth from a PADsynth else Prand = 64; //no randomness Pcurrentbasefunc = 0; Pbasefuncpar = 64; Pbasefuncmodulation = 0; Pbasefuncmodulationpar1 = 64; Pbasefuncmodulationpar2 = 64; Pbasefuncmodulationpar3 = 32; Pmodulation = 0; Pmodulationpar1 = 64; Pmodulationpar2 = 64; Pmodulationpar3 = 32; Pwaveshapingfunction = 0; Pwaveshaping = 64; Pfiltertype = 0; Pfilterpar1 = 64; Pfilterpar2 = 64; Pfilterbeforews = 0; Psatype = 0; Psapar = 64; Pamprandpower = 64; Pamprandtype = 0; Pharmonicshift = 0; Pharmonicshiftfirst = 0; Padaptiveharmonics = 0; Padaptiveharmonicspower = 100; Padaptiveharmonicsbasefreq = 128; Padaptiveharmonicspar = 50; for(int i = 0; i < OSCIL_SIZE / 2; i++) { oscilFFTfreqs.s[i] = 0.0; oscilFFTfreqs.c[i] = 0.0; basefuncFFTfreqs.s[i] = 0.0; basefuncFFTfreqs.c[i] = 0.0; } oscilprepared = 0; oldfilterpars = 0; oldsapars = 0; prepare(); } void OscilGen::convert2sine(int magtype) { REALTYPE mag[MAX_AD_HARMONICS], phase[MAX_AD_HARMONICS]; REALTYPE oscil[OSCIL_SIZE]; FFTFREQS freqs; newFFTFREQS(&freqs, OSCIL_SIZE / 2); get(oscil, -1.0); FFTwrapper *fft = new FFTwrapper(OSCIL_SIZE); fft->smps2freqs(oscil, freqs); delete (fft); REALTYPE max = 0.0; mag[0] = 0; phase[0] = 0; for(int i = 0; i < MAX_AD_HARMONICS; i++) { mag[i] = sqrt(pow(freqs.s[i + 1], 2) + pow(freqs.c[i + 1], 2.0)); phase[i] = atan2(freqs.c[i + 1], freqs.s[i + 1]); if(max < mag[i]) max = mag[i]; } if(max < 0.00001) max = 1.0; defaults(); for(int i = 0; i < MAX_AD_HARMONICS - 1; i++) { REALTYPE newmag = mag[i] / max; REALTYPE newphase = phase[i]; Phmag[i] = (int) ((newmag) * 64.0) + 64; Phphase[i] = 64 - (int) (64.0 * newphase / PI); if(Phphase[i] > 127) Phphase[i] = 127; if(Phmag[i] == 64) Phphase[i] = 64; } deleteFFTFREQS(&freqs); prepare(); } /* * Base Functions - START */ REALTYPE OscilGen::basefunc_pulse(REALTYPE x, REALTYPE a) { return (fmod(x, 1.0) < a) ? -1.0 : 1.0; } REALTYPE OscilGen::basefunc_saw(REALTYPE x, REALTYPE a) { if(a < 0.00001) a = 0.00001; else if(a > 0.99999) a = 0.99999; x = fmod(x, 1); if(x < a) return x / a * 2.0 - 1.0; else return (1.0 - x) / (1.0 - a) * 2.0 - 1.0; } REALTYPE OscilGen::basefunc_triangle(REALTYPE x, REALTYPE a) { x = fmod(x + 0.25, 1); a = 1 - a; if(a < 0.00001) a = 0.00001; if(x < 0.5) x = x * 4 - 1.0; else x = (1.0 - x) * 4 - 1.0; x /= -a; if(x < -1.0) x = -1.0; if(x > 1.0) x = 1.0; return x; } REALTYPE OscilGen::basefunc_power(REALTYPE x, REALTYPE a) { x = fmod(x, 1); if(a < 0.00001) a = 0.00001; else if(a > 0.99999) a = 0.99999; return pow(x, exp((a - 0.5) * 10.0)) * 2.0 - 1.0; } REALTYPE OscilGen::basefunc_gauss(REALTYPE x, REALTYPE a) { x = fmod(x, 1) * 2.0 - 1.0; if(a < 0.00001) a = 0.00001; return exp(-x * x * (exp(a * 8) + 5.0)) * 2.0 - 1.0; } REALTYPE OscilGen::basefunc_diode(REALTYPE x, REALTYPE a) { if(a < 0.00001) a = 0.00001; else if(a > 0.99999) a = 0.99999; a = a * 2.0 - 1.0; x = cos((x + 0.5) * 2.0 * PI) - a; if(x < 0.0) x = 0.0; return x / (1.0 - a) * 2 - 1.0; } REALTYPE OscilGen::basefunc_abssine(REALTYPE x, REALTYPE a) { x = fmod(x, 1); if(a < 0.00001) a = 0.00001; else if(a > 0.99999) a = 0.99999; return sin(pow(x, exp((a - 0.5) * 5.0)) * PI) * 2.0 - 1.0; } REALTYPE OscilGen::basefunc_pulsesine(REALTYPE x, REALTYPE a) { if(a < 0.00001) a = 0.00001; x = (fmod(x, 1) - 0.5) * exp((a - 0.5) * log(128)); if(x < -0.5) x = -0.5; else if(x > 0.5) x = 0.5; x = sin(x * PI * 2.0); return x; } REALTYPE OscilGen::basefunc_stretchsine(REALTYPE x, REALTYPE a) { x = fmod(x + 0.5, 1) * 2.0 - 1.0; a = (a - 0.5) * 4; if(a > 0.0) a *= 2; a = pow(3.0, a); REALTYPE b = pow(fabs(x), a); if(x < 0) b = -b; return -sin(b * PI); } REALTYPE OscilGen::basefunc_chirp(REALTYPE x, REALTYPE a) { x = fmod(x, 1.0) * 2.0 * PI; a = (a - 0.5) * 4; if(a < 0.0) a *= 2.0; a = pow(3.0, a); return sin(x / 2.0) * sin(a * x * x); } REALTYPE OscilGen::basefunc_absstretchsine(REALTYPE x, REALTYPE a) { x = fmod(x + 0.5, 1) * 2.0 - 1.0; a = (a - 0.5) * 9; a = pow(3.0, a); REALTYPE b = pow(fabs(x), a); if(x < 0) b = -b; return -pow(sin(b * PI), 2); } REALTYPE OscilGen::basefunc_chebyshev(REALTYPE x, REALTYPE a) { a = a * a * a * 30.0 + 1.0; return cos(acos(x * 2.0 - 1.0) * a); } REALTYPE OscilGen::basefunc_sqr(REALTYPE x, REALTYPE a) { a = a * a * a * a * 160.0 + 0.001; return -atan(sin(x * 2.0 * PI) * a); } /* * Base Functions - END */ /* * Get the base function */ void OscilGen::getbasefunction(REALTYPE *smps) { int i; REALTYPE par = (Pbasefuncpar + 0.5) / 128.0; if(Pbasefuncpar == 64) par = 0.5; REALTYPE basefuncmodulationpar1 = Pbasefuncmodulationpar1 / 127.0, basefuncmodulationpar2 = Pbasefuncmodulationpar2 / 127.0, basefuncmodulationpar3 = Pbasefuncmodulationpar3 / 127.0; switch(Pbasefuncmodulation) { case 1: basefuncmodulationpar1 = (pow(2, basefuncmodulationpar1 * 5.0) - 1.0) / 10.0; basefuncmodulationpar3 = floor((pow(2, basefuncmodulationpar3 * 5.0) - 1.0)); if(basefuncmodulationpar3 < 0.9999) basefuncmodulationpar3 = -1.0; break; case 2: basefuncmodulationpar1 = (pow(2, basefuncmodulationpar1 * 5.0) - 1.0) / 10.0; basefuncmodulationpar3 = 1.0 + floor((pow(2, basefuncmodulationpar3 * 5.0) - 1.0)); break; case 3: basefuncmodulationpar1 = (pow(2, basefuncmodulationpar1 * 7.0) - 1.0) / 10.0; basefuncmodulationpar3 = 0.01 + (pow(2, basefuncmodulationpar3 * 16.0) - 1.0) / 10.0; break; } // printf("%.5f %.5f\n",basefuncmodulationpar1,basefuncmodulationpar3); for(i = 0; i < OSCIL_SIZE; i++) { REALTYPE t = i * 1.0 / OSCIL_SIZE; switch(Pbasefuncmodulation) { case 1: t = t * basefuncmodulationpar3 + sin( (t + basefuncmodulationpar2) * 2.0 * PI) * basefuncmodulationpar1; //rev break; case 2: t = t + sin( (t * basefuncmodulationpar3 + basefuncmodulationpar2) * 2.0 * PI) * basefuncmodulationpar1; //sine break; case 3: t = t + pow((1.0 - cos( (t + basefuncmodulationpar2) * 2.0 * PI)) * 0.5, basefuncmodulationpar3) * basefuncmodulationpar1; //power break; } t = t - floor(t); switch(Pcurrentbasefunc) { case 1: smps[i] = basefunc_triangle(t, par); break; case 2: smps[i] = basefunc_pulse(t, par); break; case 3: smps[i] = basefunc_saw(t, par); break; case 4: smps[i] = basefunc_power(t, par); break; case 5: smps[i] = basefunc_gauss(t, par); break; case 6: smps[i] = basefunc_diode(t, par); break; case 7: smps[i] = basefunc_abssine(t, par); break; case 8: smps[i] = basefunc_pulsesine(t, par); break; case 9: smps[i] = basefunc_stretchsine(t, par); break; case 10: smps[i] = basefunc_chirp(t, par); break; case 11: smps[i] = basefunc_absstretchsine(t, par); break; case 12: smps[i] = basefunc_chebyshev(t, par); break; case 13: smps[i] = basefunc_sqr(t, par); break; default: smps[i] = -sin(2.0 * PI * i / OSCIL_SIZE); } } } /* * Filter the oscillator */ void OscilGen::oscilfilter() { if(Pfiltertype == 0) return; REALTYPE par = 1.0 - Pfilterpar1 / 128.0; REALTYPE par2 = Pfilterpar2 / 127.0; REALTYPE max = 0.0, tmp = 0.0, p2, x; for(int i = 1; i < OSCIL_SIZE / 2; i++) { REALTYPE gain = 1.0; switch(Pfiltertype) { case 1: gain = pow(1.0 - par * par * par * 0.99, i); //lp tmp = par2 * par2 * par2 * par2 * 0.5 + 0.0001; if(gain < tmp) gain = pow(gain, 10.0) / pow(tmp, 9.0); break; case 2: gain = 1.0 - pow(1.0 - par * par, i + 1); //hp1 gain = pow(gain, par2 * 2.0 + 0.1); break; case 3: if(par < 0.2) par = par * 0.25 + 0.15; gain = 1.0 - pow(1.0 - par * par * 0.999 + 0.001, i * 0.05 * i + 1.0); //hp1b tmp = pow(5.0, par2 * 2.0); gain = pow(gain, tmp); break; case 4: gain = i + 1 - pow(2, (1.0 - par) * 7.5); //bp1 gain = 1.0 / (1.0 + gain * gain / (i + 1.0)); tmp = pow(5.0, par2 * 2.0); gain = pow(gain, tmp); if(gain < 1e-5) gain = 1e-5; break; case 5: gain = i + 1 - pow(2, (1.0 - par) * 7.5); //bs1 gain = pow(atan(gain / (i / 10.0 + 1)) / 1.57, 6); gain = pow(gain, par2 * par2 * 3.9 + 0.1); break; case 6: tmp = pow(par2, 0.33); gain = (i + 1 > pow(2, (1.0 - par) * 10) ? 0.0 : 1.0) * par2 + (1.0 - par2); //lp2 break; case 7: tmp = pow(par2, 0.33); //tmp=1.0-(1.0-par2)*(1.0-par2); gain = (i + 1 > pow(2, (1.0 - par) * 7) ? 1.0 : 0.0) * par2 + (1.0 - par2); //hp2 if(Pfilterpar1 == 0) gain = 1.0; break; case 8: tmp = pow(par2, 0.33); //tmp=1.0-(1.0-par2)*(1.0-par2); gain = (fabs(pow(2, (1.0 - par) * 7) - i) > i / 2 + 1 ? 0.0 : 1.0) * par2 + (1.0 - par2); //bp2 break; case 9: tmp = pow(par2, 0.33); gain = (fabs(pow(2, (1.0 - par) * 7) - i) < i / 2 + 1 ? 0.0 : 1.0) * par2 + (1.0 - par2); //bs2 break; case 10: tmp = pow(5.0, par2 * 2.0 - 1.0); tmp = pow(i / 32.0, tmp) * 32.0; if(Pfilterpar2 == 64) tmp = i; gain = cos(par * par * PI / 2.0 * tmp); //cos gain *= gain; break; case 11: tmp = pow(5.0, par2 * 2.0 - 1.0); tmp = pow(i / 32.0, tmp) * 32.0; if(Pfilterpar2 == 64) tmp = i; gain = sin(par * par * PI / 2.0 * tmp); //sin gain *= gain; break; case 12: p2 = 1.0 - par + 0.2; x = i / (64.0 * p2 * p2); if(x < 0.0) x = 0.0; else if(x > 1.0) x = 1.0; tmp = pow(1.0 - par2, 2.0); gain = cos(x * PI) * (1.0 - tmp) + 1.01 + tmp; //low shelf break; case 13: tmp = (int) (pow(2.0, (1.0 - par) * 7.2)); gain = 1.0; if(i == (int) (tmp)) gain = pow(2.0, par2 * par2 * 8.0); break; } oscilFFTfreqs.s[i] *= gain; oscilFFTfreqs.c[i] *= gain; REALTYPE tmp = oscilFFTfreqs.s[i] * oscilFFTfreqs.s[i] + oscilFFTfreqs.c[i] * oscilFFTfreqs.c[i]; if(max < tmp) max = tmp; } max = sqrt(max); if(max < 1e-10) max = 1.0; REALTYPE imax = 1.0 / max; for(int i = 1; i < OSCIL_SIZE / 2; i++) { oscilFFTfreqs.s[i] *= imax; oscilFFTfreqs.c[i] *= imax; } } /* * Change the base function */ void OscilGen::changebasefunction() { if(Pcurrentbasefunc != 0) { getbasefunction(tmpsmps); fft->smps2freqs(tmpsmps, basefuncFFTfreqs); basefuncFFTfreqs.c[0] = 0.0; } else { for(int i = 0; i < OSCIL_SIZE / 2; i++) { basefuncFFTfreqs.s[i] = 0.0; basefuncFFTfreqs.c[i] = 0.0; } //in this case basefuncFFTfreqs_ are not used } oscilprepared = 0; oldbasefunc = Pcurrentbasefunc; oldbasepar = Pbasefuncpar; oldbasefuncmodulation = Pbasefuncmodulation; oldbasefuncmodulationpar1 = Pbasefuncmodulationpar1; oldbasefuncmodulationpar2 = Pbasefuncmodulationpar2; oldbasefuncmodulationpar3 = Pbasefuncmodulationpar3; } /* * Waveshape */ void OscilGen::waveshape() { int i; oldwaveshapingfunction = Pwaveshapingfunction; oldwaveshaping = Pwaveshaping; if(Pwaveshapingfunction == 0) return; oscilFFTfreqs.c[0] = 0.0; //remove the DC //reduce the amplitude of the freqs near the nyquist for(i = 1; i < OSCIL_SIZE / 8; i++) { REALTYPE tmp = i / (OSCIL_SIZE / 8.0); oscilFFTfreqs.s[OSCIL_SIZE / 2 - i] *= tmp; oscilFFTfreqs.c[OSCIL_SIZE / 2 - i] *= tmp; } fft->freqs2smps(oscilFFTfreqs, tmpsmps); //Normalize REALTYPE max = 0.0; for(i = 0; i < OSCIL_SIZE; i++) if(max < fabs(tmpsmps[i])) max = fabs(tmpsmps[i]); if(max < 0.00001) max = 1.0; max = 1.0 / max; for(i = 0; i < OSCIL_SIZE; i++) tmpsmps[i] *= max; //Do the waveshaping waveshapesmps(OSCIL_SIZE, tmpsmps, Pwaveshapingfunction, Pwaveshaping); fft->smps2freqs(tmpsmps, oscilFFTfreqs); //perform FFT } /* * Do the Frequency Modulation of the Oscil */ void OscilGen::modulation() { int i; oldmodulation = Pmodulation; oldmodulationpar1 = Pmodulationpar1; oldmodulationpar2 = Pmodulationpar2; oldmodulationpar3 = Pmodulationpar3; if(Pmodulation == 0) return; REALTYPE modulationpar1 = Pmodulationpar1 / 127.0, modulationpar2 = 0.5 - Pmodulationpar2 / 127.0, modulationpar3 = Pmodulationpar3 / 127.0; switch(Pmodulation) { case 1: modulationpar1 = (pow(2, modulationpar1 * 7.0) - 1.0) / 100.0; modulationpar3 = floor((pow(2, modulationpar3 * 5.0) - 1.0)); if(modulationpar3 < 0.9999) modulationpar3 = -1.0; break; case 2: modulationpar1 = (pow(2, modulationpar1 * 7.0) - 1.0) / 100.0; modulationpar3 = 1.0 + floor((pow(2, modulationpar3 * 5.0) - 1.0)); break; case 3: modulationpar1 = (pow(2, modulationpar1 * 9.0) - 1.0) / 100.0; modulationpar3 = 0.01 + (pow(2, modulationpar3 * 16.0) - 1.0) / 10.0; break; } oscilFFTfreqs.c[0] = 0.0; //remove the DC //reduce the amplitude of the freqs near the nyquist for(i = 1; i < OSCIL_SIZE / 8; i++) { REALTYPE tmp = i / (OSCIL_SIZE / 8.0); oscilFFTfreqs.s[OSCIL_SIZE / 2 - i] *= tmp; oscilFFTfreqs.c[OSCIL_SIZE / 2 - i] *= tmp; } fft->freqs2smps(oscilFFTfreqs, tmpsmps); int extra_points = 2; REALTYPE *in = new REALTYPE[OSCIL_SIZE + extra_points]; //Normalize REALTYPE max = 0.0; for(i = 0; i < OSCIL_SIZE; i++) if(max < fabs(tmpsmps[i])) max = fabs(tmpsmps[i]); if(max < 0.00001) max = 1.0; max = 1.0 / max; for(i = 0; i < OSCIL_SIZE; i++) in[i] = tmpsmps[i] * max; for(i = 0; i < extra_points; i++) in[i + OSCIL_SIZE] = tmpsmps[i] * max; //Do the modulation for(i = 0; i < OSCIL_SIZE; i++) { REALTYPE t = i * 1.0 / OSCIL_SIZE; switch(Pmodulation) { case 1: t = t * modulationpar3 + sin((t + modulationpar2) * 2.0 * PI) * modulationpar1; //rev break; case 2: t = t + sin((t * modulationpar3 + modulationpar2) * 2.0 * PI) * modulationpar1; //sine break; case 3: t = t + pow((1.0 - cos( (t + modulationpar2) * 2.0 * PI)) * 0.5, modulationpar3) * modulationpar1; //power break; } t = (t - floor(t)) * OSCIL_SIZE; int poshi = (int) t; REALTYPE poslo = t - floor(t); tmpsmps[i] = in[poshi] * (1.0 - poslo) + in[poshi + 1] * poslo; } delete [] in; fft->smps2freqs(tmpsmps, oscilFFTfreqs); //perform FFT } /* * Adjust the spectrum */ void OscilGen::spectrumadjust() { if(Psatype == 0) return; REALTYPE par = Psapar / 127.0; switch(Psatype) { case 1: par = 1.0 - par * 2.0; if(par >= 0.0) par = pow(5.0, par); else par = pow(8.0, par); break; case 2: par = pow(10.0, (1.0 - par) * 3.0) * 0.25; break; case 3: par = pow(10.0, (1.0 - par) * 3.0) * 0.25; break; } REALTYPE max = 0.0; for(int i = 0; i < OSCIL_SIZE / 2; i++) { REALTYPE tmp = pow(oscilFFTfreqs.c[i], 2) + pow(oscilFFTfreqs.s[i], 2.0); if(max < tmp) max = tmp; } max = sqrt(max) / OSCIL_SIZE * 2.0; if(max < 1e-8) max = 1.0; for(int i = 0; i < OSCIL_SIZE / 2; i++) { REALTYPE mag = sqrt(pow(oscilFFTfreqs.s[i], 2) + pow(oscilFFTfreqs.c[i], 2.0)) / max; REALTYPE phase = atan2(oscilFFTfreqs.s[i], oscilFFTfreqs.c[i]); switch(Psatype) { case 1: mag = pow(mag, par); break; case 2: if(mag < par) mag = 0.0; break; case 3: mag /= par; if(mag > 1.0) mag = 1.0; break; } oscilFFTfreqs.c[i] = mag * cos(phase); oscilFFTfreqs.s[i] = mag * sin(phase); } } void OscilGen::shiftharmonics() { if(Pharmonicshift == 0) return; REALTYPE hc, hs; int harmonicshift = -Pharmonicshift; if(harmonicshift > 0) { for(int i = OSCIL_SIZE / 2 - 2; i >= 0; i--) { int oldh = i - harmonicshift; if(oldh < 0) { hc = 0.0; hs = 0.0; } else { hc = oscilFFTfreqs.c[oldh + 1]; hs = oscilFFTfreqs.s[oldh + 1]; } oscilFFTfreqs.c[i + 1] = hc; oscilFFTfreqs.s[i + 1] = hs; } } else { for(int i = 0; i < OSCIL_SIZE / 2 - 1; i++) { int oldh = i + abs(harmonicshift); if(oldh >= (OSCIL_SIZE / 2 - 1)) { hc = 0.0; hs = 0.0; } else { hc = oscilFFTfreqs.c[oldh + 1]; hs = oscilFFTfreqs.s[oldh + 1]; if(fabs(hc) < 0.000001) hc = 0.0; if(fabs(hs) < 0.000001) hs = 0.0; } oscilFFTfreqs.c[i + 1] = hc; oscilFFTfreqs.s[i + 1] = hs; } } oscilFFTfreqs.c[0] = 0.0; } /* * Prepare the Oscillator */ void OscilGen::prepare() { int i, j, k; REALTYPE a, b, c, d, hmagnew; if((oldbasepar != Pbasefuncpar) || (oldbasefunc != Pcurrentbasefunc) || (oldbasefuncmodulation != Pbasefuncmodulation) || (oldbasefuncmodulationpar1 != Pbasefuncmodulationpar1) || (oldbasefuncmodulationpar2 != Pbasefuncmodulationpar2) || (oldbasefuncmodulationpar3 != Pbasefuncmodulationpar3)) changebasefunction(); for(i = 0; i < MAX_AD_HARMONICS; i++) hphase[i] = (Phphase[i] - 64.0) / 64.0 * PI / (i + 1); for(i = 0; i < MAX_AD_HARMONICS; i++) { hmagnew = 1.0 - fabs(Phmag[i] / 64.0 - 1.0); switch(Phmagtype) { case 1: hmag[i] = exp(hmagnew * log(0.01)); break; case 2: hmag[i] = exp(hmagnew * log(0.001)); break; case 3: hmag[i] = exp(hmagnew * log(0.0001)); break; case 4: hmag[i] = exp(hmagnew * log(0.00001)); break; default: hmag[i] = 1.0 - hmagnew; break; } if(Phmag[i] < 64) hmag[i] = -hmag[i]; } //remove the harmonics where Phmag[i]==64 for(i = 0; i < MAX_AD_HARMONICS; i++) if(Phmag[i] == 64) hmag[i] = 0.0; for(i = 0; i < OSCIL_SIZE / 2; i++) { oscilFFTfreqs.c[i] = 0.0; oscilFFTfreqs.s[i] = 0.0; } if(Pcurrentbasefunc == 0) { //the sine case for(i = 0; i < MAX_AD_HARMONICS; i++) { oscilFFTfreqs.c[i + 1] = -hmag[i] * sin(hphase[i] * (i + 1)) / 2.0; oscilFFTfreqs.s[i + 1] = hmag[i] * cos(hphase[i] * (i + 1)) / 2.0; } } else { for(j = 0; j < MAX_AD_HARMONICS; j++) { if(Phmag[j] == 64) continue; for(i = 1; i < OSCIL_SIZE / 2; i++) { k = i * (j + 1); if(k >= OSCIL_SIZE / 2) break; a = basefuncFFTfreqs.c[i]; b = basefuncFFTfreqs.s[i]; c = hmag[j] * cos(hphase[j] * k); d = hmag[j] * sin(hphase[j] * k); oscilFFTfreqs.c[k] += a * c - b * d; oscilFFTfreqs.s[k] += a * d + b * c; } } } if(Pharmonicshiftfirst != 0) shiftharmonics(); if(Pfilterbeforews == 0) { waveshape(); oscilfilter(); } else { oscilfilter(); waveshape(); } modulation(); spectrumadjust(); if(Pharmonicshiftfirst == 0) shiftharmonics(); oscilFFTfreqs.c[0] = 0.0; oldhmagtype = Phmagtype; oldharmonicshift = Pharmonicshift + Pharmonicshiftfirst * 256; oscilprepared = 1; } void OscilGen::adaptiveharmonic(FFTFREQS f, REALTYPE freq) { if((Padaptiveharmonics == 0) /*||(freq<1.0)*/) return; if(freq < 1.0) freq = 440.0; FFTFREQS inf; newFFTFREQS(&inf, OSCIL_SIZE / 2); for(int i = 0; i < OSCIL_SIZE / 2; i++) { inf.s[i] = f.s[i]; inf.c[i] = f.c[i]; f.s[i] = 0.0; f.c[i] = 0.0; } inf.c[0] = 0.0; inf.s[0] = 0.0; REALTYPE hc = 0.0, hs = 0.0; REALTYPE basefreq = 30.0 * pow(10.0, Padaptiveharmonicsbasefreq / 128.0); REALTYPE power = (Padaptiveharmonicspower + 1.0) / 101.0; REALTYPE rap = freq / basefreq; rap = pow(rap, power); bool down = false; if(rap > 1.0) { rap = 1.0 / rap; down = true; } for(int i = 0; i < OSCIL_SIZE / 2 - 2; i++) { REALTYPE h = i * rap; int high = (int)(i * rap); REALTYPE low = fmod(h, 1.0); if(high >= (OSCIL_SIZE / 2 - 2)) break; else { if(down) { f.c[high] += inf.c[i] * (1.0 - low); f.s[high] += inf.s[i] * (1.0 - low); f.c[high + 1] += inf.c[i] * low; f.s[high + 1] += inf.s[i] * low; } else { hc = inf.c[high] * (1.0 - low) + inf.c[high + 1] * low; hs = inf.s[high] * (1.0 - low) + inf.s[high + 1] * low; } if(fabs(hc) < 0.000001) hc = 0.0; if(fabs(hs) < 0.000001) hs = 0.0; } if(!down) { if(i == 0) { //corect the aplitude of the first harmonic hc *= rap; hs *= rap; } f.c[i] = hc; f.s[i] = hs; } } f.c[1] += f.c[0]; f.s[1] += f.s[0]; f.c[0] = 0.0; f.s[0] = 0.0; deleteFFTFREQS(&inf); } void OscilGen::adaptiveharmonicpostprocess(REALTYPE *f, int size) { if(Padaptiveharmonics <= 1) return; REALTYPE *inf = new REALTYPE[size]; REALTYPE par = Padaptiveharmonicspar * 0.01; par = 1.0 - pow((1.0 - par), 1.5); for(int i = 0; i < size; i++) { inf[i] = f[i] * par; f[i] = f[i] * (1.0 - par); } if(Padaptiveharmonics == 2) { //2n+1 for(int i = 0; i < size; i++) if((i % 2) == 0) f[i] += inf[i]; //i=0 pt prima armonica,etc. } else { //celelalte moduri int nh = (Padaptiveharmonics - 3) / 2 + 2; int sub_vs_add = (Padaptiveharmonics - 3) % 2; if(sub_vs_add == 0) { for(int i = 0; i < size; i++) { if(((i + 1) % nh) == 0) f[i] += inf[i]; ; } } else { for(int i = 0; i < size / nh - 1; i++) f[(i + 1) * nh - 1] += inf[i]; ; } } delete[] inf; } /* * Get the oscillator function */ short int OscilGen::get(REALTYPE *smps, REALTYPE freqHz) { return this->get(smps, freqHz, 0); } void OscilGen::newrandseed(unsigned int randseed) { this->randseed = randseed; } /* * Get the oscillator function */ short int OscilGen::get(REALTYPE *smps, REALTYPE freqHz, int resonance) { int i; int nyquist, outpos; if((oldbasepar != Pbasefuncpar) || (oldbasefunc != Pcurrentbasefunc) || (oldhmagtype != Phmagtype) || (oldwaveshaping != Pwaveshaping) || (oldwaveshapingfunction != Pwaveshapingfunction)) oscilprepared = 0; if(oldfilterpars != Pfiltertype * 256 + Pfilterpar1 + Pfilterpar2 * 65536 + Pfilterbeforews * 16777216) { oscilprepared = 0; oldfilterpars = Pfiltertype * 256 + Pfilterpar1 + Pfilterpar2 * 65536 + Pfilterbeforews * 16777216; } if(oldsapars != Psatype * 256 + Psapar) { oscilprepared = 0; oldsapars = Psatype * 256 + Psapar; } if((oldbasefuncmodulation != Pbasefuncmodulation) || (oldbasefuncmodulationpar1 != Pbasefuncmodulationpar1) || (oldbasefuncmodulationpar2 != Pbasefuncmodulationpar2) || (oldbasefuncmodulationpar3 != Pbasefuncmodulationpar3)) oscilprepared = 0; if((oldmodulation != Pmodulation) || (oldmodulationpar1 != Pmodulationpar1) || (oldmodulationpar2 != Pmodulationpar2) || (oldmodulationpar3 != Pmodulationpar3)) oscilprepared = 0; if(oldharmonicshift != Pharmonicshift + Pharmonicshiftfirst * 256) oscilprepared = 0; if(oscilprepared != 1) prepare(); outpos = (int)((RND * 2.0 - 1.0) * (REALTYPE) OSCIL_SIZE * (Prand - 64.0) / 64.0); outpos = (outpos + 2 * OSCIL_SIZE) % OSCIL_SIZE; for(i = 0; i < OSCIL_SIZE / 2; i++) { outoscilFFTfreqs.c[i] = 0.0; outoscilFFTfreqs.s[i] = 0.0; } nyquist = (int)(0.5 * SAMPLE_RATE / fabs(freqHz)) + 2; if(ADvsPAD) nyquist = (int)(OSCIL_SIZE / 2); if(nyquist > OSCIL_SIZE / 2) nyquist = OSCIL_SIZE / 2; int realnyquist = nyquist; if(Padaptiveharmonics != 0) nyquist = OSCIL_SIZE / 2; for(i = 1; i < nyquist - 1; i++) { outoscilFFTfreqs.c[i] = oscilFFTfreqs.c[i]; outoscilFFTfreqs.s[i] = oscilFFTfreqs.s[i]; } adaptiveharmonic(outoscilFFTfreqs, freqHz); adaptiveharmonicpostprocess(&outoscilFFTfreqs.c[1], OSCIL_SIZE / 2 - 1); adaptiveharmonicpostprocess(&outoscilFFTfreqs.s[1], OSCIL_SIZE / 2 - 1); nyquist = realnyquist; if(Padaptiveharmonics) { //do the antialiasing in the case of adaptive harmonics for(i = nyquist; i < OSCIL_SIZE / 2; i++) { outoscilFFTfreqs.s[i] = 0; outoscilFFTfreqs.c[i] = 0; } } // Randomness (each harmonic), the block type is computed // in ADnote by setting start position according to this setting if((Prand > 64) && (freqHz >= 0.0) && (!ADvsPAD)) { REALTYPE rnd, angle, a, b, c, d; rnd = PI * pow((Prand - 64.0) / 64.0, 2.0); for(i = 1; i < nyquist - 1; i++) { //to Nyquist only for AntiAliasing angle = rnd * i * RND; a = outoscilFFTfreqs.c[i]; b = outoscilFFTfreqs.s[i]; c = cos(angle); d = sin(angle); outoscilFFTfreqs.c[i] = a * c - b * d; outoscilFFTfreqs.s[i] = a * d + b * c; } } //Harmonic Amplitude Randomness if((freqHz > 0.1) && (!ADvsPAD)) { unsigned int realrnd = rand(); srand(randseed); REALTYPE power = Pamprandpower / 127.0; REALTYPE normalize = 1.0 / (1.2 - power); switch(Pamprandtype) { case 1: power = power * 2.0 - 0.5; power = pow(15.0, power); for(i = 1; i < nyquist - 1; i++) { REALTYPE amp = pow(RND, power) * normalize; outoscilFFTfreqs.c[i] *= amp; outoscilFFTfreqs.s[i] *= amp; } break; case 2: power = power * 2.0 - 0.5; power = pow(15.0, power) * 2.0; REALTYPE rndfreq = 2 * PI * RND; for(i = 1; i < nyquist - 1; i++) { REALTYPE amp = pow(fabs(sin(i * rndfreq)), power) * normalize; outoscilFFTfreqs.c[i] *= amp; outoscilFFTfreqs.s[i] *= amp; } break; } srand(realrnd + 1); } if((freqHz > 0.1) && (resonance != 0)) res->applyres(nyquist - 1, outoscilFFTfreqs, freqHz); //Full RMS normalize REALTYPE sum = 0; for(int j = 1; j < OSCIL_SIZE / 2; j++) { REALTYPE term = outoscilFFTfreqs.c[j] * outoscilFFTfreqs.c[j] + outoscilFFTfreqs.s[j] * outoscilFFTfreqs.s[j]; sum += term; } if(sum < 0.000001) sum = 1.0; sum = 1.0 / sqrt(sum); for(int j = 1; j < OSCIL_SIZE / 2; j++) { outoscilFFTfreqs.c[j] *= sum; outoscilFFTfreqs.s[j] *= sum; } if((ADvsPAD) && (freqHz > 0.1)) //in this case the smps will contain the freqs for(i = 1; i < OSCIL_SIZE / 2; i++) smps[i - 1] = sqrt(outoscilFFTfreqs.c[i] * outoscilFFTfreqs.c[i] + outoscilFFTfreqs.s[i] * outoscilFFTfreqs.s[i]); else { fft->freqs2smps(outoscilFFTfreqs, smps); for(i = 0; i < OSCIL_SIZE; i++) smps[i] *= 0.25; //correct the amplitude } if(Prand < 64) return outpos; else return 0; } /* * Get the spectrum of the oscillator for the UI */ void OscilGen::getspectrum(int n, REALTYPE *spc, int what) { if(n > OSCIL_SIZE / 2) n = OSCIL_SIZE / 2; for(int i = 1; i < n; i++) { if(what == 0) spc[i - 1] = sqrt(oscilFFTfreqs.c[i] * oscilFFTfreqs.c[i] + oscilFFTfreqs.s[i] * oscilFFTfreqs.s[i]); else { if(Pcurrentbasefunc == 0) spc[i - 1] = ((i == 1) ? (1.0) : (0.0)); else spc[i - 1] = sqrt(basefuncFFTfreqs.c[i] * basefuncFFTfreqs.c[i] + basefuncFFTfreqs.s[i] * basefuncFFTfreqs.s[i]); } } if(what == 0) { for(int i = 0; i < n; i++) outoscilFFTfreqs.s[i] = outoscilFFTfreqs.c[i] = spc[i]; for(int i = n; i < OSCIL_SIZE / 2; i++) outoscilFFTfreqs.s[i] = outoscilFFTfreqs.c[i] = 0.0; adaptiveharmonic(outoscilFFTfreqs, 0.0); for(int i = 0; i < n; i++) spc[i] = outoscilFFTfreqs.s[i]; adaptiveharmonicpostprocess(spc, n - 1); } } /* * Convert the oscillator as base function */ void OscilGen::useasbase() { int i; for(i = 0; i < OSCIL_SIZE / 2; i++) { basefuncFFTfreqs.c[i] = oscilFFTfreqs.c[i]; basefuncFFTfreqs.s[i] = oscilFFTfreqs.s[i]; } oldbasefunc = Pcurrentbasefunc = 127; prepare(); } /* * Get the base function for UI */ void OscilGen::getcurrentbasefunction(REALTYPE *smps) { if(Pcurrentbasefunc != 0) fft->freqs2smps(basefuncFFTfreqs, smps); else getbasefunction(smps); //the sine case } void OscilGen::add2XML(XMLwrapper *xml) { xml->addpar("harmonic_mag_type", Phmagtype); xml->addpar("base_function", Pcurrentbasefunc); xml->addpar("base_function_par", Pbasefuncpar); xml->addpar("base_function_modulation", Pbasefuncmodulation); xml->addpar("base_function_modulation_par1", Pbasefuncmodulationpar1); xml->addpar("base_function_modulation_par2", Pbasefuncmodulationpar2); xml->addpar("base_function_modulation_par3", Pbasefuncmodulationpar3); xml->addpar("modulation", Pmodulation); xml->addpar("modulation_par1", Pmodulationpar1); xml->addpar("modulation_par2", Pmodulationpar2); xml->addpar("modulation_par3", Pmodulationpar3); xml->addpar("wave_shaping", Pwaveshaping); xml->addpar("wave_shaping_function", Pwaveshapingfunction); xml->addpar("filter_type", Pfiltertype); xml->addpar("filter_par1", Pfilterpar1); xml->addpar("filter_par2", Pfilterpar2); xml->addpar("filter_before_wave_shaping", Pfilterbeforews); xml->addpar("spectrum_adjust_type", Psatype); xml->addpar("spectrum_adjust_par", Psapar); xml->addpar("rand", Prand); xml->addpar("amp_rand_type", Pamprandtype); xml->addpar("amp_rand_power", Pamprandpower); xml->addpar("harmonic_shift", Pharmonicshift); xml->addparbool("harmonic_shift_first", Pharmonicshiftfirst); xml->addpar("adaptive_harmonics", Padaptiveharmonics); xml->addpar("adaptive_harmonics_base_frequency", Padaptiveharmonicsbasefreq); xml->addpar("adaptive_harmonics_power", Padaptiveharmonicspower); xml->beginbranch("HARMONICS"); for(int n = 0; n < MAX_AD_HARMONICS; n++) { if((Phmag[n] == 64) && (Phphase[n] == 64)) continue; xml->beginbranch("HARMONIC", n + 1); xml->addpar("mag", Phmag[n]); xml->addpar("phase", Phphase[n]); xml->endbranch(); } xml->endbranch(); if(Pcurrentbasefunc == 127) { REALTYPE max = 0.0; for(int i = 0; i < OSCIL_SIZE / 2; i++) { if(max < fabs(basefuncFFTfreqs.c[i])) max = fabs(basefuncFFTfreqs.c[i]); if(max < fabs(basefuncFFTfreqs.s[i])) max = fabs(basefuncFFTfreqs.s[i]); } if(max < 0.00000001) max = 1.0; xml->beginbranch("BASE_FUNCTION"); for(int i = 1; i < OSCIL_SIZE / 2; i++) { REALTYPE xc = basefuncFFTfreqs.c[i] / max; REALTYPE xs = basefuncFFTfreqs.s[i] / max; if((fabs(xs) > 0.00001) && (fabs(xs) > 0.00001)) { xml->beginbranch("BF_HARMONIC", i); xml->addparreal("cos", xc); xml->addparreal("sin", xs); xml->endbranch(); } } xml->endbranch(); } } void OscilGen::getfromXML(XMLwrapper *xml) { Phmagtype = xml->getpar127("harmonic_mag_type", Phmagtype); Pcurrentbasefunc = xml->getpar127("base_function", Pcurrentbasefunc); Pbasefuncpar = xml->getpar127("base_function_par", Pbasefuncpar); Pbasefuncmodulation = xml->getpar127("base_function_modulation", Pbasefuncmodulation); Pbasefuncmodulationpar1 = xml->getpar127("base_function_modulation_par1", Pbasefuncmodulationpar1); Pbasefuncmodulationpar2 = xml->getpar127("base_function_modulation_par2", Pbasefuncmodulationpar2); Pbasefuncmodulationpar3 = xml->getpar127("base_function_modulation_par3", Pbasefuncmodulationpar3); Pmodulation = xml->getpar127("modulation", Pmodulation); Pmodulationpar1 = xml->getpar127("modulation_par1", Pmodulationpar1); Pmodulationpar2 = xml->getpar127("modulation_par2", Pmodulationpar2); Pmodulationpar3 = xml->getpar127("modulation_par3", Pmodulationpar3); Pwaveshaping = xml->getpar127("wave_shaping", Pwaveshaping); Pwaveshapingfunction = xml->getpar127("wave_shaping_function", Pwaveshapingfunction); Pfiltertype = xml->getpar127("filter_type", Pfiltertype); Pfilterpar1 = xml->getpar127("filter_par1", Pfilterpar1); Pfilterpar2 = xml->getpar127("filter_par2", Pfilterpar2); Pfilterbeforews = xml->getpar127("filter_before_wave_shaping", Pfilterbeforews); Psatype = xml->getpar127("spectrum_adjust_type", Psatype); Psapar = xml->getpar127("spectrum_adjust_par", Psapar); Prand = xml->getpar127("rand", Prand); Pamprandtype = xml->getpar127("amp_rand_type", Pamprandtype); Pamprandpower = xml->getpar127("amp_rand_power", Pamprandpower); Pharmonicshift = xml->getpar("harmonic_shift", Pharmonicshift, -64, 64); Pharmonicshiftfirst = xml->getparbool("harmonic_shift_first", Pharmonicshiftfirst); Padaptiveharmonics = xml->getpar("adaptive_harmonics", Padaptiveharmonics, 0, 127); Padaptiveharmonicsbasefreq = xml->getpar( "adaptive_harmonics_base_frequency", Padaptiveharmonicsbasefreq, 0, 255); Padaptiveharmonicspower = xml->getpar("adaptive_harmonics_power", Padaptiveharmonicspower, 0, 200); if(xml->enterbranch("HARMONICS")) { Phmag[0] = 64; Phphase[0] = 64; for(int n = 0; n < MAX_AD_HARMONICS; n++) { if(xml->enterbranch("HARMONIC", n + 1) == 0) continue; Phmag[n] = xml->getpar127("mag", 64); Phphase[n] = xml->getpar127("phase", 64); xml->exitbranch(); } xml->exitbranch(); } if(Pcurrentbasefunc != 0) changebasefunction(); if(xml->enterbranch("BASE_FUNCTION")) { for(int i = 1; i < OSCIL_SIZE / 2; i++) { if(xml->enterbranch("BF_HARMONIC", i)) { basefuncFFTfreqs.c[i] = xml->getparreal("cos", 0.0); basefuncFFTfreqs.s[i] = xml->getparreal("sin", 0.0); xml->exitbranch(); } } xml->exitbranch(); REALTYPE max = 0.0; basefuncFFTfreqs.c[0] = 0.0; for(int i = 0; i < OSCIL_SIZE / 2; i++) { if(max < fabs(basefuncFFTfreqs.c[i])) max = fabs(basefuncFFTfreqs.c[i]); if(max < fabs(basefuncFFTfreqs.s[i])) max = fabs(basefuncFFTfreqs.s[i]); } if(max < 0.00000001) max = 1.0; for(int i = 0; i < OSCIL_SIZE / 2; i++) { if(basefuncFFTfreqs.c[i]) basefuncFFTfreqs.c[i] /= max; if(basefuncFFTfreqs.s[i]) basefuncFFTfreqs.s[i] /= max; } } }