diff --git a/src/DSPProcessFreeSurround.cpp b/src/DSPProcessFreeSurround.cpp index 42ebc26..ff45c86 100644 --- a/src/DSPProcessFreeSurround.cpp +++ b/src/DSPProcessFreeSurround.cpp @@ -30,8 +30,6 @@ #include "addon.h" #include "FreeSurroundSettings.h" -#define FFT_LENGTH 1024 - // our default internal block size, in floats static const unsigned default_block_size = SURROUND_BUFSIZE; unsigned int block_size = default_block_size; @@ -176,7 +174,7 @@ unsigned int CDSPProcess_FreeSurround::StreamProcess(float **array_in, float **a if (!m_Decoder) return samples; - float **outputs = m_Decoder->getOutputBuffers(); + float **outputs = m_Decoder->getOutputBuffers(); for (unsigned int pos = 0; pos < samples; ++pos) { diff --git a/src/FreeSurroundDecoder.cpp b/src/FreeSurroundDecoder.cpp index 6250325..86246fa 100644 --- a/src/FreeSurroundDecoder.cpp +++ b/src/FreeSurroundDecoder.cpp @@ -33,9 +33,8 @@ #include "FreeSurroundDecoder.h" -const float pi = 3.141592654f; -const float epsilon = 0.000001f; -using namespace std; +const double pi = 3.14159265358979323846; +const double epsilon = 0.000001; #ifndef TARGET_WINDOWS #undef min @@ -69,9 +68,9 @@ CFreeSurroundDecoder::CFreeSurroundDecoder(channel_setup setup, unsigned blocksi for (unsigned k=0; k < m_BufferSize; ++k) m_Window[k] = sqrt(0.5 * (1 - cos(2 * pi * k / m_BufferSize)) / m_BufferSize); - m_Destination = (double*)calloc(m_BufferSize, sizeof(double)); - m_TotalLeft = (double*)calloc(m_BufferSize, sizeof(double)); - m_TotalRight = (double*)calloc(m_BufferSize, sizeof(double)); + m_Destination = (float*)calloc(m_BufferSize, sizeof(float)); + m_TotalLeft = (float*)calloc(m_BufferSize, sizeof(float)); + m_TotalRight = (float*)calloc(m_BufferSize, sizeof(float)); m_FreqLeft = (cplx*)calloc(m_BufferSize / 2 + 1, sizeof(cplx)); m_FreqRight = (cplx*)calloc(m_BufferSize / 2 + 1, sizeof(cplx)); @@ -116,12 +115,15 @@ float **CFreeSurroundDecoder::getOutputBuffers() void CFreeSurroundDecoder::Decode(float **inputs) { + //! append incoming data to the end of the input buffer memcpy(&m_InputBuffer[0][m_BufferSizeHalf], &inputs[0][0], m_BufferSize*sizeof(float)); memcpy(&m_InputBuffer[1][m_BufferSizeHalf], &inputs[1][0], m_BufferSize*sizeof(float)); + //! process first and second half, overlapped BufferedDecode(m_InputBuffer, 0); BufferedDecode(m_InputBuffer, m_BufferSizeHalf); + //! shift last half of the input to the beginning (for overlapping with a future block) memcpy(&m_InputBuffer[0][0], &m_InputBuffer[0][m_BufferSize], m_BufferSizeHalf*sizeof(float)); memcpy(&m_InputBuffer[1][0], &m_InputBuffer[1][m_BufferSize], m_BufferSizeHalf*sizeof(float)); @@ -136,7 +138,7 @@ void CFreeSurroundDecoder::Flush() m_BufferEmpty = true; } -inline float CFreeSurroundDecoder::sqr(double x) +inline double CFreeSurroundDecoder::sqr(double x) { return x * x; } @@ -156,29 +158,29 @@ inline cplx CFreeSurroundDecoder::polar(double a, double p) return cplx(a * cos(p), a * sin(p)); } -inline float CFreeSurroundDecoder::Min(double a, double b) +inline double CFreeSurroundDecoder::Min(double a, double b) { return a < b ? a : b; } -inline float CFreeSurroundDecoder::Max(double a, double b) +inline double CFreeSurroundDecoder::Max(double a, double b) { return a > b ? a : b; } -inline float CFreeSurroundDecoder::clamp(double x) +inline double CFreeSurroundDecoder::clamp(double x) { return Max(-1, Min(1, x)); } -inline float CFreeSurroundDecoder::sign(double x) +inline double CFreeSurroundDecoder::sign(double x) { return x < 0 ? -1 : (x > 0 ? 1 : 0); } inline double CFreeSurroundDecoder::EdgeDistance(double a) { - return min(sqrt(1 + sqr(tan(a))), sqrt(1 + sqr(1 / tan(a)))); + return Min(sqrt(1 + sqr(tan(a))), sqrt(1 + sqr(1 / tan(a)))); } void CFreeSurroundDecoder::BufferedDecode(float *input[2], int ptr) @@ -191,11 +193,11 @@ void CFreeSurroundDecoder::BufferedDecode(float *input[2], int ptr) } //! map into spectral domain - kiss_fftr(m_FFTForward, &m_TotalLeft[0], (kiss_fft_cpx*)&m_FreqLeft[0]); - kiss_fftr(m_FFTForward, &m_TotalRight[0], (kiss_fft_cpx*)&m_FreqRight[0]); + kiss_fftr(m_FFTForward, m_TotalLeft, (kiss_fft_cpx*)m_FreqLeft); + kiss_fftr(m_FFTForward, m_TotalRight, (kiss_fft_cpx*)m_FreqRight); - // compute multichannel output signal in the spectral domain - for (unsigned f = 1; f < m_BufferSizeHalf; ++f) + //! compute multichannel output signal in the spectral domain + for (unsigned int f = 1; f < m_BufferSizeHalf; ++f) { //! get Lt/Rt amplitudes & phases double ampL = amplitude(m_FreqLeft[f]); @@ -232,7 +234,7 @@ void CFreeSurroundDecoder::BufferedDecode(float *input[2], int ptr) for (unsigned c = 0; c < m_Channels-1; ++c) { //! look up channel map at respective position (with bilinear interpolation) and build the signal - vector &a = chn_alloc[m_ChannelSetup][c]; + std::vector &a = chn_alloc[m_ChannelSetup][c]; m_Signal[c][f] = polar(amp_total*((1-x)*(1-y)*a[q][p] + x*(1-y)*a[q][p+1] + (1-x)*y*a[q+1][p] + x*y*a[q+1][p+1]), phase_of[1+(int)sign(chn_xsf[m_ChannelSetup][c])]); } @@ -241,7 +243,7 @@ void CFreeSurroundDecoder::BufferedDecode(float *input[2], int ptr) if (m_UseLFE && f < m_HighCutoff) { //! level of LFE channel according to normalized frequency - double lfe_level = f < m_LowCutoff ? 1 : 0.5*(1+cos(pi*(f-m_LowCutoff)/(m_HighCutoff-m_LowCutoff))); + float lfe_level = f < m_LowCutoff ? 1 : 0.5*(1+cos(pi*(f-m_LowCutoff)/(m_HighCutoff-m_LowCutoff))); //! assign LFE channel m_Signal[m_Channels-1][f] = lfe_level * polar(amp_total,phase_of[1]); //! subtract the signal from the other channels @@ -253,11 +255,11 @@ void CFreeSurroundDecoder::BufferedDecode(float *input[2], int ptr) for (unsigned channel = 0; channel < m_Channels; ++channel) { //! shift the last 2/3 to the first 2/3 of the output buffer - memcpy(&m_OutputBuffer[channel][0], &m_OutputBuffer[channel][m_BufferSizeHalf], m_BufferSize*sizeof(float)); + memcpy(&m_OutputBuffer[channel][0], &m_OutputBuffer[channel][m_BufferSizeHalf], m_BufferSize*sizeof(double)); //! and clear the rest - memset(&m_OutputBuffer[channel][m_BufferSize], 0, m_BufferSizeHalf*sizeof(float)); + memset(&m_OutputBuffer[channel][m_BufferSize], 0, m_BufferSizeHalf*sizeof(double)); - kiss_fftri(m_FFTInverse,(kiss_fft_cpx*)&m_Signal[channel][0], &m_Destination[0]); + kiss_fftri(m_FFTInverse, (kiss_fft_cpx*)m_Signal[channel], &m_Destination[0]); //! add the result to the last 2/3 of the output buffer, windowed (and remultiplex) for (unsigned k = 0; k < m_BufferSize; ++k) diff --git a/src/FreeSurroundDecoder.h b/src/FreeSurroundDecoder.h index ad563b0..d4ef061 100644 --- a/src/FreeSurroundDecoder.h +++ b/src/FreeSurroundDecoder.h @@ -27,7 +27,6 @@ #include -#define kiss_fft_scalar double //!< we're using doubles here... #include "kissfft/kiss_fftr.h" #include "ChannelMaps.h" @@ -66,7 +65,7 @@ typedef enum { cs_legacy = 0 // same channels as cs_5point1 but different upmixing transform; does not support the focus control } channel_setup; -typedef std::complex cplx; +typedef std::complex cplx; /** * The FreeSurround decoder. @@ -221,9 +220,9 @@ class CFreeSurroundDecoder bool m_UseLFE; //!< whether to use the LFE channel //! FFT data structures - double *m_Destination; - double *m_TotalLeft; //!< left total, (source arrays), time-domain destination buffer array - double *m_TotalRight; //!< right total, " + float *m_Destination; + float *m_TotalLeft; //!< left total, (source arrays), time-domain destination buffer array + float *m_TotalRight; //!< right total, " cplx *m_FreqLeft; //!< left total in frequency domain cplx *m_FreqRight; //!< right total in frequency domain kiss_fftr_cfg m_FFTForward; //!< FFT buffers @@ -237,14 +236,14 @@ class CFreeSurroundDecoder double *m_Window; //!< the window function, precomputed //! helper functions - static inline float sqr(double x); + static inline double sqr(double x); static inline double amplitude(const cplx &x); static inline double phase(const cplx &x); static inline cplx polar(double a, double p); - static inline float Min(double a, double b); - static inline float Max(double a, double b); - static inline float clamp(double x); - static inline float sign(double x); + static inline double Min(double a, double b); + static inline double Max(double a, double b); + static inline double clamp(double x); + static inline double sign(double x); //!> get the distance of the soundfield edge, along a given angle static inline double EdgeDistance(double a);