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(); }
void OscilGen::convert2sine() { float mag[MAX_AD_HARMONICS], phase[MAX_AD_HARMONICS]; float oscil[synth.oscilsize]; fft_t *freqs = new fft_t[synth.oscilsize / 2]; get(oscil, -1.0f); FFTwrapper *fft = new FFTwrapper(synth.oscilsize); fft->smps2freqs(oscil, freqs); delete (fft); normalize(freqs, synth.oscilsize); mag[0] = 0; phase[0] = 0; for(int i = 0; i < MAX_AD_HARMONICS; ++i) { mag[i] = abs(freqs, i + 1); phase[i] = arg(freqs, i + 1); } defaults(); for(int i = 0; i < MAX_AD_HARMONICS - 1; ++i) { float newmag = mag[i]; float newphase = phase[i]; Phmag[i] = (int) ((newmag) * 63.0f) + 64; Phphase[i] = 64 - (int) (64.0f * newphase / PI); if(Phphase[i] > 127) Phphase[i] = 127; if(Phmag[i] == 64) Phphase[i] = 64; } delete[] freqs; prepare(); }
//Requires // - Pquality.samplesize // - Pquality.basenote // - Pquality.oct // - Pquality.smpoct // - spectrum at various frequencies (oodles of data) void PADnoteParameters::sampleGenerator(PADnoteParameters::callback cb, std::function<bool()> do_abort) { const int samplesize = (((int) 1) << (Pquality.samplesize + 14)); const int spectrumsize = samplesize / 2; float *spectrum = new float[spectrumsize]; const int profilesize = 512; float profile[profilesize]; const float bwadjust = getprofile(profile, profilesize); float basefreq = 65.406f * powf(2.0f, Pquality.basenote / 2); if(Pquality.basenote % 2 == 1) basefreq *= 1.5f; int samplemax = Pquality.oct + 1; int smpoct = Pquality.smpoct; if(Pquality.smpoct == 5) smpoct = 6; if(Pquality.smpoct == 6) smpoct = 12; if(smpoct != 0) samplemax *= smpoct; else samplemax = samplemax / 2 + 1; if(samplemax == 0) samplemax = 1; //prepare a BIG FFT FFTwrapper *fft = new FFTwrapper(samplesize); fft_t *fftfreqs = new fft_t[samplesize / 2]; //this is used to compute frequency relation to the base frequency float adj[samplemax]; for(int nsample = 0; nsample < samplemax; ++nsample) adj[nsample] = (Pquality.oct + 1.0f) * (float)nsample / samplemax; for(int nsample = 0; nsample < samplemax; ++nsample) { if(do_abort()) goto exit; const float basefreqadjust = powf(2.0f, adj[nsample] - adj[samplemax - 1] * 0.5f); if(Pmode == 0) generatespectrum_bandwidthMode(spectrum, spectrumsize, basefreq * basefreqadjust, profile, profilesize, bwadjust); else generatespectrum_otherModes(spectrum, spectrumsize, basefreq * basefreqadjust); //the last samples contains the first samples //(used for linear/cubic interpolation) const int extra_samples = 5; PADnoteParameters::Sample newsample; newsample.smp = new float[samplesize + extra_samples]; newsample.smp[0] = 0.0f; for(int i = 1; i < spectrumsize; ++i) //randomize the phases fftfreqs[i] = FFTpolar(spectrum[i], (float)RND * 2 * PI); //that's all; here is the only ifft for the whole sample; //no windows are used ;-) fft->freqs2smps(fftfreqs, newsample.smp); //normalize(rms) float rms = 0.0f; for(int i = 0; i < samplesize; ++i) rms += newsample.smp[i] * newsample.smp[i]; rms = sqrt(rms); if(rms < 0.000001f) rms = 1.0f; rms *= sqrt(262144.0f / samplesize);//262144=2^18 for(int i = 0; i < samplesize; ++i) newsample.smp[i] *= 1.0f / rms * 50.0f; //prepare extra samples used by the linear or cubic interpolation for(int i = 0; i < extra_samples; ++i) newsample.smp[i + samplesize] = newsample.smp[i]; //yield new sample newsample.size = samplesize; newsample.basefreq = basefreq * basefreqadjust; cb(nsample, newsample); } exit: //Cleanup delete (fft); delete[] fftfreqs; delete[] spectrum; }
// Applies the parameters (i.e. computes all the samples, based on parameters); void PADnoteParameters::applyparameters(bool islocked) { const int samplesize = (((int)1) << (Pquality.samplesize + 14)); int spectrumsize = samplesize / 2; float spectrum[spectrumsize]; int profilesize = 512; float profile[profilesize]; float bwadjust = getprofile(profile, profilesize); // for (int i=0;i<profilesize;i++) profile[i]*=profile[i]; float basefreq = 65.406f * powf(2.0f, Pquality.basenote / 2); if (Pquality.basenote %2 == 1) basefreq *= 1.5; int samplemax = Pquality.oct + 1; int smpoct = Pquality.smpoct; if (Pquality.smpoct == 5) smpoct = 6; if (Pquality.smpoct == 6) smpoct = 12; if (smpoct != 0) samplemax *= smpoct; else samplemax = samplemax / 2 + 1; if (samplemax == 0) samplemax = 1; // prepare a BIG FFT stuff FFTwrapper *fft = new FFTwrapper(samplesize); FFTFREQS fftfreqs; FFTwrapper::newFFTFREQS(&fftfreqs, samplesize / 2); float adj[samplemax]; // this is used to compute frequency relation to the base frequency for (int nsample = 0; nsample < samplemax; ++nsample) adj[nsample] = (Pquality.oct + 1.0f) * (float)nsample / samplemax; for (int nsample = 0; nsample < samplemax; ++nsample) { float tmp = adj[nsample] - adj[samplemax - 1] * 0.5f; float basefreqadjust = powf(2.0f, tmp); if (Pmode == 0) generatespectrum_bandwidthMode(spectrum, spectrumsize, basefreq * basefreqadjust, profile, profilesize, bwadjust); else generatespectrum_otherModes(spectrum, spectrumsize, basefreq * basefreqadjust, profile, profilesize, bwadjust); const int extra_samples = 5; // the last samples contains the first // samples (used for linear/cubic interpolation) newsample.smp = new float[samplesize + extra_samples]; newsample.smp[0] = 0.0; for (int i = 1; i < spectrumsize; ++i) { // randomize the phases float phase = synth->numRandom() * 6.29f; fftfreqs.c[i] = spectrum[i] * cosf(phase); fftfreqs.s[i] = spectrum[i] * sinf(phase); } fft->freqs2smps(&fftfreqs, newsample.smp); // that's all; here is the only ifft for the whole sample; no windows are used ;-) // normalize(rms) float rms = 0.0; for (int i = 0; i < samplesize; ++i) rms += newsample.smp[i] * newsample.smp[i]; rms = sqrtf(rms); if (rms < 0.000001) rms = 1.0; rms *= sqrtf(262144.0f / samplesize); for (int i = 0; i < samplesize; ++i) newsample.smp[i] *= 1.0f / rms * 50.0f; // prepare extra samples used by the linear or cubic interpolation for (int i = 0; i < extra_samples; ++i) newsample.smp[i + samplesize] = newsample.smp[i]; // replace the current sample with the new computed sample if (!islocked) synth->actionLock(lockmute); deletesample(nsample); sample[nsample].smp = newsample.smp; sample[nsample].size = samplesize; sample[nsample].basefreq = basefreq * basefreqadjust; if (!islocked) synth->actionLock(unlock); newsample.smp = NULL; } delete fft; FFTwrapper::deleteFFTFREQS(&fftfreqs); // delete the additional samples that might exists and are not useful if (!islocked) synth->actionLock(lockmute); for (int i = samplemax; i < PAD_MAX_SAMPLES; ++i) deletesample(i); if (!islocked) synth->actionLock(unlock); }