From 401e6ccb121726850242cd4d8d710049bc82fc92 Mon Sep 17 00:00:00 2001 From: Ricardo Wurmus Date: Sat, 13 Jun 2020 23:47:14 +0200 Subject: gnu: alsa-modular-synth: Add patch to fix vocoder build error. * gnu/packages/patches/alsa-modular-synth-fix-vocoder.patch: New file. * gnu/local.mk (dist_patch_DATA): Add it. * gnu/packages/audio.scm (alsa-modular-synth)[source]: Add it. --- gnu/packages/audio.scm | 4 +- .../patches/alsa-modular-synth-fix-vocoder.patch | 522 +++++++++++++++++++++ 2 files changed, 525 insertions(+), 1 deletion(-) create mode 100644 gnu/packages/patches/alsa-modular-synth-fix-vocoder.patch (limited to 'gnu/packages') diff --git a/gnu/packages/audio.scm b/gnu/packages/audio.scm index c8d15a3bb7..7f9720d257 100644 --- a/gnu/packages/audio.scm +++ b/gnu/packages/audio.scm @@ -175,7 +175,9 @@ implementation of Adaptive Multi Rate Narrowband and Wideband "/" version "/ams-" version ".tar.bz2")) (sha256 (base32 - "1azbrhpfk4nnybr7kgmc7w6al6xnzppg853vas8gmkh185kk11l0")))) + "1azbrhpfk4nnybr7kgmc7w6al6xnzppg853vas8gmkh185kk11l0")) + (patches + (search-patches "alsa-modular-synth-fix-vocoder.patch")))) (build-system gnu-build-system) (arguments `(#:configure-flags diff --git a/gnu/packages/patches/alsa-modular-synth-fix-vocoder.patch b/gnu/packages/patches/alsa-modular-synth-fix-vocoder.patch new file mode 100644 index 0000000000..33a68a1dd8 --- /dev/null +++ b/gnu/packages/patches/alsa-modular-synth-fix-vocoder.patch @@ -0,0 +1,522 @@ +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 -- cgit v1.2.3