This patch was taken from Debian. https://salsa.debian.org/multimedia-team/ams/-/raw/master/debian/patches/0007-Make-vocoder-module-compatible-to-C-11.patch From: Guido Scholz Date: Tue, 6 Nov 2018 21:55:38 +0100 Subject: Make vocoder module compatible to C++11 --- src/m_vocoder.cpp | 218 +++++++++++++++++++++++++++--------------------------- src/m_vocoder.h | 31 ++++---- 2 files changed, 124 insertions(+), 125 deletions(-) diff --git a/src/m_vocoder.cpp b/src/m_vocoder.cpp index 572cf65..371e2cf 100644 --- a/src/m_vocoder.cpp +++ b/src/m_vocoder.cpp @@ -18,10 +18,6 @@ along with ams. If not, see . */ -#include -#include -#include -#include #include #include #include @@ -36,16 +32,13 @@ #include "synthdata.h" #include "midicheckbox.h" #include "midislider.h" -// For FFTW to be happy we must include complex.h before fftw3.h -#include -#include #include "port.h" #include "m_vocoder.h" // Window function - One way to make the FFT behave // and give more continuous results over edge steps. -float M_vocoder::windowcurve (int windowfunc, int len, int elem, float alpha) +float M_vocoder::windowcurve (int windowfunc, unsigned int len, int elem, float alpha) { float out; out = 1.0; @@ -98,6 +91,7 @@ float M_vocoder::windowcurve (int windowfunc, int len, int elem, float alpha) return (out); } + M_vocoder::M_vocoder(QWidget* parent, int id) : Module(M_type_vocoder, id, 5, parent, tr("FFT Vocoder")) { @@ -160,6 +154,7 @@ M_vocoder::M_vocoder(QWidget* parent, int id) modbuf[l1] = (float *)malloc( fftsize * sizeof(float)); memset( modbuf[l1], 0, fftsize * sizeof(float)); } + carrbuf = (float **)malloc(synthdata->poly * sizeof(float *)); for (l1 = 0; l1 < synthdata->poly; l1++) { carrbuf[l1] = (float *)malloc( fftsize * sizeof(float)); @@ -175,38 +170,48 @@ M_vocoder::M_vocoder(QWidget* parent, int id) window[l2] = windowcurve (whichwin, fftsize, l2, 0.25); // FFTW setup stuff - carrinforward = (fftw_complex *) fftw_malloc (sizeof (fftw_complex) - * fftsize); - carrinbackward = (fftw_complex *) fftw_malloc (sizeof (fftw_complex) - * fftsize); - carroutforward = (fftw_complex *) fftw_malloc (sizeof (fftw_complex) - * fftsize); - carroutbackward = (fftw_complex *) fftw_malloc (sizeof (fftw_complex) - * fftsize); - modinforward = (fftw_complex *) fftw_malloc (sizeof (fftw_complex) - * fftsize); - modinbackward = (fftw_complex *) fftw_malloc (sizeof (fftw_complex) - * fftsize); - modoutforward = (fftw_complex *) fftw_malloc (sizeof (fftw_complex) - * fftsize); - modoutbackward = (fftw_complex *) fftw_malloc (sizeof (fftw_complex) - * fftsize); - fftw_set_timelimit (5.0); - planmodforward = fftw_plan_dft_1d (fftsize, modinforward, - modoutforward, FFTW_FORWARD, FFTW_MEASURE); - planmodbackward = fftw_plan_dft_1d (fftsize, modinbackward, - modoutbackward, FFTW_BACKWARD, FFTW_MEASURE); - plancarrforward = fftw_plan_dft_1d (fftsize, carrinforward, - carroutforward, FFTW_FORWARD, FFTW_MEASURE); - plancarrbackward = fftw_plan_dft_1d (fftsize, carrinbackward, - carroutbackward, FFTW_BACKWARD, FFTW_MEASURE); + carrinforward.reserve(fftsize); + carrinbackward.reserve(fftsize); + carroutforward.reserve(fftsize); + carroutbackward.reserve(fftsize); + modinforward.reserve(fftsize); + modinbackward.reserve(fftsize); + modoutforward.reserve(fftsize); + modoutbackward.reserve(fftsize); + + fftw_set_timelimit(5.0); + + planmodforward = fftw_plan_dft_1d(fftsize, + reinterpret_cast (modinforward.data()), + reinterpret_cast (modoutforward.data()), + FFTW_FORWARD, FFTW_MEASURE); + + planmodbackward = fftw_plan_dft_1d(fftsize, + reinterpret_cast (modinbackward.data()), + reinterpret_cast (modoutbackward.data()), + FFTW_BACKWARD, FFTW_MEASURE); + + plancarrforward = fftw_plan_dft_1d(fftsize, + reinterpret_cast (carrinforward.data()), + reinterpret_cast (carroutforward.data()), + FFTW_FORWARD, FFTW_MEASURE); + + plancarrbackward = fftw_plan_dft_1d(fftsize, + reinterpret_cast (carrinbackward.data()), + reinterpret_cast (carroutbackward.data()), + FFTW_BACKWARD, FFTW_MEASURE); } + M_vocoder::~M_vocoder() { - int l1; + // Clean up FFTW stuff. + fftw_destroy_plan (plancarrforward); + fftw_destroy_plan (plancarrbackward); + fftw_destroy_plan (planmodforward); + fftw_destroy_plan (planmodbackward); - for (l1 = 0; l1 < synthdata->poly; l1++) { + for (int l1 = 0; l1 < synthdata->poly; l1++) { free(modbuf[l1]); free(carrbuf[l1]); } @@ -215,29 +220,14 @@ M_vocoder::~M_vocoder() { free (window); free (modmap); free (armodmap); - - //#define FFTW_CLEANUP -#ifdef FFTW_CLEANUP - // Clean up FFTW stuff. - fftw_destroy_plan (plancarrforward); - fftw_destroy_plan (plancarrbackward); - fftw_destroy_plan (planmodforward); - fftw_destroy_plan (planmodbackward); - fftw_free (carrinforward); - fftw_free (carrinbackward); - fftw_free (carroutforward); - fftw_free (carroutbackward); - fftw_free (modinforward); - fftw_free (modinbackward); - fftw_free (modoutforward); - fftw_free (modoutbackward); -#endif } + void M_vocoder::generateCycle() { int l1; // l1 indexes along polyphony. unsigned int l2; // l2 indexes along the cycle + const std::complex I(0.0, 1.0); inModulator = port_M_modulator->getinputdata(); inPitchShift = port_M_pitchshift->getinputdata(); @@ -272,7 +262,7 @@ void M_vocoder::generateCycle() { // Did the user change the FFT windowing function? if (myFFTWindowFunc != whichwin) { whichwin = myFFTWindowFunc; - for (l2 = 0; l2 < (unsigned int) fftsize; l2++) + for (l2 = 0; l2 < fftsize; l2++) window[l2] = windowcurve (whichwin, fftsize, l2, 0.25); } @@ -294,7 +284,7 @@ void M_vocoder::generateCycle() { } // window the input buffer to modinforward - for (l2 = 0; l2 < (unsigned int)fftsize ; l2++) { + for (l2 = 0; l2 < fftsize ; l2++) { modinforward[l2] = modbuf[l1][l2] * window[l2]; } @@ -310,17 +300,18 @@ void M_vocoder::generateCycle() { fftw_execute (planmodforward); // copy the FFT of the modulator to modinbackward. - for (l2 = 0; l2 < (unsigned int)fftsize; l2++) - modinbackward[l2] = modoutforward[l2]; + //for (l2 = 0; l2 < fftsize; l2++) + // modinbackward[l2] = modoutforward[l2]; + modinbackward = modoutforward; // Send the FFT of the modulator to the output for giggles // and get an approximation of the first harmonic too. float firstharmonicval; int firstharmonicindex; firstharmonicval = 0.0; - firstharmonicindex = 1.0; + firstharmonicindex = 1; for (l2 = 1; l2 < (unsigned int) synthdata->cyclesize; l2++) { - data[2][l1][l2] = logf(fabs (creal (modoutforward[l2])) + 1.0); + data[2][l1][l2] = logf(fabs(modoutforward[l2].real()) + 1.0); if (data[2][l1][l2] > firstharmonicval) { firstharmonicindex = l2; firstharmonicval = data[2][l1][l2] ; @@ -333,35 +324,38 @@ void M_vocoder::generateCycle() { // intermediate frequency-domain munging of modulator // Frequency (additive, Bode-style) shifting first - for (l2 = 0; l2 < (unsigned int)fftsize; l2++) - modinbackward[l2] = 0; + for (l2 = 0; l2 < fftsize; l2++) + modinbackward[l2] = 0.0; + int lclfrq; - for (l2 = 0; l2 < (unsigned int)fftsize/2; l2++) { + for (l2 = 0; l2 < fftsize/2; l2++) { // positive frequencies (first half) of the FFT result lclfrq = l2 + (int)freqshift + vcfreqshift * inFreqShift[l1][0]; lclfrq = lclfrq > 0 ? lclfrq : 0; - lclfrq = lclfrq < ((fftsize/2)-1) ? lclfrq : (fftsize/2)-1; + lclfrq = lclfrq < (int)((fftsize/2)-1) ? lclfrq : (fftsize/2)-1; modinbackward [lclfrq] = modoutforward [l2]; // Negative frequencies (second half of the fft result) - modinbackward [fftsize - lclfrq] = modoutforward [ fftsize - l2]; + modinbackward [fftsize - lclfrq] = modoutforward [fftsize - l2]; } - // Pitchshifting (multiplicative, harmonic-retaining) shifting. - // Note that we reuse the modoutforward as working space - for (l2 = 0; l2 < (unsigned int) fftsize; l2++) { - modoutforward[l2] = modinbackward[l2]; - }; - for (l2 = 0; l2 < (unsigned int)fftsize; l2++) - modinbackward[l2] = 0; + // Pitchshifting (multiplicative, harmonic-retaining) shifting. + // Note that we reuse the modoutforward as working space + //for (l2 = 0; l2 < fftsize; l2++) { + // modoutforward[l2] = modinbackward[l2]; + //}; + modoutforward = modinbackward; + + for (l2 = 0; l2 < fftsize; l2++) + modinbackward[l2] = 0.0; float psmod, psfactor; psmod = (pitchshift + vcpitch * inPitchShift[l1][0]); psfactor = pow (2.0, psmod); - for (l2 = 0; l2 < (unsigned int)fftsize/2; l2++) { + for (l2 = 0; l2 < fftsize/2; l2++) { // positive frequencies (first half) of the FFT result lclfrq = l2 * psfactor; lclfrq = lclfrq > 0 ? lclfrq : 0; - lclfrq = lclfrq < ((fftsize/2)-1) ? lclfrq : (fftsize/2)-1; + lclfrq = lclfrq < (int)((fftsize/2)-1) ? lclfrq : (fftsize/2)-1; // Old way to pitch shift: just move the bucket. But this puts // nulls wherever the energy is split between two buckets with // a 180 degree phase difference. @@ -375,12 +369,12 @@ void M_vocoder::generateCycle() { // Better way: move freq. bin, multiply angle by octave motion. // modinbackward[lclfrq] += - cabs (modoutforward [l2]) - * cexp (I * ( carg (modoutforward [l2]) + std::abs(modoutforward[l2]) + * std::exp (I * ( std::arg (modoutforward [l2]) + (l2 * phaseshift * psfactor))); modinbackward[fftsize - lclfrq] += - cabs (modoutforward [ fftsize - l2]) - * cexp (I * ( carg (modoutforward [ fftsize - l2]) + std::abs (modoutforward [ fftsize - l2]) + * std::exp (I * ( std::arg (modoutforward [ fftsize - l2]) + (l2 * phaseshift * psfactor))); }; } @@ -389,9 +383,9 @@ void M_vocoder::generateCycle() { fftw_execute (planmodbackward); // renormalize the time-domain modulator output - for (l2 = 0; l2 < (unsigned)fftsize; l2++) { - modoutbackward [l2] = modoutbackward[l2] / float (fftsize) ; - modoutbackward [l2] = modoutbackward[l2] / window[l2]; + for (l2 = 0; l2 < fftsize; l2++) { + modoutbackward [l2] = modoutbackward[l2] / (double) fftsize; + modoutbackward [l2] = modoutbackward[l2] / (double) window[l2]; } unsigned int i; @@ -400,13 +394,11 @@ void M_vocoder::generateCycle() { // Splicing the new output to the results - if (dynsplice == 0.0) - { + if (dynsplice == 0.0) { // output it as the altered modulator. for (l2 = 0; l2 < synthdata->cyclesize; l2++) { - data[0][l1][l2] = creal ( modoutbackward [l2 + - fftsize/2 - - synthdata->cyclesize/2 ]); + data[0][l1][l2] = + modoutbackward[l2 + fftsize/2 - synthdata->cyclesize/2].real(); } clomatch_index = fftsize - synthdata->cyclesize; } @@ -421,18 +413,21 @@ void M_vocoder::generateCycle() { float tval, dtval; int searchstart; float spliceval, dspliceval; - searchstart = fftsize/2 - synthdata->cyclesize; - if (searchstart < 1) searchstart = 1; - clomatch_index = searchstart; + + searchstart = fftsize/2 - synthdata->cyclesize; + if (searchstart < 1) + searchstart = 1; + + clomatch_index = searchstart; spliceval = data[0][l1][synthdata->cyclesize - 1]; dspliceval = spliceval - data[0][l1][synthdata->cyclesize - 2]; - clov_sofar= fabs(creal(modoutbackward[clomatch_index])-spliceval ); + clov_sofar= fabs(modoutbackward[clomatch_index].real()-spliceval); for (l2 = searchstart; l2 < (searchstart + synthdata->cyclesize); l2++) { - tval = creal (modoutbackward[l2]); - dtval = tval - creal (modoutbackward [l2-1]); + tval = modoutbackward[l2].real(); + dtval = tval - modoutbackward [l2-1].real(); if ( ((fabs (tval - spliceval )) < clov_sofar ) && ((dtval * dspliceval ) >= 0) @@ -445,15 +440,15 @@ void M_vocoder::generateCycle() { }; // fprintf (stderr, "%d %f %f ", // clomatch_index, clov_sofar, clodv_sofar); - + // What's our residual error, so that we can splice this // with minimal "click"? - residual = + spliceval - creal( modoutbackward[clomatch_index]); + residual = + spliceval - modoutbackward[clomatch_index].real(); // Move our wave, with the best match so far established, to // the output buffer area. for (l2 = 0; l2 < synthdata->cyclesize; l2++) { - data[0][l1][l2] = creal ( modoutbackward [ clomatch_index + l2]) + data[0][l1][l2] = modoutbackward[clomatch_index + l2].real() + ((1.0 - (float(l2) / float(synthdata->cyclesize))) * residual); }; @@ -466,17 +461,18 @@ void M_vocoder::generateCycle() { for (l2 = 0; l2 < fftsize - synthdata->cyclesize; l2++) { carrbuf [l1][l2] = carrbuf [l1][l2 + synthdata->cyclesize]; } + for (l2 = 0; l2 < synthdata->cyclesize; l2++) { carrbuf [l1][l2 + fftsize - synthdata->cyclesize] = inCarrier[l1][l2]; } - for (l2 = 0; l2 < unsigned (fftsize); l2++) { + for (l2 = 0; l2 < fftsize; l2++) { carrinforward [l2] = carrbuf [l1][l2] * window[l2]; } fftw_execute (plancarrforward); - for (l2 = 0; l2 < (unsigned) fftsize; l2++) { + for (l2 = 0; l2 < fftsize; l2++) { carrinbackward[l2] = carroutforward[l2]; }; @@ -486,34 +482,37 @@ void M_vocoder::generateCycle() { // Group the modulator into channels, and multipy the channels // over the carrier. - int localchannels; - localchannels = channels + vcchannels * inChannels[l1][0]; - if (localchannels < 1) localchannels = 1; - if (localchannels > fftsize - 1) localchannels = fftsize - 1; - for (l2 = 0; l2 < (unsigned) fftsize; l2++) { + unsigned int localchannels = channels + vcchannels * inChannels[l1][0]; + if (localchannels < 1) + localchannels = 1; + + if (localchannels > fftsize - 1) + localchannels = fftsize - 1; + + for (l2 = 0; l2 < fftsize; l2++) { modmap[l2] = 0; // initial conditions... if (l2 == 0) for (i = 0; i < channels; i++) - modmap[l2] += cabs (modoutforward[l2 + i]); + modmap[l2] += std::abs(modoutforward[l2 + i]); else modmap [l2] = modmap[l2 - 1]; // add the heads, subtract the tails i = l2 + channels; - if (l2 < (unsigned)fftsize - 2) - modmap[l2] += cabs( modoutforward [i] ); + if (l2 < fftsize - 2) + modmap[l2] += std::abs(modoutforward[i]); i = l2 - channels; if (l2 >= channels) - modmap[l2] -= cabs( modoutforward [i] ); + modmap[l2] -= std::abs(modoutforward[i]); } // Normalize the modmap - for (l2 = 0; l2 < (unsigned) fftsize; l2++) + for (l2 = 0; l2 < fftsize; l2++) modmap[l2] = modmap[l2] / localchannels; // Do attack/release - for (l2 = 0; l2 < (unsigned) fftsize; l2++) { + for (l2 = 0; l2 < fftsize; l2++) { if (modmap [l2] > armodmap[l2]) armodmap [l2] += (1 - attack) * (modmap[l2] - armodmap[l2]); if (modmap [l2] < armodmap[l2]) @@ -521,8 +520,8 @@ void M_vocoder::generateCycle() { } // multiply the carrier by the modulation map. - for (l2 = 0; l2 < (unsigned) fftsize; l2++) { - carrinbackward[l2] = carroutforward[l2] * armodmap[l2]; + for (l2 = 0; l2 < fftsize; l2++) { + carrinbackward[l2] = carroutforward[l2] * (double) armodmap[l2]; } // reverse transform to final output, and renormalize by 1/fftsize. @@ -532,8 +531,7 @@ void M_vocoder::generateCycle() { for (l2 = 0; l2 < synthdata->cyclesize; l2++) { offset = l2 + (fftsize/2) - (synthdata->cyclesize / 2); data[1][l1][l2]= - (creal(carroutbackward[offset]/window[offset])) / (fftsize * 100); + (carroutbackward[offset].real()/window[offset]) / (fftsize * 100); }; }; } - diff --git a/src/m_vocoder.h b/src/m_vocoder.h index 38eac58..32c8521 100644 --- a/src/m_vocoder.h +++ b/src/m_vocoder.h @@ -1,4 +1,4 @@ -/* +/* Vocoder - derived from m_delay.cpp Copyright (C) 2011 Bill Yerazunis @@ -22,7 +22,9 @@ #define M_VOCODER_H #include "module.h" -#include + +#include +#include #include #define MODULE_VOCODER_WIDTH 105 @@ -30,7 +32,7 @@ class M_vocoder : public Module { - Q_OBJECT + Q_OBJECT float channels, vcchannels; float attack, release; @@ -42,21 +44,20 @@ class M_vocoder : public Module Port *port_M_modulator, *port_M_pitchshift, *port_M_freqshift, *port_M_channels, *port_M_carrier; + Port *port_modfft_out, *port_firstharmonic_out, - *port_altmodulator_out, - *port_vocoder_out; + *port_altmodulator_out, *port_vocoder_out; - fftw_plan planmodforward, planmodbackward, + fftw_plan planmodforward, planmodbackward, plancarrforward, plancarrbackward; - fftw_complex *carrinforward, *carroutforward, - *carrinbackward, *carroutbackward, - *modinforward, *modoutforward, - *modinbackward, *modoutbackward; + std::vector> carrinforward, carroutforward, + carrinbackward, carroutbackward, + modinforward, modoutforward, + modinbackward, modoutbackward; - public: - int fftsize; - float **inModulator, **inPitchShift, **inFreqShift, + unsigned int fftsize; + float **inModulator, **inPitchShift, **inFreqShift, **inChannels, **inCarrier; // the previous time-based samples, for overlapping float **modbuf, **carrbuf; @@ -68,10 +69,10 @@ class M_vocoder : public Module float *armodmap; public: - float windowcurve (int windowfunc, int len, int elem, float alpha ); + float windowcurve (int windowfunc, unsigned int len, int elem, float alpha ); M_vocoder(QWidget* parent=0, int id = 0); ~M_vocoder(); void generateCycle(); }; - + #endif