diff --git a/CMakeLists.txt b/CMakeLists.txt index ad10182ceb..99b3e58d89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -587,6 +587,11 @@ else() set(PNG png) endif() +# Using static FreeSurround from Externals +# There is no system FreeSurround library. +message(STATUS "Using static FreeSurround from Externals") +add_subdirectory(Externals/FreeSurround) + if (APPLE) message(STATUS "Using ed25519 from Externals") add_subdirectory(Externals/ed25519) diff --git a/Externals/FreeSurround/CMakeLists.txt b/Externals/FreeSurround/CMakeLists.txt new file mode 100644 index 0000000000..6d488f155e --- /dev/null +++ b/Externals/FreeSurround/CMakeLists.txt @@ -0,0 +1,14 @@ +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +set(SRCS + source/ChannelMaps.cpp + source/KissFFT.cpp + source/KissFFTR.cpp + source/FreeSurroundDecoder.cpp +) + +add_library(FreeSurround STATIC ${SRCS}) +target_include_directories(FreeSurround PUBLIC include) +target_compile_options(FreeSurround PRIVATE -w) diff --git a/Externals/FreeSurround/FreeSurround.vcxproj b/Externals/FreeSurround/FreeSurround.vcxproj new file mode 100644 index 0000000000..baf9df7ed4 --- /dev/null +++ b/Externals/FreeSurround/FreeSurround.vcxproj @@ -0,0 +1,53 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {8498F2FA-5CA6-4169-9971-DE5B1FE6132C} + + + + StaticLibrary + v141 + Unicode + + + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Externals/FreeSurround/FreeSurround.vcxproj.filters b/Externals/FreeSurround/FreeSurround.vcxproj.filters new file mode 100644 index 0000000000..65dd14ee66 --- /dev/null +++ b/Externals/FreeSurround/FreeSurround.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + source + + + source + + + source + + + source + + + + + include + + + include + + + include + + + include + + + include + + + + + {776ecb31-6d5e-489f-bac9-b91a1b202345} + + + {11345325-d67c-4a21-b2e9-c7c6c8cfc8b4} + + + \ No newline at end of file diff --git a/Externals/FreeSurround/include/FreeSurround/ChannelMaps.h b/Externals/FreeSurround/include/FreeSurround/ChannelMaps.h new file mode 100644 index 0000000000..9ff4c3a8cf --- /dev/null +++ b/Externals/FreeSurround/include/FreeSurround/ChannelMaps.h @@ -0,0 +1,36 @@ +/* +Copyright (C) 2010 Christian Kothe + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +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 for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef CHANNELMAPS_H +#define CHANNELMAPS_H +#include "FreeSurroundDecoder.h" +#include +#include + +const int grid_res = 21; // resolution of the lookup grid + +// channel allocation maps (per setup) +typedef std::vector> alloc_lut; +extern std::map chn_alloc; +// channel metadata maps (per setup) +extern std::map> chn_angle; +extern std::map> chn_xsf; +extern std::map> chn_ysf; +extern std::map> chn_id; + +#endif diff --git a/Externals/FreeSurround/include/FreeSurround/FreeSurroundDecoder.h b/Externals/FreeSurround/include/FreeSurround/FreeSurroundDecoder.h new file mode 100644 index 0000000000..0aa51d5739 --- /dev/null +++ b/Externals/FreeSurround/include/FreeSurround/FreeSurroundDecoder.h @@ -0,0 +1,209 @@ +// Copyright (C) 2007-2010 Christian Kothe +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +// USA. + +#ifndef FREESURROUND_DECODER_H +#define FREESURROUND_DECODER_H +#include "KissFFTR.h" +#include +#include + +typedef std::complex cplx; + +// Identifiers for the supported output channels (from front to back, left to +// right). The ordering here also determines the ordering of interleaved +// samples in the output signal. + +typedef enum channel_id { + ci_none = 0, + ci_front_left = 1 << 1, + ci_front_center_left = 1 << 2, + ci_front_center = 1 << 3, + ci_front_center_right = 1 << 4, + ci_front_right = 1 << 5, + ci_side_front_left = 1 << 6, + ci_side_front_right = 1 << 7, + ci_side_center_left = 1 << 8, + ci_side_center_right = 1 << 9, + ci_side_back_left = 1 << 10, + ci_side_back_right = 1 << 11, + ci_back_left = 1 << 12, + ci_back_center_left = 1 << 13, + ci_back_center = 1 << 14, + ci_back_center_right = 1 << 15, + ci_back_right = 1 << 16, + ci_lfe = 1 << 31 +} channel_id; + +// The supported output channel setups. A channel setup is defined by the set +// of channels that are present. Here is a graphic of the cs_5point1 setup: +// http://en.wikipedia.org/wiki/File:5_1_channels_(surround_sound)_label.svg +typedef enum channel_setup { + cs_5point1 = ci_front_left | ci_front_center | ci_front_right | ci_back_left | + ci_back_right | ci_lfe, + + cs_7point1 = ci_front_left | ci_front_center | ci_front_right | + ci_side_center_left | ci_side_center_right | ci_back_left | + ci_back_right | ci_lfe +} channel_setup; + +// The FreeSurround decoder. + +class DPL2FSDecoder { +public: + // Create an instance of the decoder. + // @param setup The output channel setup -- determines the number of output + // channels and their place in the sound field. + // @param blocksize Granularity at which data is processed by the decode() + // function. Must be a power of two and should correspond to ca. 10ms worth + // of single-channel samples (default is 4096 for 44.1Khz data). Do not make + // it shorter or longer than 5ms to 20ms since the granularity at which + // locations are decoded changes with this. + DPL2FSDecoder(); + ~DPL2FSDecoder(); + + void Init(channel_setup setup = cs_5point1, unsigned int blocksize = 4096, + unsigned int samplerate = 48000); + + // Decode a chunk of stereo sound. The output is delayed by half of the + // blocksize. This function is the only one needed for straightforward + // decoding. + // @param input Contains exactly blocksize (multiplexed) stereo samples, i.e. + // 2*blocksize numbers. + // @return A pointer to an internal buffer of exactly blocksize (multiplexed) + // multichannel samples. The actual number of values depends on the number of + // output channels in the chosen channel setup. + float *decode(float *input); + + // Flush the internal buffer. + void flush(); + + // set soundfield & rendering parameters + // for more information, see full FreeSurround source code + void set_circular_wrap(float v); + void set_shift(float v); + void set_depth(float v); + void set_focus(float v); + void set_center_image(float v); + void set_front_separation(float v); + void set_rear_separation(float v); + void set_low_cutoff(float v); + void set_high_cutoff(float v); + void set_bass_redirection(bool v); + + // number of samples currently held in the buffer + unsigned int buffered(); + +private: + // constants + const float pi = 3.141592654f; + const float epsilon = 0.000001f; + + // number of samples per input/output block, number of output channels + unsigned int N, C; + unsigned int samplerate; + + // the channel setup + channel_setup setup; + bool initialized; + + // parameters + // angle of the front soundstage around the listener (90\B0=default) + float circular_wrap; + + // forward/backward offset of the soundstage + float shift; + + // backward extension of the soundstage + float depth; + + // localization of the sound events + float focus; + + // presence of the center speaker + float center_image; + + // front stereo separation + float front_separation; + + // rear stereo separation + float rear_separation; + + // LFE cutoff frequencies + float lo_cut, hi_cut; + + // whether to use the LFE channel + bool use_lfe; + + // FFT data structures + // left total, right total (source arrays), time-domain destination buffer + // array + std::vector lt, rt, dst; + + // left total / right total in frequency domain + std::vector lf, rf; + + // FFT buffers + kiss_fftr_cfg forward, inverse; + + // buffers + // whether the buffer is currently empty or dirty + bool buffer_empty; + + // stereo input buffer (multiplexed) + std::vector inbuf; + + // multichannel output buffer (multiplexed) + std::vector outbuf; + + // the window function, precomputed + std::vector wnd; + + // the signal to be constructed in every channel, in the frequency domain + // instantiate the decoder with a given channel setup and processing block + // size (in samples) + std::vector> signal; + + // helper functions + inline float sqr(double x); + inline double amplitude(const cplx &x); + inline double phase(const cplx &x); + inline cplx polar(double a, double p); + inline float min(double a, double b); + inline float max(double a, double b); + inline float clamp(double x); + inline float sign(double x); + + // get the distance of the soundfield edge, along a given angle + inline double edgedistance(double a); + + // get the index (and fractional offset!) in a piecewise-linear channel + // allocation grid + int map_to_grid(double &x); + + // decode a block of data and overlap-add it into outbuf + void buffered_decode(float *input); + + // transform amp/phase difference space into x/y soundfield space + void transform_decode(double a, double p, double &x, double &y); + + // apply a circular_wrap transformation to some position + void transform_circular_wrap(double &x, double &y, double refangle); + + // apply a focus transformation to some position + void transform_focus(double &x, double &y, double focus); +}; +#endif diff --git a/Externals/FreeSurround/include/FreeSurround/KissFFT.h b/Externals/FreeSurround/include/FreeSurround/KissFFT.h new file mode 100644 index 0000000000..5b52102101 --- /dev/null +++ b/Externals/FreeSurround/include/FreeSurround/KissFFT.h @@ -0,0 +1,131 @@ +#ifndef KISS_FFT_H +#define KISS_FFT_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// we're using doubles here... +#define kiss_fft_scalar double + +/* + ATTENTION! + If you would like a : + -- a utility that will handle the caching of fft objects + -- real-only (no imaginary time component ) FFT + -- a multi-dimensional FFT + -- a command-line utility to perform ffts + -- a command-line utility to perform fast-convolution filtering + + Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c + in the tools/ directory. +*/ + +#ifdef USE_SIMD +#include +#define kiss_fft_scalar __m128 +#define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes, 16) +#define KISS_FFT_FREE _mm_free +#else +#define KISS_FFT_MALLOC malloc +#define KISS_FFT_FREE free +#endif + +#ifdef FIXED_POINT +#include +#if (FIXED_POINT == 32) +#define kiss_fft_scalar int32_t +#else +#define kiss_fft_scalar int16_t +#endif +#else +#ifndef kiss_fft_scalar +/* default is float */ +#define kiss_fft_scalar float +#endif +#endif + +typedef struct { + kiss_fft_scalar r; + kiss_fft_scalar i; +} kiss_fft_cpx; + +typedef struct kiss_fft_state *kiss_fft_cfg; + +/* + * kiss_fft_alloc + * + * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. + * + * typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL); + * + * The return value from fft_alloc is a cfg buffer used internally + * by the fft routine or NULL. + * + * If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using + * malloc. + * The returned value should be free()d when done to avoid memory leaks. + * + * The state can be placed in a user supplied buffer 'mem': + * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, + * then the function places the cfg in mem and the size used in *lenmem + * and returns mem. + * + * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), + * then the function returns NULL and places the minimum cfg + * buffer size in *lenmem. + * */ + +kiss_fft_cfg kiss_fft_alloc(int nfft, int inverse_fft, void *mem, + size_t *lenmem); + +/* + * kiss_fft(cfg,in_out_buf) + * + * Perform an FFT on a complex input buffer. + * for a forward FFT, + * fin should be f[0] , f[1] , ... ,f[nfft-1] + * fout will be F[0] , F[1] , ... ,F[nfft-1] + * Note that each element is complex and can be accessed like + f[k].r and f[k].i + * */ +void kiss_fft(kiss_fft_cfg cfg, const kiss_fft_cpx *fin, kiss_fft_cpx *fout); + +/* + A more generic version of the above function. It reads its input from every Nth + sample. + * */ +void kiss_fft_stride(kiss_fft_cfg cfg, const kiss_fft_cpx *fin, + kiss_fft_cpx *fout, int fin_stride); + +/* If kiss_fft_alloc allocated a buffer, it is one contiguous + buffer and can be simply free()d when no longer needed*/ +#define kiss_fft_free free + +/* + Cleans up some memory that gets managed internally. Not necessary to call, but + it might clean up + your compiler output to call this before you exit. +*/ +void kiss_fft_cleanup(void); + +/* + * Returns the smallest integer k, such that k>=n and k has only "fast" factors + * (2,3,5) + */ +int kiss_fft_next_fast_size(int n); + +/* for real ffts, we need an even size */ +#define kiss_fftr_next_fast_size_real(n) \ + (kiss_fft_next_fast_size(((n) + 1) >> 1) << 1) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Externals/FreeSurround/include/FreeSurround/KissFFTR.h b/Externals/FreeSurround/include/FreeSurround/KissFFTR.h new file mode 100644 index 0000000000..8c310ca8d1 --- /dev/null +++ b/Externals/FreeSurround/include/FreeSurround/KissFFTR.h @@ -0,0 +1,47 @@ +#ifndef KISS_FTR_H +#define KISS_FTR_H + +#include "KissFFT.h" +#ifdef __cplusplus +extern "C" { +#endif + +/* + + Real optimized version can save about 45% cpu time vs. complex fft of a real + seq. + + + + */ + +typedef struct kiss_fftr_state *kiss_fftr_cfg; + +kiss_fftr_cfg kiss_fftr_alloc(int nfft, int inverse_fft, void *mem, + size_t *lenmem); +/* + nfft must be even + + If you don't care to allocate space, use mem = lenmem = NULL +*/ + +void kiss_fftr(kiss_fftr_cfg cfg, const kiss_fft_scalar *timedata, + kiss_fft_cpx *freqdata); +/* + input timedata has nfft scalar points + output freqdata has nfft/2+1 complex points +*/ + +void kiss_fftri(kiss_fftr_cfg cfg, const kiss_fft_cpx *freqdata, + kiss_fft_scalar *timedata); +/* + input freqdata has nfft/2+1 complex points + output timedata has nfft scalar points +*/ + +#define kiss_fftr_free free + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Externals/FreeSurround/include/FreeSurround/_KissFFTGuts.h b/Externals/FreeSurround/include/FreeSurround/_KissFFTGuts.h new file mode 100644 index 0000000000..dc234495ad --- /dev/null +++ b/Externals/FreeSurround/include/FreeSurround/_KissFFTGuts.h @@ -0,0 +1,202 @@ +/* +Copyright (c) 2003-2010, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted +provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, +this list of conditions +and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, +this list of +conditions and the following disclaimer in the documentation and/or other +materials provided with +the distribution. + * Neither the author nor the names of any contributors may be used to +endorse or promote +products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* kiss_fft.h + defines kiss_fft_scalar as either short or a float type + and defines + typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ +#include "KissFFT.h" +#include + +#define MAXFACTORS 32 +/* e.g. an fft of length 128 has 4 factors + as far as kissfft is concerned + 4*4*4*2 + */ + +struct kiss_fft_state { + int nfft; + int inverse; + int factors[2 * MAXFACTORS]; + kiss_fft_cpx twiddles[1]; +}; + +/* + Explanation of macros dealing with complex math: + + C_MUL(m,a,b) : m = a*b + C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise + C_SUB( res, a,b) : res = a - b + C_SUBFROM( res , a) : res -= a + C_ADDTO( res , a) : res += a + * */ +#ifdef FIXED_POINT +#if (FIXED_POINT == 32) +#define FRACBITS 31 +#define SAMPPROD int64_t +#define SAMP_MAX 2147483647 +#else +#define FRACBITS 15 +#define SAMPPROD int32_t +#define SAMP_MAX 32767 +#endif + +#define SAMP_MIN -SAMP_MAX + +#if defined(CHECK_OVERFLOW) +#define CHECK_OVERFLOW_OP(a, op, b) \ + if ((SAMPPROD)(a)op(SAMPPROD)(b) > SAMP_MAX || \ + (SAMPPROD)(a)op(SAMPPROD)(b) < SAMP_MIN) { \ + fprintf(stderr, \ + "WARNING:overflow @ " __FILE__ "(%d): (%d " #op " %d) = %ld\n", \ + __LINE__, (a), (b), (SAMPPROD)(a)op(SAMPPROD)(b)); \ + } +#endif + +#define smul(a, b) ((SAMPPROD)(a) * (b)) +#define sround(x) (kiss_fft_scalar)(((x) + (1 << (FRACBITS - 1))) >> FRACBITS) + +#define S_MUL(a, b) sround(smul(a, b)) + +#define C_MUL(m, a, b) \ + do { \ + (m).r = sround(smul((a).r, (b).r) - smul((a).i, (b).i)); \ + (m).i = sround(smul((a).r, (b).i) + smul((a).i, (b).r)); \ + } while (0) + +#define DIVSCALAR(x, k) (x) = sround(smul(x, SAMP_MAX / k)) + +#define C_FIXDIV(c, div) \ + do { \ + DIVSCALAR((c).r, div); \ + DIVSCALAR((c).i, div); \ + } while (0) + +#define C_MULBYSCALAR(c, s) \ + do { \ + (c).r = sround(smul((c).r, s)); \ + (c).i = sround(smul((c).i, s)); \ + } while (0) + +#else /* not FIXED_POINT*/ + +#define S_MUL(a, b) ((a) * (b)) +#define C_MUL(m, a, b) \ + do { \ + (m).r = (a).r * (b).r - (a).i * (b).i; \ + (m).i = (a).r * (b).i + (a).i * (b).r; \ + } while (0) +#define C_FIXDIV(c, div) /* NOOP */ +#define C_MULBYSCALAR(c, s) \ + do { \ + (c).r *= (s); \ + (c).i *= (s); \ + } while (0) +#endif + +#ifndef CHECK_OVERFLOW_OP +#define CHECK_OVERFLOW_OP(a, op, b) /* noop */ +#endif + +#define C_ADD(res, a, b) \ + do { \ + CHECK_OVERFLOW_OP((a).r, +, (b).r) \ + CHECK_OVERFLOW_OP((a).i, +, (b).i) \ + (res).r = (a).r + (b).r; \ + (res).i = (a).i + (b).i; \ + } while (0) +#define C_SUB(res, a, b) \ + do { \ + CHECK_OVERFLOW_OP((a).r, -, (b).r) \ + CHECK_OVERFLOW_OP((a).i, -, (b).i) \ + (res).r = (a).r - (b).r; \ + (res).i = (a).i - (b).i; \ + } while (0) +#define C_ADDTO(res, a) \ + do { \ + CHECK_OVERFLOW_OP((res).r, +, (a).r) \ + CHECK_OVERFLOW_OP((res).i, +, (a).i) \ + (res).r += (a).r; \ + (res).i += (a).i; \ + } while (0) + +#define C_SUBFROM(res, a) \ + do { \ + CHECK_OVERFLOW_OP((res).r, -, (a).r) \ + CHECK_OVERFLOW_OP((res).i, -, (a).i) \ + (res).r -= (a).r; \ + (res).i -= (a).i; \ + } while (0) + +#ifdef FIXED_POINT +#define KISS_FFT_COS(phase) floor(.5 + SAMP_MAX * cos(phase)) +#define KISS_FFT_SIN(phase) floor(.5 + SAMP_MAX * sin(phase)) +#define HALF_OF(x) ((x) >> 1) +#elif defined(USE_SIMD) +#define KISS_FFT_COS(phase) _mm_set1_ps(cos(phase)) +#define KISS_FFT_SIN(phase) _mm_set1_ps(sin(phase)) +#define HALF_OF(x) ((x)*_mm_set1_ps(.5)) +#else +#define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) +#define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) +#define HALF_OF(x) ((x)*.5) +#endif + +#define kf_cexp(x, phase) \ + do { \ + (x)->r = KISS_FFT_COS(phase); \ + (x)->i = KISS_FFT_SIN(phase); \ + } while (0) + +/* a debugging function */ +#define pcpx(c) \ + fprintf(stderr, "%g + %gi\n", (double)((c)->r), (double)((c)->i)) + +#ifdef KISS_FFT_USE_ALLOCA +// define this to allow use of alloca instead of malloc for temporary buffers +// Temporary buffers are used in two case: +// 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5 +// 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an +// in-place transform. +#include +#define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes) +#define KISS_FFT_TMP_FREE(ptr) +#else +#define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes) +#define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr) +#endif diff --git a/Externals/FreeSurround/source/ChannelMaps.cpp b/Externals/FreeSurround/source/ChannelMaps.cpp new file mode 100644 index 0000000000..c3a9a4ab40 --- /dev/null +++ b/Externals/FreeSurround/source/ChannelMaps.cpp @@ -0,0 +1,1148 @@ +/* +Copyright (C) 2010 Christian Kothe + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +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 for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include "FreeSurround/ChannelMaps.h" + +float map_5point1_ang[] = {-27, 0, 27, -105, 105}; +float map_5point1_xsf[] = {-1, 0, 1, -1, 1}; +float map_5point1_ysf[] = {1, 1, 1, -1, -1}; +channel_id map_5point1_id[] = {ci_front_left, ci_front_center, ci_front_right, + ci_back_left, ci_back_right, ci_lfe}; + +float map_5point1_lf[21][21] = { + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.054079f, 0.13605f, 0.11031f, 0.083738f, 0.058746f, 0.03616f, + 0.022585f, 0.018356f, 0.012179f, 0.0043961f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.11103f, 0.16562f, 0.18635f, 0.15778f, 0.12791f, 0.12403f, + 0.10709f, 0.090176f, 0.070512f, 0.049741f, 0.027549f, 0.011727f, + 0.0013628f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.17535f, 0.20208f, 0.21809f, 0.22862f, 0.21842f, 0.20197f, + 0.18341f, 0.15706f, 0.13031f, 0.10103f, 0.068601f, 0.041975f, + 0.018696f, 0.0039144f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.24362f, 0.24543f, 0.25563f, 0.27972f, 0.28786f, 0.26979f, + 0.24789f, 0.21805f, 0.18569f, 0.14921f, 0.10871f, 0.073541f, + 0.041097f, 0.017152f, 0.0038597f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.3173f, 0.29703f, 0.31848f, 0.33006f, 0.33185f, 0.32571f, + 0.30203f, 0.27305f, 0.23691f, 0.19431f, 0.14844f, 0.10174f, + 0.061737f, 0.03134f, 0.010908f, 0.0013625f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.39394f, 0.36121f, 0.3753f, 0.38051f, 0.37306f, 0.35451f, + 0.33178f, 0.30958f, 0.28023f, 0.23726f, 0.18262f, 0.12638f, + 0.07899f, 0.043546f, 0.017841f, 0.00044495f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.47562f, 0.43164f, 0.43211f, 0.42477f, 0.4019f, 0.37291f, + 0.34131f, 0.31385f, 0.29675f, 0.2674f, 0.21259f, 0.14347f, + 0.086077f, 0.046322f, 0.012467f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.55484f, 0.49969f, 0.48539f, 0.45665f, 0.41889f, 0.37886f, + 0.33895f, 0.30764f, 0.28138f, 0.2723f, 0.23279f, 0.14674f, + 0.083778f, 0.032293f, 0.0048976f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.63203f, 0.56664f, 0.52742f, 0.47709f, 0.42408f, 0.37424f, + 0.33419f, 0.30176f, 0.27482f, 0.25011f, 0.23665f, 0.1471f, + 0.082204f, 0.040759f, 0.015195f, 0.0028496f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.70711f, 0.63601f, 0.56403f, 0.49301f, 0.42572f, 0.37154f, + 0.33227f, 0.30051f, 0.27246f, 0.24769f, 0.22385f, 0.17996f, + 0.13303f, 0.089089f, 0.051572f, 0.021112f, 0.0019269f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.77384f, 0.69829f, 0.59208f, 0.49896f, 0.42627f, 0.37547f, + 0.33559f, 0.30342f, 0.27695f, 0.2532f, 0.24555f, 0.24096f, + 0.202f, 0.15312f, 0.099312f, 0.049149f, 0.01419f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.83292f, 0.75424f, 0.62497f, 0.51188f, 0.43577f, 0.38288f, + 0.34157f, 0.31064f, 0.28485f, 0.27588f, 0.27011f, 0.26791f, + 0.24233f, 0.19874f, 0.14444f, 0.081488f, 0.031102f, 0.0022352f, + 0.000000f, 0.000000f, 0.000000f}, + {0.88048f, 0.80823f, 0.66178f, 0.53219f, 0.45043f, 0.39421f, + 0.35046f, 0.32046f, 0.30985f, 0.30176f, 0.29791f, 0.28855f, + 0.26277f, 0.22895f, 0.1783f, 0.11122f, 0.048526f, 0.0073556f, + 0.000000f, 0.000000f, 0.000000f}, + {0.91982f, 0.8564f, 0.6966f, 0.55364f, 0.46596f, 0.41011f, 0.36623f, + 0.3499f, 0.34025f, 0.33348f, 0.32389f, 0.30536f, 0.27602f, 0.24046f, + 0.19967f, 0.13416f, 0.066173f, 0.014462f, 0.000000f, 0.000000f, 0.000000f}, + {0.94888f, 0.8756f, 0.72118f, 0.58509f, 0.49378f, 0.42727f, 0.40951f, + 0.39303f, 0.37927f, 0.36377f, 0.34295f, 0.31626f, 0.28156f, 0.24129f, + 0.19667f, 0.15218f, 0.075526f, 0.017441f, 0.000000f, 0.000000f, 0.000000f}, + {0.9703f, 0.87092f, 0.76228f, 0.60765f, 0.51716f, 0.48514f, 0.45531f, + 0.43328f, 0.40894f, 0.38299f, 0.35389f, 0.31939f, 0.27862f, 0.23237f, + 0.18465f, 0.12881f, 0.081296f, 0.019071f, 0.000000f, 0.000000f, 0.000000f}, + {0.98481f, 0.85688f, 0.73952f, 0.62982f, 0.5767f, 0.53382f, 0.4939f, + 0.46098f, 0.42667f, 0.39124f, 0.35254f, 0.31034f, 0.26195f, 0.20782f, + 0.15167f, 0.09417f, 0.04946f, 0.016531f, 0.000000f, 0.000000f, 0.000000f}, + {0.99396f, 0.83616f, 0.71307f, 0.68155f, 0.64457f, 0.57478f, + 0.52315f, 0.47464f, 0.42859f, 0.38222f, 0.33181f, 0.27965f, + 0.21975f, 0.15464f, 0.094607f, 0.047925f, 0.0098814f, 0.0024671f, + 0.000000f, 0.000000f, 0.000000f}, + {0.99855f, 0.81216f, 0.78057f, 0.73849f, 0.68375f, 0.61653f, + 0.5369f, 0.46213f, 0.39741f, 0.33339f, 0.26339f, 0.19725f, + 0.13069f, 0.067274f, 0.019339f, 0.0021311f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {1.000000f, 0.94446f, 0.8823f, 0.80914f, 0.72626f, 0.63102f, + 0.52519f, 0.40402f, 0.27711f, 0.14046f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}}; + +float map_5point1_cf[21][21] = { + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0019269f, + 0.00062925f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.00059225f, 0.001914f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0055425f, 0.0155f, + 0.025167f, 0.017695f, 0.0063155f, 1.0116e-005f, 0.000000f, 0.000000f, + 0.0062031f, 0.017508f, 0.025125f, 0.015305f, 0.0054168f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.0056317f, 0.024256f, 0.044322f, + 0.061583f, 0.065405f, 0.041656f, 0.014688f, 4.0817e-019f, 0.014527f, + 0.041389f, 0.065342f, 0.061236f, 0.044002f, 0.024003f, 0.005504f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.0019274f, 0.02644f, 0.05812f, 0.08731f, + 0.11105f, 0.11767f, 0.10963f, 0.061306f, 0.017226f, 0.061006f, + 0.10958f, 0.11735f, 0.11066f, 0.086884f, 0.057744f, 0.026151f, + 0.0018503f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.016697f, 0.059451f, 0.104f, 0.13974f, + 0.15702f, 0.15962f, 0.15223f, 0.13355f, 0.063692f, 0.13353f, + 0.15211f, 0.15945f, 0.15675f, 0.13934f, 0.10352f, 0.059047f, + 0.016456f, 0.000000f, 0.000000f}, + {0.000000f, 1.2068e-018f, 0.038851f, 0.096919f, 0.15087f, 0.17987f, + 0.18511f, 0.17445f, 0.15817f, 0.14379f, 0.13384f, 0.14378f, + 0.15816f, 0.17444f, 0.18509f, 0.17981f, 0.15076f, 0.096821f, + 0.038797f, 0.000000f, 0.000000f}, + {0.000000f, 0.0063777f, 0.070344f, 0.14288f, 0.19068f, 0.2049f, + 0.19453f, 0.1758f, 0.16036f, 0.14645f, 0.14681f, 0.14646f, + 0.16036f, 0.1758f, 0.19453f, 0.20473f, 0.19031f, 0.14227f, + 0.06984f, 0.0061903f, 0.000000f}, + {0.000000f, 0.017224f, 0.099719f, 0.18101f, 0.21822f, 0.2193f, + 0.19777f, 0.17979f, 0.16475f, 0.16187f, 0.16149f, 0.16187f, + 0.16477f, 0.1798f, 0.19777f, 0.21922f, 0.21792f, 0.18045f, + 0.099116f, 0.016918f, 0.000000f}, + {0.000000f, 0.02596f, 0.12753f, 0.21148f, 0.23925f, 0.22819f, 0.20284f, + 0.18535f, 0.18085f, 0.17814f, 0.17812f, 0.17814f, 0.18084f, 0.18536f, + 0.20284f, 0.22818f, 0.23901f, 0.21095f, 0.12685f, 0.025562f, 0.000000f}, + {0.000000f, 0.03194f, 0.15144f, 0.23904f, 0.2564f, 0.23733f, 0.21182f, + 0.20371f, 0.19964f, 0.19751f, 0.19694f, 0.1975f, 0.19963f, 0.20369f, + 0.21184f, 0.23733f, 0.25621f, 0.23853f, 0.15068f, 0.031485f, 0.000000f}, + {0.000000f, 0.051138f, 0.17541f, 0.26062f, 0.27419f, 0.24713f, 0.23812f, + 0.22985f, 0.2244f, 0.22133f, 0.22022f, 0.22132f, 0.22439f, 0.22984f, + 0.2381f, 0.24715f, 0.274f, 0.26009f, 0.17455f, 0.050511f, 0.000000f}, + {0.000000f, 0.08308f, 0.18105f, 0.28155f, 0.29188f, 0.28632f, 0.27128f, + 0.26327f, 0.25585f, 0.25151f, 0.25234f, 0.2515f, 0.25584f, 0.26325f, + 0.27127f, 0.28627f, 0.29189f, 0.28098f, 0.18013f, 0.082312f, 0.000000f}, + {0.000000f, 0.11865f, 0.22314f, 0.29977f, 0.32517f, 0.33282f, 0.32312f, + 0.31164f, 0.30095f, 0.2946f, 0.29542f, 0.29459f, 0.30094f, 0.31163f, + 0.32308f, 0.33259f, 0.32473f, 0.29967f, 0.22211f, 0.11774f, 0.000000f}, + {0.000000f, 0.15601f, 0.26339f, 0.30497f, 0.3472f, 0.38198f, 0.39609f, + 0.39135f, 0.3765f, 0.36616f, 0.36703f, 0.36615f, 0.37649f, 0.39123f, + 0.39574f, 0.3814f, 0.34627f, 0.30393f, 0.26322f, 0.15497f, 0.000000f}, + {0.000000f, 0.19222f, 0.23448f, 0.28578f, 0.34732f, 0.4169f, 0.48293f, + 0.51439f, 0.52067f, 0.52104f, 0.52661f, 0.52086f, 0.52026f, 0.51365f, + 0.48176f, 0.41543f, 0.34579f, 0.28436f, 0.23319f, 0.19202f, 0.000000f}, + {1.1102e-016f, 0.076479f, 0.15764f, 0.24801f, 0.34452f, 0.44874f, + 0.55712f, 0.67263f, 0.78467f, 0.89574f, 1.000000f, 0.89382f, + 0.78261f, 0.67046f, 0.55485f, 0.4464f, 0.34213f, 0.24558f, + 0.15519f, 0.074014f, 0.000000f}}; + +float map_5point1_rf[21][21] = { + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0043772f, + 0.011962f, 0.018075f, 0.022264f, 0.035717f, 0.058204f, 0.083257f, + 0.10958f, 0.13592f, 0.052336f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.0013084f, 0.011636f, 0.027472f, 0.049384f, + 0.070085f, 0.089694f, 0.10655f, 0.12342f, 0.12737f, 0.15705f, + 0.18623f, 0.16489f, 0.10973f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.0038919f, 0.018492f, 0.041753f, 0.068513f, 0.1006f, + 0.12983f, 0.15652f, 0.18313f, 0.20135f, 0.21775f, 0.22851f, + 0.21738f, 0.20108f, 0.17363f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.0038302f, 0.016973f, 0.040831f, 0.073199f, 0.10859f, 0.14876f, + 0.1852f, 0.21753f, 0.24734f, 0.26927f, 0.28776f, 0.27908f, + 0.25473f, 0.24451f, 0.24192f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0013625f, + 0.010822f, 0.031114f, 0.061436f, 0.10138f, 0.14831f, 0.19392f, + 0.2365f, 0.27257f, 0.30156f, 0.32564f, 0.33123f, 0.32934f, + 0.31761f, 0.29589f, 0.31565f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.00041878f, + 0.017789f, 0.0433f, 0.07868f, 0.12602f, 0.18248f, 0.23686f, + 0.2799f, 0.30936f, 0.33175f, 0.35421f, 0.37263f, 0.38012f, + 0.37444f, 0.35999f, 0.39234f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.01238f, 0.046242f, 0.085813f, 0.14312f, 0.21247f, 0.26716f, + 0.29661f, 0.31385f, 0.34119f, 0.3727f, 0.40155f, 0.42428f, + 0.43128f, 0.43048f, 0.47409f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.0048489f, 0.032179f, 0.083684f, 0.14641f, 0.23272f, 0.27225f, + 0.28139f, 0.30767f, 0.33894f, 0.3788f, 0.4187f, 0.45626f, + 0.48466f, 0.49857f, 0.55339f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0029287f, + 0.015357f, 0.040874f, 0.082238f, 0.14702f, 0.23663f, 0.25012f, + 0.27481f, 0.30176f, 0.33418f, 0.37423f, 0.42403f, 0.4769f, + 0.52692f, 0.56555f, 0.63203f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0019397f, 0.021156f, + 0.051639f, 0.089163f, 0.13307f, 0.17997f, 0.22386f, 0.24772f, + 0.27249f, 0.30054f, 0.33231f, 0.37158f, 0.42577f, 0.49302f, + 0.56398f, 0.63586f, 0.70711f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.01438f, 0.049473f, 0.099723f, + 0.15348f, 0.20226f, 0.24098f, 0.24557f, 0.25321f, 0.27695f, 0.30342f, + 0.33559f, 0.37551f, 0.42626f, 0.49895f, 0.59175f, 0.69745f, 0.77384f}, + {0.000000f, 0.000000f, 0.000000f, 0.0023122f, 0.031384f, 0.081894f, + 0.14485f, 0.19907f, 0.24237f, 0.268f, 0.27012f, 0.27589f, + 0.28486f, 0.31064f, 0.34157f, 0.38293f, 0.43576f, 0.51188f, + 0.62473f, 0.75361f, 0.83195f}, + {0.000000f, 0.000000f, 0.000000f, 0.0075151f, 0.048878f, 0.11169f, + 0.17871f, 0.229f, 0.263f, 0.28867f, 0.29793f, 0.30177f, + 0.3099f, 0.32047f, 0.3505f, 0.39422f, 0.45043f, 0.53218f, + 0.66167f, 0.80779f, 0.87965f}, + {0.000000f, 0.000000f, 0.000000f, 0.014677f, 0.066587f, 0.13466f, 0.19976f, + 0.24081f, 0.2763f, 0.30555f, 0.32392f, 0.33349f, 0.34026f, 0.3499f, + 0.36625f, 0.41012f, 0.46596f, 0.55393f, 0.69668f, 0.85613f, 0.91914f}, + {0.000000f, 0.000000f, 0.000000f, 0.017689f, 0.075976f, 0.15229f, 0.19715f, + 0.24172f, 0.28192f, 0.31654f, 0.343f, 0.3639f, 0.37933f, 0.39305f, + 0.40957f, 0.42729f, 0.49385f, 0.58524f, 0.72145f, 0.8756f, 0.94832f}, + {0.000000f, 0.000000f, 0.000000f, 0.019339f, 0.081415f, 0.12939f, 0.18521f, + 0.2329f, 0.27908f, 0.31978f, 0.35395f, 0.38326f, 0.40917f, 0.43346f, + 0.45546f, 0.48528f, 0.5172f, 0.60794f, 0.76272f, 0.87113f, 0.96987f}, + {0.000000f, 0.000000f, 0.000000f, 0.016574f, 0.049892f, 0.094728f, 0.15233f, + 0.20846f, 0.26255f, 0.31088f, 0.35261f, 0.39169f, 0.42708f, 0.46137f, + 0.49449f, 0.53421f, 0.57711f, 0.6299f, 0.74014f, 0.85731f, 0.9845f}, + {0.000000f, 0.000000f, 0.000000f, 0.0025743f, 0.010122f, 0.048381f, + 0.095227f, 0.15539f, 0.22053f, 0.28038f, 0.33191f, 0.38291f, + 0.42927f, 0.47532f, 0.52386f, 0.57553f, 0.64546f, 0.68239f, + 0.71318f, 0.83679f, 0.99377f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0022432f, + 0.019725f, 0.067908f, 0.13152f, 0.19821f, 0.26356f, 0.3345f, + 0.39855f, 0.46338f, 0.53833f, 0.61802f, 0.68515f, 0.7397f, + 0.78158f, 0.8123f, 0.99846f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.14292f, + 0.27953f, 0.40639f, 0.52748f, 0.63323f, 0.72837f, 0.81116f, + 0.88423f, 0.94629f, 1.000000f}}; + +float map_5point1_ls[21][21] = { + {1.000000f, 0.99863f, 0.99396f, 0.98481f, 0.9703f, 0.94888f, + 0.91914f, 0.88048f, 0.83195f, 0.77384f, 0.70834f, 0.63338f, + 0.55484f, 0.47562f, 0.39394f, 0.3173f, 0.24362f, 0.17537f, + 0.11147f, 0.054079f, -7.8496e-017f}, + {0.99854f, 0.94804f, 0.94647f, 0.94043f, 0.92966f, 0.91177f, 0.87898f, + 0.82659f, 0.76643f, 0.70248f, 0.63602f, 0.56664f, 0.49969f, 0.43164f, + 0.36121f, 0.29703f, 0.24559f, 0.20208f, 0.16581f, 0.13592f, 0.000000f}, + {0.99373f, 0.94619f, 0.89929f, 0.8973f, 0.89f, 0.84522f, 0.80369f, + 0.75196f, 0.69549f, 0.64182f, 0.59149f, 0.53909f, 0.48676f, 0.43211f, + 0.3753f, 0.31848f, 0.25563f, 0.21817f, 0.18628f, 0.11031f, 0.000000f}, + {0.98443f, 0.94057f, 0.89693f, 0.84178f, 0.80673f, 0.76938f, 0.72295f, + 0.68173f, 0.63988f, 0.59999f, 0.56152f, 0.51902f, 0.47535f, 0.42864f, + 0.38061f, 0.33006f, 0.27965f, 0.22857f, 0.15778f, 0.083896f, 0.000000f}, + {0.96987f, 0.92924f, 0.89008f, 0.8064f, 0.72353f, 0.68753f, 0.64727f, + 0.61961f, 0.59007f, 0.5611f, 0.53236f, 0.49762f, 0.45999f, 0.41905f, + 0.37687f, 0.33185f, 0.28785f, 0.21842f, 0.12802f, 0.058746f, 0.000000f}, + {0.94832f, 0.91132f, 0.84488f, 0.76916f, 0.6876f, 0.60199f, 0.57793f, + 0.55557f, 0.53786f, 0.52026f, 0.49866f, 0.47305f, 0.4406f, 0.40425f, + 0.36538f, 0.32707f, 0.2697f, 0.20197f, 0.12403f, 0.03616f, 0.000000f}, + {0.91914f, 0.87839f, 0.80323f, 0.72262f, 0.64697f, 0.57779f, 0.51599f, + 0.49381f, 0.48147f, 0.4732f, 0.46311f, 0.44521f, 0.41747f, 0.38486f, + 0.34957f, 0.30247f, 0.24789f, 0.18361f, 0.10709f, 0.022585f, 0.000000f}, + {0.87965f, 0.82586f, 0.75136f, 0.68116f, 0.61943f, 0.55563f, 0.49394f, + 0.45149f, 0.43778f, 0.42773f, 0.42381f, 0.41464f, 0.39077f, 0.36007f, + 0.32202f, 0.27305f, 0.21805f, 0.15706f, 0.090176f, 0.018356f, 0.000000f}, + {0.83195f, 0.76558f, 0.69482f, 0.63955f, 0.58992f, 0.53794f, 0.48142f, + 0.43767f, 0.40132f, 0.39038f, 0.38425f, 0.38246f, 0.35885f, 0.3262f, + 0.2847f, 0.23683f, 0.18569f, 0.13031f, 0.070512f, 0.012179f, 0.000000f}, + {0.77494f, 0.70182f, 0.64105f, 0.59937f, 0.5609f, 0.52028f, 0.47314f, + 0.42777f, 0.39034f, 0.35673f, 0.34932f, 0.34449f, 0.31565f, 0.27779f, + 0.23728f, 0.19424f, 0.14921f, 0.10103f, 0.049741f, 0.0045097f, 0.000000f}, + {0.70711f, 0.63577f, 0.59134f, 0.56143f, 0.53234f, 0.49869f, + 0.46315f, 0.42387f, 0.38431f, 0.34937f, 0.3185f, 0.28163f, + 0.2449f, 0.21252f, 0.18253f, 0.14834f, 0.1086f, 0.068513f, + 0.027472f, -8.5322e-019f, 0.000000f}, + {0.63338f, 0.56555f, 0.53856f, 0.51865f, 0.49722f, 0.47263f, 0.44507f, + 0.41451f, 0.38241f, 0.34452f, 0.2816f, 0.24145f, 0.18988f, 0.15379f, + 0.12638f, 0.10174f, 0.073541f, 0.042039f, 0.011806f, 0.000000f, 0.000000f}, + {0.55339f, 0.49871f, 0.48607f, 0.47475f, 0.45953f, 0.44013f, + 0.41724f, 0.39065f, 0.35885f, 0.31539f, 0.24485f, 0.1898f, + 0.16119f, 0.11535f, 0.083376f, 0.061737f, 0.041097f, 0.018696f, + 0.0013628f, 0.000000f, 0.000000f}, + {0.47409f, 0.43048f, 0.43138f, 0.42817f, 0.41859f, 0.40381f, + 0.38442f, 0.36003f, 0.32583f, 0.27748f, 0.21245f, 0.15351f, + 0.11527f, 0.092466f, 0.055926f, 0.03134f, 0.017152f, 0.0039822f, + 0.000000f, 0.000000f, 0.000000f}, + {0.39234f, 0.35999f, 0.37455f, 0.38033f, 0.37646f, 0.36503f, + 0.34948f, 0.32174f, 0.28429f, 0.23686f, 0.18246f, 0.12608f, + 0.083197f, 0.055812f, 0.03557f, 0.011379f, 0.0039191f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.31565f, 0.29607f, 0.31773f, 0.32943f, 0.33124f, 0.32696f, + 0.30198f, 0.27263f, 0.2365f, 0.19392f, 0.14828f, 0.10138f, + 0.061436f, 0.031114f, 0.011267f, 0.002725f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.24192f, 0.24451f, 0.25473f, 0.27908f, 0.28772f, 0.26927f, + 0.24734f, 0.21753f, 0.18526f, 0.14882f, 0.10856f, 0.073199f, + 0.040831f, 0.01704f, 0.0038302f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.17365f, 0.20108f, 0.21738f, 0.22846f, 0.21775f, 0.20135f, + 0.18335f, 0.15652f, 0.12991f, 0.1006f, 0.068474f, 0.041753f, + 0.018492f, 0.0038919f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.10973f, 0.16489f, 0.18616f, 0.15705f, 0.12737f, 0.12342f, + 0.10655f, 0.089694f, 0.070085f, 0.049384f, 0.027446f, 0.011636f, + 0.0013628f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.052332f, 0.13583f, 0.10958f, 0.083257f, 0.058204f, 0.035717f, + 0.022438f, 0.018227f, 0.011962f, 0.0043772f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}}; + +float map_5point1_rs[21][21] = { + {-7.8496e-017f, 0.052336f, 0.10973f, 0.17365f, 0.24192f, 0.31565f, + 0.39394f, 0.47409f, 0.55484f, 0.63338f, 0.70587f, 0.77384f, + 0.83195f, 0.87965f, 0.91914f, 0.94832f, 0.96987f, 0.9845f, + 0.99377f, 0.99854f, 1.000000f}, + {0.000000f, 0.13583f, 0.16489f, 0.20208f, 0.24451f, 0.29589f, 0.35999f, + 0.43048f, 0.49857f, 0.56633f, 0.63558f, 0.70182f, 0.76558f, 0.82586f, + 0.87839f, 0.91132f, 0.92934f, 0.94057f, 0.94637f, 0.94804f, 0.99863f}, + {0.000000f, 0.11031f, 0.18615f, 0.21738f, 0.25552f, 0.31761f, 0.37444f, + 0.43128f, 0.48597f, 0.53856f, 0.59121f, 0.64167f, 0.69482f, 0.75136f, + 0.80323f, 0.84488f, 0.89008f, 0.89725f, 0.89927f, 0.94647f, 0.99396f}, + {0.000000f, 0.083257f, 0.15778f, 0.22845f, 0.27908f, 0.32934f, 0.38061f, + 0.42817f, 0.47475f, 0.51865f, 0.56131f, 0.59998f, 0.63948f, 0.6818f, + 0.72306f, 0.76916f, 0.80688f, 0.84174f, 0.8973f, 0.94077f, 0.98473f}, + {0.000000f, 0.058746f, 0.12737f, 0.2183f, 0.28772f, 0.33167f, 0.37646f, + 0.41852f, 0.45953f, 0.49722f, 0.53221f, 0.56083f, 0.58986f, 0.61943f, + 0.64753f, 0.6876f, 0.72348f, 0.80673f, 0.89031f, 0.92966f, 0.9703f}, + {0.000000f, 0.035717f, 0.12342f, 0.20135f, 0.26927f, 0.32696f, 0.36503f, + 0.40381f, 0.44057f, 0.47309f, 0.49858f, 0.52028f, 0.53794f, 0.55557f, + 0.57829f, 0.60191f, 0.688f, 0.76938f, 0.84522f, 0.91177f, 0.94888f}, + {0.000000f, 0.022264f, 0.10655f, 0.18361f, 0.24774f, 0.30233f, 0.34948f, + 0.3848f, 0.41719f, 0.44502f, 0.46308f, 0.47314f, 0.48142f, 0.49394f, + 0.51592f, 0.57793f, 0.64727f, 0.72306f, 0.80369f, 0.87898f, 0.91982f}, + {0.000000f, 0.018075f, 0.089694f, 0.15698f, 0.21753f, 0.27257f, 0.32174f, + 0.36002f, 0.39065f, 0.41451f, 0.4238f, 0.42773f, 0.43804f, 0.45143f, + 0.49424f, 0.55557f, 0.61961f, 0.68173f, 0.75196f, 0.82659f, 0.88048f}, + {0.000000f, 0.011962f, 0.070085f, 0.12983f, 0.1852f, 0.2365f, 0.28429f, + 0.32614f, 0.35884f, 0.38237f, 0.38425f, 0.39034f, 0.40127f, 0.43778f, + 0.48142f, 0.53827f, 0.59007f, 0.63988f, 0.69549f, 0.76643f, 0.83292f}, + {0.000000f, 0.0043772f, 0.049741f, 0.10103f, 0.14876f, 0.19392f, 0.23686f, + 0.27743f, 0.31539f, 0.34452f, 0.34932f, 0.35669f, 0.39034f, 0.42773f, + 0.47315f, 0.52061f, 0.5611f, 0.59999f, 0.64182f, 0.7028f, 0.77494f}, + {0.000000f, -8.5322e-019f, 0.027447f, 0.068465f, 0.10853f, 0.14825f, + 0.18244f, 0.21244f, 0.24485f, 0.28161f, 0.31849f, 0.34932f, + 0.38425f, 0.42381f, 0.46314f, 0.49869f, 0.53239f, 0.56152f, + 0.59147f, 0.63596f, 0.70711f}, + {0.000000f, 0.000000f, 0.011636f, 0.041753f, 0.073199f, 0.1017f, 0.12603f, + 0.15351f, 0.18976f, 0.24145f, 0.28164f, 0.34451f, 0.38246f, 0.41464f, + 0.44521f, 0.47305f, 0.49762f, 0.51919f, 0.5393f, 0.56664f, 0.63338f}, + {0.000000f, 0.000000f, 0.0013084f, 0.018492f, 0.040831f, 0.061737f, + 0.083146f, 0.11527f, 0.16121f, 0.18988f, 0.2449f, 0.31565f, + 0.35887f, 0.39092f, 0.41747f, 0.4406f, 0.45999f, 0.47535f, + 0.48676f, 0.49969f, 0.55484f}, + {0.000000f, 0.000000f, 0.000000f, 0.0038919f, 0.016973f, 0.031114f, + 0.056058f, 0.092505f, 0.11557f, 0.15374f, 0.21251f, 0.27779f, + 0.3262f, 0.36008f, 0.38486f, 0.40425f, 0.41905f, 0.42882f, + 0.43211f, 0.43164f, 0.47562f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0038302f, 0.011267f, + 0.0356f, 0.055926f, 0.083376f, 0.12638f, 0.18252f, 0.23728f, + 0.2847f, 0.32214f, 0.34955f, 0.36552f, 0.37704f, 0.38081f, + 0.3753f, 0.36121f, 0.39394f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0027341f, + 0.011405f, 0.03134f, 0.061737f, 0.10174f, 0.14834f, 0.19436f, + 0.23696f, 0.27305f, 0.30247f, 0.32704f, 0.33185f, 0.33006f, + 0.31848f, 0.29703f, 0.3173f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.0039191f, 0.017152f, 0.041097f, 0.073541f, 0.10862f, 0.14921f, + 0.18569f, 0.21805f, 0.24789f, 0.26986f, 0.28782f, 0.27982f, + 0.25563f, 0.24559f, 0.24362f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.0039822f, 0.018696f, 0.042039f, 0.068554f, 0.10103f, + 0.13031f, 0.15706f, 0.1837f, 0.20197f, 0.21842f, 0.22858f, + 0.21822f, 0.20208f, 0.17537f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.0013628f, 0.011806f, 0.027511f, 0.049741f, + 0.070512f, 0.090176f, 0.10709f, 0.12403f, 0.12802f, 0.15778f, + 0.1863f, 0.16581f, 0.11147f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, -8.5322e-019f, 0.0045097f, + 0.012179f, 0.018356f, 0.022585f, 0.03616f, 0.058746f, 0.083896f, + 0.11031f, 0.136f, 0.054075f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, -7.8496e-017f}}; + +float map_7point1_ang[] = {-27, 0, 27, -95, 95, -142, 142}; +float map_7point1_xsf[] = {-1, 0, 1, -1, 1, -1, 1}; +float map_7point1_ysf[] = {1, 1, 1, 0, 0, -1, -1}; +channel_id map_7point1_id[] = { + ci_front_left, ci_front_center, ci_front_right, ci_side_center_left, + ci_side_center_right, ci_back_left, ci_back_right, ci_lfe}; + +float map_7point1_lf[21][21] = { + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 9.4126e-019f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.0025743f, 0.016552f, 0.019339f, 0.017689f, + 0.014677f, 0.0075151f, 0.0023122f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.010122f, 0.049892f, 0.081385f, 0.075976f, + 0.066587f, 0.048878f, 0.031384f, 0.01438f, 0.0019269f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.0022432f, 0.048381f, 0.094728f, 0.12939f, 0.15091f, + 0.13421f, 0.11169f, 0.081894f, 0.049473f, 0.021188f, 0.0029287f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.019725f, 0.095227f, 0.15233f, 0.18129f, 0.18619f, + 0.18195f, 0.1662f, 0.14038f, 0.099716f, 0.051668f, 0.015357f, + 0.0004627f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.067908f, 0.15539f, 0.20448f, 0.21574f, 0.21038f, + 0.19727f, 0.18275f, 0.16961f, 0.14309f, 0.089211f, 0.030602f, + 0.0029125f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.13152f, 0.21916f, 0.24385f, 0.23799f, 0.22019f, + 0.19777f, 0.1798f, 0.16484f, 0.15891f, 0.12092f, 0.0391f, + 0.0061765f, 0.0028379f, 0.00043186f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.19821f, 0.26858f, 0.26884f, 0.24624f, 0.21773f, + 0.19453f, 0.1758f, 0.16036f, 0.14653f, 0.13495f, 0.052607f, + 0.038854f, 0.030373f, 0.015188f, 0.0028496f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {8.6596e-017f, 0.26351f, 0.30441f, 0.28405f, 0.24723f, 0.21577f, + 0.19296f, 0.17452f, 0.15823f, 0.14384f, 0.13114f, 0.13492f, + 0.12086f, 0.089089f, 0.051572f, 0.021112f, 0.0019269f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.14292f, 0.32999f, 0.33317f, 0.29065f, 0.24843f, 0.21902f, + 0.19594f, 0.17746f, 0.1625f, 0.14962f, 0.14386f, 0.14651f, + 0.15886f, 0.14285f, 0.099312f, 0.049149f, 0.01419f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.27953f, 0.38637f, 0.35876f, 0.29909f, 0.25487f, 0.22426f, + 0.20041f, 0.18277f, 0.16832f, 0.16249f, 0.15824f, 0.16036f, + 0.16482f, 0.16948f, 0.14005f, 0.081488f, 0.031102f, 0.0022352f, + 0.000000f, 0.000000f, 0.000000f}, + {0.40639f, 0.44503f, 0.38515f, 0.31183f, 0.26428f, 0.23169f, + 0.20647f, 0.18936f, 0.18276f, 0.17745f, 0.17453f, 0.1758f, + 0.17979f, 0.18273f, 0.16592f, 0.11122f, 0.048526f, 0.0073556f, + 0.000000f, 0.000000f, 0.000000f}, + {0.52748f, 0.51574f, 0.41678f, 0.32546f, 0.27415f, 0.24175f, 0.21641f, + 0.20646f, 0.2004f, 0.19593f, 0.19298f, 0.19453f, 0.19777f, 0.19716f, + 0.18189f, 0.13374f, 0.066173f, 0.014462f, 0.000000f, 0.000000f, 0.000000f}, + {0.63323f, 0.58186f, 0.4515f, 0.34992f, 0.2914f, 0.25248f, 0.24174f, + 0.23169f, 0.22425f, 0.219f, 0.21579f, 0.21773f, 0.22013f, 0.21018f, + 0.18585f, 0.15082f, 0.075526f, 0.017441f, 0.000000f, 0.000000f, 0.000000f}, + {0.72837f, 0.62641f, 0.51744f, 0.37803f, 0.31074f, 0.29139f, 0.27414f, + 0.26427f, 0.25485f, 0.24842f, 0.24726f, 0.24619f, 0.23779f, 0.2154f, + 0.18082f, 0.12881f, 0.081296f, 0.019071f, 0.000000f, 0.000000f, 0.000000f}, + {0.81116f, 0.6558f, 0.5246f, 0.41789f, 0.37802f, 0.34991f, 0.32545f, + 0.31182f, 0.29908f, 0.29063f, 0.28406f, 0.26859f, 0.24346f, 0.20392f, + 0.15167f, 0.09417f, 0.04946f, 0.016531f, 0.000000f, 0.000000f, 0.000000f}, + {0.88423f, 0.67127f, 0.52691f, 0.5245f, 0.51721f, 0.45136f, + 0.41661f, 0.38495f, 0.35851f, 0.33283f, 0.30436f, 0.26801f, + 0.21844f, 0.15464f, 0.094607f, 0.047925f, 0.0098814f, 0.0024671f, + 0.000000f, 0.000000f, 0.000000f}, + {0.94622f, 0.67633f, 0.67099f, 0.65523f, 0.62554f, 0.58081f, + 0.51465f, 0.44406f, 0.38544f, 0.32902f, 0.26339f, 0.19725f, + 0.13069f, 0.067274f, 0.019339f, 0.0021311f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {1.000000f, 0.94446f, 0.8823f, 0.80914f, 0.72626f, 0.63102f, + 0.52519f, 0.40402f, 0.27711f, 0.14046f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}}; + +float map_7point1_cf[21][21] = { + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0019269f, + 0.00062925f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.00059225f, 0.001914f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0055425f, 0.0155f, + 0.025167f, 0.017695f, 0.0063155f, 1.0116e-005f, 0.000000f, 0.000000f, + 0.0062031f, 0.017508f, 0.025125f, 0.015305f, 0.0054168f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.0056317f, 0.024256f, 0.044322f, + 0.061583f, 0.065405f, 0.041656f, 0.014688f, 4.0817e-019f, 0.014527f, + 0.041389f, 0.065342f, 0.061236f, 0.044002f, 0.024003f, 0.005504f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.0019274f, 0.02644f, 0.05812f, 0.08731f, + 0.11105f, 0.11767f, 0.10963f, 0.061306f, 0.017226f, 0.061006f, + 0.10958f, 0.11735f, 0.11066f, 0.086884f, 0.057744f, 0.026151f, + 0.0018503f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.016697f, 0.059451f, 0.104f, 0.13974f, + 0.15702f, 0.15962f, 0.15223f, 0.13355f, 0.063692f, 0.13353f, + 0.15211f, 0.15945f, 0.15675f, 0.13934f, 0.10352f, 0.059047f, + 0.016456f, 0.000000f, 0.000000f}, + {0.000000f, 1.2068e-018f, 0.038851f, 0.096919f, 0.15087f, 0.17987f, + 0.18511f, 0.17445f, 0.15817f, 0.14379f, 0.13384f, 0.14378f, + 0.15816f, 0.17444f, 0.18509f, 0.17981f, 0.15076f, 0.096821f, + 0.038797f, 0.000000f, 0.000000f}, + {0.000000f, 0.0063777f, 0.070344f, 0.14288f, 0.19068f, 0.2049f, + 0.19453f, 0.1758f, 0.16036f, 0.14645f, 0.14681f, 0.14646f, + 0.16036f, 0.1758f, 0.19453f, 0.20473f, 0.19031f, 0.14227f, + 0.06984f, 0.0061903f, 0.000000f}, + {0.000000f, 0.017224f, 0.099719f, 0.18101f, 0.21822f, 0.2193f, + 0.19777f, 0.17979f, 0.16475f, 0.16187f, 0.16149f, 0.16187f, + 0.16477f, 0.1798f, 0.19777f, 0.21922f, 0.21792f, 0.18045f, + 0.099116f, 0.016918f, 0.000000f}, + {0.000000f, 0.02596f, 0.12753f, 0.21148f, 0.23925f, 0.22819f, 0.20284f, + 0.18535f, 0.18085f, 0.17814f, 0.17812f, 0.17814f, 0.18084f, 0.18536f, + 0.20284f, 0.22818f, 0.23901f, 0.21095f, 0.12685f, 0.025562f, 0.000000f}, + {0.000000f, 0.03194f, 0.15144f, 0.23904f, 0.2564f, 0.23733f, 0.21182f, + 0.20371f, 0.19964f, 0.19751f, 0.19694f, 0.1975f, 0.19963f, 0.20369f, + 0.21184f, 0.23733f, 0.25621f, 0.23853f, 0.15068f, 0.031485f, 0.000000f}, + {0.000000f, 0.051138f, 0.17541f, 0.26062f, 0.27419f, 0.24713f, 0.23812f, + 0.22985f, 0.2244f, 0.22133f, 0.22022f, 0.22132f, 0.22439f, 0.22984f, + 0.2381f, 0.24715f, 0.274f, 0.26009f, 0.17455f, 0.050511f, 0.000000f}, + {0.000000f, 0.08308f, 0.18105f, 0.28155f, 0.29188f, 0.28632f, 0.27128f, + 0.26327f, 0.25585f, 0.25151f, 0.25234f, 0.2515f, 0.25584f, 0.26325f, + 0.27127f, 0.28627f, 0.29189f, 0.28098f, 0.18013f, 0.082312f, 0.000000f}, + {0.000000f, 0.11865f, 0.22314f, 0.29977f, 0.32517f, 0.33282f, 0.32312f, + 0.31164f, 0.30095f, 0.2946f, 0.29542f, 0.29459f, 0.30094f, 0.31163f, + 0.32308f, 0.33259f, 0.32473f, 0.29967f, 0.22211f, 0.11774f, 0.000000f}, + {0.000000f, 0.15601f, 0.26339f, 0.30497f, 0.3472f, 0.38198f, 0.39609f, + 0.39135f, 0.3765f, 0.36616f, 0.36703f, 0.36615f, 0.37649f, 0.39123f, + 0.39574f, 0.3814f, 0.34627f, 0.30393f, 0.26322f, 0.15497f, 0.000000f}, + {0.000000f, 0.19222f, 0.23448f, 0.28578f, 0.34732f, 0.4169f, 0.48293f, + 0.51439f, 0.52067f, 0.52104f, 0.52661f, 0.52086f, 0.52026f, 0.51365f, + 0.48176f, 0.41543f, 0.34579f, 0.28436f, 0.23319f, 0.19202f, 0.000000f}, + {1.1102e-016f, 0.076479f, 0.15764f, 0.24801f, 0.34452f, 0.44874f, + 0.55712f, 0.67263f, 0.78467f, 0.89574f, 1.000000f, 0.89382f, + 0.78261f, 0.67046f, 0.55485f, 0.4464f, 0.34213f, 0.24558f, + 0.15519f, 0.074014f, 0.000000f}}; + +float map_7point1_rf[21][21] = { + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.0022352f, 0.0073556f, 0.014462f, 0.017441f, 0.019071f, 0.016531f, + 0.0024671f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0019269f, 0.01419f, + 0.031102f, 0.048526f, 0.066173f, 0.075526f, 0.081297f, 0.04946f, + 0.0098814f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.0028496f, 0.021112f, 0.049149f, + 0.081488f, 0.11122f, 0.13374f, 0.15081f, 0.12881f, 0.09417f, + 0.047925f, 0.0021311f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.00043186f, 0.015188f, 0.051545f, 0.099312f, + 0.14005f, 0.16592f, 0.1819f, 0.18585f, 0.18082f, 0.15167f, + 0.094607f, 0.019339f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.0028379f, 0.030373f, 0.089057f, 0.14285f, + 0.16948f, 0.18273f, 0.19716f, 0.21018f, 0.2154f, 0.20392f, + 0.15464f, 0.067274f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.0004627f, 0.0029125f, 0.0061679f, 0.038854f, 0.12083f, 0.15886f, + 0.16483f, 0.17979f, 0.19777f, 0.22013f, 0.23779f, 0.24346f, + 0.21844f, 0.13069f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0029287f, + 0.015357f, 0.030602f, 0.0391f, 0.052555f, 0.13491f, 0.14652f, + 0.16036f, 0.1758f, 0.19453f, 0.21773f, 0.24619f, 0.26859f, + 0.26801f, 0.19725f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0019397f, 0.021156f, + 0.051639f, 0.089163f, 0.1209f, 0.13493f, 0.13114f, 0.14385f, + 0.15824f, 0.17453f, 0.19297f, 0.21578f, 0.24725f, 0.28402f, + 0.30431f, 0.2633f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.01438f, 0.049473f, 0.099716f, + 0.14309f, 0.15891f, 0.1465f, 0.14385f, 0.14961f, 0.16249f, 0.17745f, + 0.19593f, 0.219f, 0.24842f, 0.29063f, 0.33283f, 0.32902f, 0.14046f}, + {0.000000f, 0.000000f, 0.000000f, 0.0023122f, 0.031384f, 0.081894f, + 0.14038f, 0.16961f, 0.16482f, 0.16036f, 0.15824f, 0.1625f, + 0.16831f, 0.18276f, 0.2004f, 0.22425f, 0.25485f, 0.29908f, + 0.35851f, 0.38544f, 0.27711f}, + {0.000000f, 0.000000f, 0.000000f, 0.0075151f, 0.048878f, 0.11169f, + 0.1662f, 0.18272f, 0.1798f, 0.1758f, 0.17453f, 0.17746f, + 0.18277f, 0.18935f, 0.20646f, 0.23169f, 0.26427f, 0.31182f, + 0.38495f, 0.44406f, 0.40402f}, + {0.000000f, 0.000000f, 0.000000f, 0.014677f, 0.066587f, 0.13421f, 0.18194f, + 0.19727f, 0.19777f, 0.19453f, 0.19297f, 0.19594f, 0.20041f, 0.20647f, + 0.2164f, 0.24174f, 0.27414f, 0.32545f, 0.41661f, 0.51465f, 0.52519f}, + {0.000000f, 0.000000f, 0.000000f, 0.017689f, 0.075976f, 0.15092f, 0.18619f, + 0.21038f, 0.22019f, 0.21773f, 0.21578f, 0.21902f, 0.22426f, 0.23169f, + 0.24175f, 0.25247f, 0.29139f, 0.34991f, 0.45136f, 0.58081f, 0.63102f}, + {0.000000f, 0.000000f, 0.000000f, 0.019339f, 0.081415f, 0.12939f, 0.18129f, + 0.21574f, 0.23799f, 0.24624f, 0.24725f, 0.24843f, 0.25487f, 0.26428f, + 0.27415f, 0.2914f, 0.31073f, 0.37802f, 0.51721f, 0.62554f, 0.72626f}, + {0.000000f, 0.000000f, 0.000000f, 0.016574f, 0.049892f, 0.094728f, + 0.15233f, 0.20448f, 0.24385f, 0.26884f, 0.28405f, 0.29065f, + 0.29909f, 0.31183f, 0.32546f, 0.34992f, 0.37803f, 0.41787f, + 0.5245f, 0.65523f, 0.80914f}, + {0.000000f, 0.000000f, 0.000000f, 0.0025743f, 0.010122f, 0.048381f, + 0.095227f, 0.15539f, 0.21916f, 0.26858f, 0.3044f, 0.33317f, + 0.35876f, 0.38515f, 0.41678f, 0.4515f, 0.51744f, 0.5246f, + 0.52688f, 0.67099f, 0.8823f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0022432f, + 0.019725f, 0.067908f, 0.13152f, 0.19821f, 0.26356f, 0.32999f, + 0.38637f, 0.44503f, 0.51574f, 0.58186f, 0.62641f, 0.6558f, + 0.67127f, 0.6763f, 0.94439f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.14292f, + 0.27953f, 0.40639f, 0.52748f, 0.63323f, 0.72837f, 0.81116f, + 0.88423f, 0.94629f, 1.000000f}}; + +float map_7point1_lsm[21][21] = { + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.076479f, 0.1924f, 0.15601f, 0.11842f, 0.08308f, 0.051138f, + 0.03194f, 0.02596f, 0.017224f, 0.006217f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.15701f, 0.23422f, 0.26354f, 0.22314f, 0.18089f, 0.17541f, + 0.15144f, 0.12753f, 0.099719f, 0.070344f, 0.038959f, 0.016585f, + 0.0019274f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.24799f, 0.28578f, 0.30478f, 0.2999f, 0.28155f, 0.26062f, + 0.23875f, 0.21148f, 0.18101f, 0.14288f, 0.097017f, 0.059361f, + 0.02644f, 0.0055357f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.34452f, 0.34709f, 0.3472f, 0.32503f, 0.29199f, 0.2741f, + 0.2564f, 0.23925f, 0.21822f, 0.19068f, 0.15101f, 0.104f, + 0.05812f, 0.024256f, 0.0054585f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.44874f, 0.4169f, 0.38198f, 0.33282f, 0.28632f, 0.24721f, + 0.23733f, 0.22819f, 0.21923f, 0.20483f, 0.17996f, 0.13974f, + 0.08731f, 0.044322f, 0.015426f, 0.0019269f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.55712f, 0.48293f, 0.39609f, 0.32283f, 0.2712f, 0.23804f, + 0.21189f, 0.20278f, 0.19777f, 0.19453f, 0.18519f, 0.15702f, + 0.11105f, 0.061583f, 0.025231f, 0.00062925f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.67263f, 0.51439f, 0.39135f, 0.31154f, 0.26327f, 0.22985f, + 0.20371f, 0.18541f, 0.17979f, 0.1758f, 0.17449f, 0.15962f, + 0.11761f, 0.06551f, 0.017632f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.78467f, 0.52067f, 0.3765f, 0.30095f, 0.25585f, 0.2244f, + 0.19964f, 0.1808f, 0.16481f, 0.16036f, 0.15821f, 0.15223f, + 0.10975f, 0.041656f, 0.0063155f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.89382f, 0.52104f, 0.36605f, 0.29451f, 0.25151f, 0.22133f, + 0.19751f, 0.17814f, 0.16187f, 0.14649f, 0.14382f, 0.13363f, + 0.061306f, 0.014688f, 1.0116e-005f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {1.000000f, 0.52679f, 0.36715f, 0.29551f, 0.25242f, 0.22029f, + 0.19701f, 0.17818f, 0.16155f, 0.14686f, 0.1311f, 0.063705f, + 0.017218f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.89382f, 0.52086f, 0.36615f, 0.29459f, 0.2515f, 0.22126f, + 0.1975f, 0.17814f, 0.16187f, 0.14649f, 0.14382f, 0.13358f, + 0.061006f, 0.014527f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.78261f, 0.52026f, 0.37649f, 0.30094f, 0.25584f, 0.22432f, + 0.19963f, 0.18084f, 0.1648f, 0.16036f, 0.1582f, 0.15211f, + 0.10961f, 0.041389f, 0.0062031f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.67046f, 0.51365f, 0.39123f, 0.31163f, 0.26325f, 0.22984f, + 0.20363f, 0.1854f, 0.17974f, 0.1758f, 0.17448f, 0.15945f, + 0.11735f, 0.065362f, 0.017508f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.55485f, 0.48176f, 0.39574f, 0.32282f, 0.27127f, 0.2381f, + 0.21189f, 0.20284f, 0.19777f, 0.19453f, 0.18513f, 0.15675f, + 0.11066f, 0.061236f, 0.025146f, 0.00059225f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.4464f, 0.41543f, 0.3814f, 0.33259f, 0.28621f, 0.2472f, + 0.23726f, 0.22818f, 0.21922f, 0.20473f, 0.17984f, 0.13934f, + 0.086884f, 0.044002f, 0.015305f, 0.0019269f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.34213f, 0.34579f, 0.34627f, 0.32473f, 0.29192f, 0.274f, + 0.25621f, 0.23901f, 0.21792f, 0.19031f, 0.1508f, 0.10352f, + 0.057744f, 0.024003f, 0.0054168f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.24558f, 0.28436f, 0.30393f, 0.29971f, 0.28098f, 0.26009f, + 0.23836f, 0.21095f, 0.18045f, 0.14227f, 0.096837f, 0.059047f, + 0.026151f, 0.005504f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.15519f, 0.23319f, 0.26327f, 0.22211f, 0.18013f, 0.17455f, + 0.15068f, 0.12685f, 0.099116f, 0.06984f, 0.038815f, 0.016456f, + 0.0018503f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.074009f, 0.19209f, 0.15497f, 0.11774f, 0.082312f, 0.050511f, + 0.031485f, 0.025562f, 0.016918f, 0.0061903f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}}; + +float map_7point1_rsm[21][21] = { + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0061903f, + 0.016918f, 0.025562f, 0.031485f, 0.050511f, 0.082312f, 0.11774f, + 0.15497f, 0.19222f, 0.074014f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.0018503f, 0.016456f, 0.038851f, 0.06984f, + 0.099116f, 0.12685f, 0.15068f, 0.17455f, 0.18013f, 0.22211f, + 0.26337f, 0.23319f, 0.15519f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.005504f, 0.026151f, 0.059047f, 0.096892f, 0.14227f, + 0.18045f, 0.21095f, 0.23853f, 0.26009f, 0.28098f, 0.29979f, + 0.30393f, 0.28436f, 0.24556f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.0054168f, 0.024003f, 0.057744f, 0.10352f, 0.15084f, 0.19031f, + 0.21792f, 0.23901f, 0.25621f, 0.274f, 0.29198f, 0.32473f, + 0.34627f, 0.34579f, 0.34213f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0019269f, + 0.015305f, 0.044002f, 0.086884f, 0.13934f, 0.17988f, 0.20473f, + 0.21922f, 0.22818f, 0.23733f, 0.24725f, 0.28627f, 0.33259f, + 0.3814f, 0.41543f, 0.4464f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.00059225f, + 0.025157f, 0.061236f, 0.11066f, 0.15675f, 0.18518f, 0.19453f, + 0.19777f, 0.20284f, 0.21193f, 0.2381f, 0.27127f, 0.32308f, + 0.39574f, 0.48176f, 0.55485f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.017508f, 0.065396f, 0.11735f, 0.15945f, 0.17454f, 0.1758f, + 0.1798f, 0.18544f, 0.20369f, 0.22984f, 0.26325f, 0.31163f, + 0.39123f, 0.51365f, 0.67046f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.0062031f, 0.041389f, 0.10962f, 0.15211f, 0.15825f, 0.16036f, + 0.16483f, 0.18084f, 0.19963f, 0.22439f, 0.25584f, 0.30094f, + 0.37649f, 0.52026f, 0.78261f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.014527f, 0.061006f, 0.13359f, 0.14386f, 0.14652f, + 0.16187f, 0.17814f, 0.1975f, 0.22132f, 0.2515f, 0.29459f, + 0.36615f, 0.52086f, 0.89382f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, -4.0817e-019f, 0.017202f, 0.06369f, 0.13113f, 0.14689f, + 0.16158f, 0.17821f, 0.19705f, 0.22033f, 0.25247f, 0.29557f, + 0.36722f, 0.52689f, 1.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 1.0116e-005f, 0.014688f, 0.061306f, 0.13361f, 0.14385f, 0.14651f, + 0.16187f, 0.17814f, 0.19751f, 0.22133f, 0.25151f, 0.2946f, + 0.36616f, 0.52104f, 0.89574f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.0063155f, 0.041656f, 0.10967f, 0.15223f, 0.15823f, 0.16036f, + 0.16482f, 0.18085f, 0.19964f, 0.2244f, 0.25585f, 0.30095f, + 0.3765f, 0.52067f, 0.78467f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.017695f, 0.065451f, 0.11767f, 0.15962f, 0.17452f, 0.1758f, + 0.17979f, 0.18543f, 0.20371f, 0.22985f, 0.26327f, 0.31164f, + 0.39135f, 0.51439f, 0.67263f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.00062925f, + 0.0252f, 0.061583f, 0.11105f, 0.15702f, 0.18518f, 0.19453f, + 0.19777f, 0.20284f, 0.21192f, 0.23812f, 0.27128f, 0.32312f, + 0.39609f, 0.48293f, 0.55712f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0019397f, + 0.0155f, 0.044322f, 0.08731f, 0.13974f, 0.17992f, 0.2049f, + 0.2193f, 0.22819f, 0.23733f, 0.24724f, 0.28632f, 0.33282f, + 0.38198f, 0.4169f, 0.44874f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.0055425f, 0.024256f, 0.05812f, 0.104f, 0.15089f, 0.19068f, + 0.21822f, 0.23925f, 0.2564f, 0.27419f, 0.292f, 0.32517f, + 0.3472f, 0.34732f, 0.34452f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.0056317f, 0.02644f, 0.059451f, 0.09695f, 0.14288f, + 0.18101f, 0.21148f, 0.23904f, 0.26062f, 0.28155f, 0.29985f, + 0.30497f, 0.28578f, 0.24801f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.0019274f, 0.016697f, 0.038906f, 0.070344f, + 0.099719f, 0.12753f, 0.15144f, 0.17541f, 0.18105f, 0.22314f, + 0.26347f, 0.23448f, 0.15764f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, -1.2068e-018f, 0.0063777f, + 0.017224f, 0.02596f, 0.03194f, 0.051138f, 0.08308f, 0.11865f, + 0.15601f, 0.19233f, 0.076473f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, -1.1102e-016f}}; + +float map_7point1_ls[21][21] = { + {1.000000f, 0.99863f, 0.99396f, 0.98481f, 0.9703f, 0.94888f, + 0.91914f, 0.88048f, 0.83195f, 0.77384f, 0.70834f, 0.63338f, + 0.55484f, 0.47562f, 0.39394f, 0.3173f, 0.24362f, 0.17537f, + 0.11147f, 0.054079f, -7.8496e-017f}, + {0.94446f, 0.81199f, 0.83616f, 0.85669f, 0.87092f, 0.87561f, 0.8564f, + 0.80823f, 0.75425f, 0.69808f, 0.63602f, 0.56664f, 0.49969f, 0.43164f, + 0.36121f, 0.29703f, 0.24559f, 0.20208f, 0.16581f, 0.13592f, 0.000000f}, + {0.88271f, 0.78057f, 0.71294f, 0.73952f, 0.76209f, 0.72118f, 0.69661f, + 0.66179f, 0.62498f, 0.59208f, 0.56394f, 0.52736f, 0.48539f, 0.43211f, + 0.3753f, 0.31848f, 0.25563f, 0.21817f, 0.18628f, 0.11031f, 0.000000f}, + {0.80907f, 0.73849f, 0.68142f, 0.62971f, 0.60765f, 0.58509f, 0.55402f, + 0.53219f, 0.51188f, 0.49896f, 0.49292f, 0.47704f, 0.45666f, 0.42472f, + 0.38061f, 0.33006f, 0.27965f, 0.22857f, 0.15778f, 0.083896f, 0.000000f}, + {0.72626f, 0.68381f, 0.64457f, 0.57657f, 0.51706f, 0.49372f, 0.46596f, + 0.45043f, 0.43577f, 0.42627f, 0.42558f, 0.42408f, 0.4189f, 0.4019f, + 0.37301f, 0.33185f, 0.28785f, 0.21842f, 0.12802f, 0.058746f, 0.000000f}, + {0.63102f, 0.61653f, 0.57478f, 0.53382f, 0.48514f, 0.42718f, 0.41011f, + 0.39421f, 0.38285f, 0.37543f, 0.37141f, 0.37424f, 0.37886f, 0.37291f, + 0.35447f, 0.32571f, 0.2697f, 0.20197f, 0.12403f, 0.03616f, 0.000000f}, + {0.52519f, 0.53691f, 0.52315f, 0.49422f, 0.4552f, 0.40947f, 0.36615f, + 0.35043f, 0.34158f, 0.3356f, 0.33216f, 0.33419f, 0.33895f, 0.34131f, + 0.33172f, 0.30203f, 0.24789f, 0.18361f, 0.10709f, 0.022585f, 0.000000f}, + {0.40402f, 0.46214f, 0.47464f, 0.46087f, 0.43328f, 0.39304f, 0.3499f, + 0.32038f, 0.31064f, 0.30342f, 0.30041f, 0.30177f, 0.30761f, 0.31375f, + 0.30955f, 0.27305f, 0.21805f, 0.15706f, 0.090176f, 0.018356f, 0.000000f}, + {0.27711f, 0.39741f, 0.42859f, 0.42667f, 0.40895f, 0.37927f, 0.34025f, + 0.30982f, 0.28478f, 0.27695f, 0.27237f, 0.27482f, 0.28125f, 0.29675f, + 0.28023f, 0.23683f, 0.18569f, 0.13031f, 0.070512f, 0.012179f, 0.000000f}, + {0.14292f, 0.33339f, 0.38221f, 0.39113f, 0.38299f, 0.36377f, 0.33348f, + 0.30176f, 0.27588f, 0.25314f, 0.24761f, 0.25f, 0.2723f, 0.2674f, + 0.23727f, 0.19424f, 0.14921f, 0.10103f, 0.049741f, 0.0045097f, 0.000000f}, + {0.000000f, 0.26327f, 0.33172f, 0.35247f, 0.35385f, 0.34292f, + 0.32385f, 0.29788f, 0.27007f, 0.24552f, 0.22579f, 0.23659f, + 0.23272f, 0.21252f, 0.18253f, 0.14834f, 0.1086f, 0.068513f, + 0.027472f, -8.5322e-019f, 0.000000f}, + {0.000000f, 0.19725f, 0.27965f, 0.31034f, 0.31939f, 0.31618f, + 0.30536f, 0.28855f, 0.26792f, 0.24094f, 0.1799f, 0.14699f, + 0.14674f, 0.14347f, 0.12638f, 0.10174f, 0.073541f, 0.042039f, + 0.011806f, 0.000000f, 0.000000f}, + {0.000000f, 0.13069f, 0.21975f, 0.26195f, 0.27862f, 0.28151f, + 0.27602f, 0.26277f, 0.24232f, 0.202f, 0.13299f, 0.082204f, + 0.083689f, 0.086082f, 0.07899f, 0.061737f, 0.041097f, 0.018696f, + 0.0013628f, 0.000000f, 0.000000f}, + {0.000000f, 0.067274f, 0.15464f, 0.20782f, 0.23238f, 0.24129f, + 0.24043f, 0.22893f, 0.19873f, 0.15312f, 0.089072f, 0.040759f, + 0.032293f, 0.046248f, 0.043546f, 0.03134f, 0.017152f, 0.0039822f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.019339f, 0.094607f, 0.15196f, 0.18465f, 0.19667f, + 0.19966f, 0.1783f, 0.14444f, 0.099312f, 0.051555f, 0.015195f, + 0.0048976f, 0.012512f, 0.017789f, 0.01096f, 0.0039191f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.0021311f, 0.047925f, 0.09417f, 0.12885f, 0.15216f, + 0.13421f, 0.11122f, 0.081488f, 0.049149f, 0.021112f, 0.0028496f, + 0.000000f, 0.000000f, 0.00044495f, 0.0013625f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.0098814f, 0.04946f, 0.081296f, 0.075526f, + 0.066173f, 0.048526f, 0.031102f, 0.01419f, 0.0019269f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.0024671f, 0.016531f, 0.019071f, 0.017441f, + 0.014677f, 0.0073556f, 0.0022352f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}}; + +float map_7point1_rs[21][21] = { + {-7.8496e-017f, 0.052336f, 0.10973f, 0.17365f, 0.24192f, 0.31565f, + 0.39394f, 0.47409f, 0.55484f, 0.63338f, 0.70587f, 0.77384f, + 0.83195f, 0.87965f, 0.91914f, 0.94832f, 0.96987f, 0.9845f, + 0.99377f, 0.99854f, 1.000000f}, + {0.000000f, 0.13583f, 0.16489f, 0.20208f, 0.24451f, 0.29589f, 0.35999f, + 0.43048f, 0.49857f, 0.56633f, 0.63558f, 0.69745f, 0.75361f, 0.80779f, + 0.85613f, 0.8756f, 0.87113f, 0.85731f, 0.83679f, 0.81212f, 0.94629f}, + {0.000000f, 0.11031f, 0.18615f, 0.21738f, 0.25552f, 0.31761f, 0.37444f, + 0.43128f, 0.48466f, 0.52692f, 0.56374f, 0.59228f, 0.62473f, 0.66167f, + 0.69668f, 0.72145f, 0.76272f, 0.7402f, 0.71303f, 0.78158f, 0.88423f}, + {0.000000f, 0.083257f, 0.15778f, 0.22845f, 0.27908f, 0.32934f, 0.38061f, + 0.42428f, 0.45626f, 0.4769f, 0.4928f, 0.49938f, 0.51188f, 0.53264f, + 0.55439f, 0.58524f, 0.6082f, 0.62975f, 0.68239f, 0.7397f, 0.8111f}, + {0.000000f, 0.058746f, 0.12737f, 0.2183f, 0.28772f, 0.33167f, 0.37263f, + 0.40155f, 0.4187f, 0.42403f, 0.42555f, 0.42626f, 0.43576f, 0.45043f, + 0.46637f, 0.49385f, 0.51702f, 0.57711f, 0.64546f, 0.68515f, 0.72837f}, + {0.000000f, 0.035717f, 0.12342f, 0.20135f, 0.26927f, 0.3256f, 0.35421f, + 0.3727f, 0.37913f, 0.37456f, 0.37139f, 0.37551f, 0.38293f, 0.39422f, + 0.41047f, 0.42708f, 0.48557f, 0.53421f, 0.57553f, 0.61802f, 0.63323f}, + {0.000000f, 0.022264f, 0.10655f, 0.18361f, 0.24774f, 0.30191f, 0.3317f, + 0.3415f, 0.33894f, 0.33418f, 0.33214f, 0.33559f, 0.34157f, 0.3505f, + 0.36607f, 0.40957f, 0.45546f, 0.49461f, 0.52386f, 0.53833f, 0.52748f}, + {0.000000f, 0.018075f, 0.089694f, 0.15698f, 0.21753f, 0.27257f, 0.30936f, + 0.31378f, 0.30767f, 0.30176f, 0.30039f, 0.30342f, 0.31091f, 0.32031f, + 0.3502f, 0.39305f, 0.43346f, 0.46137f, 0.47532f, 0.46338f, 0.40639f}, + {0.000000f, 0.011962f, 0.070085f, 0.12983f, 0.1852f, 0.2365f, 0.2799f, + 0.29688f, 0.28132f, 0.27481f, 0.27235f, 0.27695f, 0.28472f, 0.3099f, + 0.34026f, 0.3796f, 0.40917f, 0.42708f, 0.42927f, 0.39855f, 0.27953f}, + {0.000000f, 0.0043772f, 0.049741f, 0.10103f, 0.14876f, 0.19392f, 0.23686f, + 0.26716f, 0.27225f, 0.25006f, 0.24759f, 0.25308f, 0.27589f, 0.30177f, + 0.33349f, 0.36411f, 0.38326f, 0.39169f, 0.38291f, 0.3345f, 0.14292f}, + {0.000000f, -8.5322e-019f, 0.027447f, 0.068465f, 0.10853f, 0.14825f, + 0.18244f, 0.21244f, 0.23269f, 0.23658f, 0.22577f, 0.24545f, + 0.27f, 0.29779f, 0.3238f, 0.34289f, 0.35387f, 0.35252f, + 0.3318f, 0.26339f, -8.6596e-017f}, + {0.000000f, 0.000000f, 0.011636f, 0.041753f, 0.073199f, 0.1017f, + 0.12602f, 0.14312f, 0.14641f, 0.14698f, 0.17992f, 0.24091f, + 0.268f, 0.28867f, 0.30555f, 0.31654f, 0.31978f, 0.31088f, + 0.28038f, 0.19821f, 0.000000f}, + {0.000000f, 0.000000f, 0.0013084f, 0.018492f, 0.040831f, 0.061737f, + 0.07868f, 0.085813f, 0.08366f, 0.082238f, 0.13301f, 0.20226f, + 0.24232f, 0.26304f, 0.2763f, 0.28192f, 0.27908f, 0.26255f, + 0.22053f, 0.13152f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.0038919f, 0.016973f, 0.031114f, + 0.043546f, 0.046224f, 0.032368f, 0.040874f, 0.089105f, 0.15348f, + 0.19907f, 0.22896f, 0.24081f, 0.24172f, 0.2329f, 0.20846f, + 0.15539f, 0.067908f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0038302f, 0.010822f, + 0.017781f, 0.01238f, 0.0048489f, 0.015357f, 0.051582f, 0.099723f, + 0.14485f, 0.17871f, 0.1997f, 0.19715f, 0.18521f, 0.15233f, + 0.095227f, 0.019725f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0013625f, + 0.00044495f, 0.000000f, 0.000000f, 0.0029287f, 0.021123f, 0.049473f, + 0.081894f, 0.11169f, 0.13466f, 0.15222f, 0.12939f, 0.094728f, + 0.048381f, 0.0022432f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.0019269f, 0.01438f, + 0.031384f, 0.048878f, 0.066587f, 0.075976f, 0.081342f, 0.049892f, + 0.010122f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.0023122f, 0.0075151f, 0.014677f, 0.017689f, 0.019339f, 0.016553f, + 0.0025743f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + -9.4126e-019f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}}; + +float map_lfe_lfe[21][21] = { + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}, + {0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f}}; + +std::map chn_alloc; +std::map> chn_angle; +std::map> chn_xsf; +std::map> chn_ysf; +std::map> chn_id; + +bool init_maps() { + chn_angle[cs_5point1] = std::vector( + &map_5point1_ang[0], + &map_5point1_ang[sizeof(map_5point1_ang) / sizeof(map_5point1_ang[0])]); + chn_xsf[cs_5point1] = std::vector( + &map_5point1_xsf[0], + &map_5point1_xsf[sizeof(map_5point1_xsf) / sizeof(map_5point1_xsf[0])]); + chn_ysf[cs_5point1] = std::vector( + &map_5point1_ysf[0], + &map_5point1_ysf[sizeof(map_5point1_ysf) / sizeof(map_5point1_ysf[0])]); + chn_id[cs_5point1] = std::vector( + &map_5point1_id[0], + &map_5point1_id[sizeof(map_5point1_id) / sizeof(map_5point1_id[0])]); + chn_alloc[cs_5point1].push_back( + std::vector(&map_5point1_lf[0], &map_5point1_lf[21])); + chn_alloc[cs_5point1].push_back( + std::vector(&map_5point1_cf[0], &map_5point1_cf[21])); + chn_alloc[cs_5point1].push_back( + std::vector(&map_5point1_rf[0], &map_5point1_rf[21])); + chn_alloc[cs_5point1].push_back( + std::vector(&map_5point1_ls[0], &map_5point1_ls[21])); + chn_alloc[cs_5point1].push_back( + std::vector(&map_5point1_rs[0], &map_5point1_rs[21])); + chn_alloc[cs_5point1].push_back( + std::vector(&map_lfe_lfe[0], &map_lfe_lfe[21])); + + chn_angle[cs_7point1] = std::vector( + &map_7point1_ang[0], + &map_7point1_ang[sizeof(map_7point1_ang) / sizeof(map_7point1_ang[0])]); + chn_xsf[cs_7point1] = std::vector( + &map_7point1_xsf[0], + &map_7point1_xsf[sizeof(map_7point1_xsf) / sizeof(map_7point1_xsf[0])]); + chn_ysf[cs_7point1] = std::vector( + &map_7point1_ysf[0], + &map_7point1_ysf[sizeof(map_7point1_ysf) / sizeof(map_7point1_ysf[0])]); + chn_id[cs_7point1] = std::vector( + &map_7point1_id[0], + &map_7point1_id[sizeof(map_7point1_id) / sizeof(map_7point1_id[0])]); + chn_alloc[cs_7point1].push_back( + std::vector(&map_7point1_lf[0], &map_7point1_lf[21])); + chn_alloc[cs_7point1].push_back( + std::vector(&map_7point1_cf[0], &map_7point1_cf[21])); + chn_alloc[cs_7point1].push_back( + std::vector(&map_7point1_rf[0], &map_7point1_rf[21])); + chn_alloc[cs_7point1].push_back( + std::vector(&map_7point1_lsm[0], &map_7point1_lsm[21])); + chn_alloc[cs_7point1].push_back( + std::vector(&map_7point1_rsm[0], &map_7point1_rsm[21])); + chn_alloc[cs_7point1].push_back( + std::vector(&map_7point1_ls[0], &map_7point1_ls[21])); + chn_alloc[cs_7point1].push_back( + std::vector(&map_7point1_rs[0], &map_7point1_rs[21])); + chn_alloc[cs_7point1].push_back( + std::vector(&map_lfe_lfe[0], &map_lfe_lfe[21])); + + return true; +} + +namespace { +bool success = init_maps(); +}; diff --git a/Externals/FreeSurround/source/FreeSurroundDecoder.cpp b/Externals/FreeSurround/source/FreeSurroundDecoder.cpp new file mode 100644 index 0000000000..b65734a5cb --- /dev/null +++ b/Externals/FreeSurround/source/FreeSurroundDecoder.cpp @@ -0,0 +1,310 @@ +/* +Copyright (C) 2007-2010 Christian Kothe + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +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 for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "FreeSurround/FreeSurroundDecoder.h" +#include "FreeSurround/ChannelMaps.h" +#include + +#undef min +#undef max + +// FreeSurround implementation +// DPL2FSDecoder::Init() must be called before using the decoder. +DPL2FSDecoder::DPL2FSDecoder() { + initialized = false; + buffer_empty = true; +} + +DPL2FSDecoder::~DPL2FSDecoder() { +#pragma warning(suppress : 4150) + delete forward; +#pragma warning(suppress : 4150) + delete inverse; +} + +void DPL2FSDecoder::Init(channel_setup chsetup, unsigned int blsize, + unsigned int sample_rate) { + if (!initialized) { + setup = chsetup; + N = blsize; + samplerate = sample_rate; + + // Initialize the parameters + wnd = std::vector(N); + inbuf = std::vector(3 * N); + lt = std::vector(N); + rt = std::vector(N); + dst = std::vector(N); + lf = std::vector(N / 2 + 1); + rf = std::vector(N / 2 + 1); + forward = kiss_fftr_alloc(N, 0, 0, 0); + inverse = kiss_fftr_alloc(N, 1, 0, 0); + C = static_cast(chn_alloc[setup].size()); + + // Allocate per-channel buffers + outbuf.resize((N + N / 2) * C); + signal.resize(C, std::vector(N)); + + // Init the window function + for (unsigned int k = 0; k < N; k++) + wnd[k] = sqrt(0.5 * (1 - cos(2 * pi * k / N)) / N); + + // set default parameters + set_circular_wrap(90); + set_shift(0); + set_depth(1); + set_focus(0); + set_center_image(1); + set_front_separation(1); + set_rear_separation(1); + set_low_cutoff(40.0f / samplerate * 2); + set_high_cutoff(90.0f / samplerate * 2); + set_bass_redirection(false); + + initialized = true; + } +} + +// decode a stereo chunk, produces a multichannel chunk of the same size +// (lagged) +float *DPL2FSDecoder::decode(float *input) { + if (initialized) { + // append incoming data to the end of the input buffer + memcpy(&inbuf[N], &input[0], 8 * N); + // process first and second half, overlapped + buffered_decode(&inbuf[0]); + buffered_decode(&inbuf[N]); + // shift last half of the input to the beginning (for overlapping with a + // future block) + memcpy(&inbuf[0], &inbuf[2 * N], 4 * N); + buffer_empty = false; + return &outbuf[0]; + } + return 0; +} + +// flush the internal buffers +void DPL2FSDecoder::flush() { + memset(&outbuf[0], 0, outbuf.size() * 4); + memset(&inbuf[0], 0, inbuf.size() * 4); + buffer_empty = true; +} + +// number of samples currently held in the buffer +unsigned int DPL2FSDecoder::buffered() { return buffer_empty ? 0 : N / 2; } + +// set soundfield & rendering parameters +void DPL2FSDecoder::set_circular_wrap(float v) { circular_wrap = v; } +void DPL2FSDecoder::set_shift(float v) { shift = v; } +void DPL2FSDecoder::set_depth(float v) { depth = v; } +void DPL2FSDecoder::set_focus(float v) { focus = v; } +void DPL2FSDecoder::set_center_image(float v) { center_image = v; } +void DPL2FSDecoder::set_front_separation(float v) { front_separation = v; } +void DPL2FSDecoder::set_rear_separation(float v) { rear_separation = v; } +void DPL2FSDecoder::set_low_cutoff(float v) { lo_cut = v * (N / 2); } +void DPL2FSDecoder::set_high_cutoff(float v) { hi_cut = v * (N / 2); } +void DPL2FSDecoder::set_bass_redirection(bool v) { use_lfe = v; } + +// helper functions +inline float DPL2FSDecoder::sqr(double x) { return static_cast(x * x); } +inline double DPL2FSDecoder::amplitude(const cplx &x) { + return sqrt(sqr(x.real()) + sqr(x.imag())); +} +inline double DPL2FSDecoder::phase(const cplx &x) { + return atan2(x.imag(), x.real()); +} +inline cplx DPL2FSDecoder::polar(double a, double p) { + return cplx(a * cos(p), a * sin(p)); +} +inline float DPL2FSDecoder::min(double a, double b) { + return static_cast(a < b ? a : b); +} +inline float DPL2FSDecoder::max(double a, double b) { + return static_cast(a > b ? a : b); +} +inline float DPL2FSDecoder::clamp(double x) { return max(-1, min(1, x)); } +inline float DPL2FSDecoder::sign(double x) { + return static_cast(x < 0 ? -1 : (x > 0 ? 1 : 0)); +} +// get the distance of the soundfield edge, along a given angle +inline double DPL2FSDecoder::edgedistance(double a) { + return min(sqrt(1 + sqr(tan(a))), sqrt(1 + sqr(1 / tan(a)))); +} +// get the index (and fractional offset!) in a piecewise-linear channel +// allocation grid +int DPL2FSDecoder::map_to_grid(double &x) { + double gp = ((x + 1) * 0.5) * (grid_res - 1), + i = min(grid_res - 2, floor(gp)); + x = gp - i; + return static_cast(i); +} + +// decode a block of data and overlap-add it into outbuf +void DPL2FSDecoder::buffered_decode(float *input) { + // demultiplex and apply window function + for (unsigned int k = 0; k < N; k++) { + lt[k] = wnd[k] * input[k * 2 + 0]; + rt[k] = wnd[k] * input[k * 2 + 1]; + } + + // map into spectral domain + kiss_fftr(forward, <[0], (kiss_fft_cpx *)&lf[0]); + kiss_fftr(forward, &rt[0], (kiss_fft_cpx *)&rf[0]); + + // compute multichannel output signal in the spectral domain + for (unsigned int f = 1; f < N / 2; f++) { + // get Lt/Rt amplitudes & phases + double ampL = amplitude(lf[f]), ampR = amplitude(rf[f]); + double phaseL = phase(lf[f]), phaseR = phase(rf[f]); + // calculate the amplitude & phase differences + double ampDiff = + clamp((ampL + ampR < epsilon) ? 0 : (ampR - ampL) / (ampR + ampL)); + double phaseDiff = abs(phaseL - phaseR); + if (phaseDiff > pi) + phaseDiff = 2 * pi - phaseDiff; + + // decode into x/y soundfield position + double x, y; + transform_decode(ampDiff, phaseDiff, x, y); + // add wrap control + transform_circular_wrap(x, y, circular_wrap); + // add shift control + y = clamp(y - shift); + // add depth control + y = clamp(1 - (1 - y) * depth); + // add focus control + transform_focus(x, y, focus); + // add crossfeed control + x = clamp(x * + (front_separation * (1 + y) / 2 + rear_separation * (1 - y) / 2)); + + // get total signal amplitude + double amp_total = sqrt(ampL * ampL + ampR * ampR); + // and total L/C/R signal phases + double phase_of[] = { + phaseL, atan2(lf[f].imag() + rf[f].imag(), lf[f].real() + rf[f].real()), + phaseR}; + // compute 2d channel map indexes p/q and update x/y to fractional offsets + // in the map grid + int p = map_to_grid(x), q = map_to_grid(y); + // map position to channel volumes + for (unsigned int c = 0; c < C - 1; c++) { + // look up channel map at respective position (with bilinear + // interpolation) and build the + // signal + std::vector &a = chn_alloc[setup][c]; + 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 + static_cast(sign(chn_xsf[setup][c]))]); + } + + // optionally redirect bass + if (use_lfe && f < hi_cut) { + // level of LFE channel according to normalized frequency + double lfe_level = + f < lo_cut ? 1 + : 0.5 * (1 + cos(pi * (f - lo_cut) / (hi_cut - lo_cut))); + // assign LFE channel + signal[C - 1][f] = lfe_level * polar(amp_total, phase_of[1]); + // subtract the signal from the other channels + for (unsigned int c = 0; c < C - 1; c++) + signal[c][f] *= (1 - lfe_level); + } + } + + // shift the last 2/3 to the first 2/3 of the output buffer + memcpy(&outbuf[0], &outbuf[C * N / 2], N * C * 4); + // and clear the rest + memset(&outbuf[C * N], 0, C * 4 * N / 2); + // backtransform each channel and overlap-add + for (unsigned int c = 0; c < C; c++) { + // back-transform into time domain + kiss_fftri(inverse, (kiss_fft_cpx *)&signal[c][0], &dst[0]); + // add the result to the last 2/3 of the output buffer, windowed (and + // remultiplex) + for (unsigned int k = 0; k < N; k++) + outbuf[C * (k + N / 2) + c] += static_cast(wnd[k] * dst[k]); + } +} + +// transform amp/phase difference space into x/y soundfield space +void DPL2FSDecoder::transform_decode(double a, double p, double &x, double &y) { + x = clamp(1.0047 * a + 0.46804 * a * p * p * p - 0.2042 * a * p * p * p * p + + 0.0080586 * a * p * p * p * p * p * p * p - + 0.0001526 * a * p * p * p * p * p * p * p * p * p * p - + 0.073512 * a * a * a * p - 0.2499 * a * a * a * p * p * p * p + + 0.016932 * a * a * a * p * p * p * p * p * p * p - + 0.00027707 * a * a * a * p * p * p * p * p * p * p * p * p * p + + 0.048105 * a * a * a * a * a * p * p * p * p * p * p * p - + 0.0065947 * a * a * a * a * a * p * p * p * p * p * p * p * p * p * + p + + 0.0016006 * a * a * a * a * a * p * p * p * p * p * p * p * p * p * + p * p - + 0.0071132 * a * a * a * a * a * a * a * p * p * p * p * p * p * p * + p * p + + 0.0022336 * a * a * a * a * a * a * a * p * p * p * p * p * p * p * + p * p * p * p - + 0.0004804 * a * a * a * a * a * a * a * p * p * p * p * p * p * p * + p * p * p * p * p); + y = clamp( + 0.98592 - 0.62237 * p + 0.077875 * p * p - 0.0026929 * p * p * p * p * p + + 0.4971 * a * a * p - 0.00032124 * a * a * p * p * p * p * p * p + + 9.2491e-006 * a * a * a * a * p * p * p * p * p * p * p * p * p * p + + 0.051549 * a * a * a * a * a * a * a * a + + 1.0727e-014 * a * a * a * a * a * a * a * a * a * a); +} + +// apply a circular_wrap transformation to some position +void DPL2FSDecoder::transform_circular_wrap(double &x, double &y, + double refangle) { + if (refangle == 90) + return; + refangle = refangle * pi / 180; + double baseangle = 90 * pi / 180; + // translate into edge-normalized polar coordinates + double ang = atan2(x, y), len = sqrt(x * x + y * y); + len = len / edgedistance(ang); + // apply circular_wrap transform + if (abs(ang) < baseangle / 2) + // angle falls within the front region (to be enlarged) + ang *= refangle / baseangle; + else + // angle falls within the rear region (to be shrunken) + ang = pi - (-(((refangle - 2 * pi) * (pi - abs(ang)) * sign(ang)) / + (2 * pi - baseangle))); + // translate back into soundfield position + len = len * edgedistance(ang); + x = clamp(sin(ang) * len); + y = clamp(cos(ang) * len); +} + +// apply a focus transformation to some position +void DPL2FSDecoder::transform_focus(double &x, double &y, double focus) { + if (focus == 0) + return; + // translate into edge-normalized polar coordinates + double ang = atan2(x, y), + len = clamp(sqrt(x * x + y * y) / edgedistance(ang)); + // apply focus + len = focus > 0 ? 1 - pow(1 - len, 1 + focus * 20) : pow(len, 1 - focus * 20); + // back-transform into euclidian soundfield position + len = len * edgedistance(ang); + x = clamp(sin(ang) * len); + y = clamp(cos(ang) * len); +} diff --git a/Externals/FreeSurround/source/KissFFT.cpp b/Externals/FreeSurround/source/KissFFT.cpp new file mode 100644 index 0000000000..9799628f15 --- /dev/null +++ b/Externals/FreeSurround/source/KissFFT.cpp @@ -0,0 +1,444 @@ +/* +Copyright (c) 2003-2010, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted +provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, +this list of conditions +and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, +this list of +conditions and the following disclaimer in the documentation and/or other +materials provided with +the distribution. + * Neither the author nor the names of any contributors may be used to +endorse or promote +products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "FreeSurround/_KissFFTGuts.h" +/* The guts header contains all the multiplication and addition macros that are + defined for + fixed or floating point complex numbers. It also delares the kf_ internal + functions. + */ + +static void kf_bfly2(kiss_fft_cpx *Fout, const size_t fstride, + const kiss_fft_cfg st, int m) { + kiss_fft_cpx *Fout2; + kiss_fft_cpx *tw1 = st->twiddles; + kiss_fft_cpx t; + Fout2 = Fout + m; + do { + C_FIXDIV(*Fout, 2); + C_FIXDIV(*Fout2, 2); + + C_MUL(t, *Fout2, *tw1); + tw1 += fstride; + C_SUB(*Fout2, *Fout, t); + C_ADDTO(*Fout, t); + ++Fout2; + ++Fout; + } while (--m); +} + +static void kf_bfly4(kiss_fft_cpx *Fout, const size_t fstride, + const kiss_fft_cfg st, const size_t m) { + kiss_fft_cpx *tw1, *tw2, *tw3; + kiss_fft_cpx scratch[6]; + size_t k = m; + const size_t m2 = 2 * m; + const size_t m3 = 3 * m; + + tw3 = tw2 = tw1 = st->twiddles; + + do { + C_FIXDIV(*Fout, 4); + C_FIXDIV(Fout[m], 4); + C_FIXDIV(Fout[m2], 4); + C_FIXDIV(Fout[m3], 4); + + C_MUL(scratch[0], Fout[m], *tw1); + C_MUL(scratch[1], Fout[m2], *tw2); + C_MUL(scratch[2], Fout[m3], *tw3); + + C_SUB(scratch[5], *Fout, scratch[1]); + C_ADDTO(*Fout, scratch[1]); + C_ADD(scratch[3], scratch[0], scratch[2]); + C_SUB(scratch[4], scratch[0], scratch[2]); + C_SUB(Fout[m2], *Fout, scratch[3]); + tw1 += fstride; + tw2 += fstride * 2; + tw3 += fstride * 3; + C_ADDTO(*Fout, scratch[3]); + + if (st->inverse) { + Fout[m].r = scratch[5].r - scratch[4].i; + Fout[m].i = scratch[5].i + scratch[4].r; + Fout[m3].r = scratch[5].r + scratch[4].i; + Fout[m3].i = scratch[5].i - scratch[4].r; + } else { + Fout[m].r = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = scratch[5].i + scratch[4].r; + } + ++Fout; + } while (--k); +} + +static void kf_bfly3(kiss_fft_cpx *Fout, const size_t fstride, + const kiss_fft_cfg st, size_t m) { + size_t k = m; + const size_t m2 = 2 * m; + kiss_fft_cpx *tw1, *tw2; + kiss_fft_cpx scratch[5]; + kiss_fft_cpx epi3; + epi3 = st->twiddles[fstride * m]; + + tw1 = tw2 = st->twiddles; + + do { + C_FIXDIV(*Fout, 3); + C_FIXDIV(Fout[m], 3); + C_FIXDIV(Fout[m2], 3); + + C_MUL(scratch[1], Fout[m], *tw1); + C_MUL(scratch[2], Fout[m2], *tw2); + + C_ADD(scratch[3], scratch[1], scratch[2]); + C_SUB(scratch[0], scratch[1], scratch[2]); + tw1 += fstride; + tw2 += fstride * 2; + + Fout[m].r = Fout->r - HALF_OF(scratch[3].r); + Fout[m].i = Fout->i - HALF_OF(scratch[3].i); + + C_MULBYSCALAR(scratch[0], epi3.i); + + C_ADDTO(*Fout, scratch[3]); + + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; + + Fout[m].r -= scratch[0].i; + Fout[m].i += scratch[0].r; + + ++Fout; + } while (--k); +} + +static void kf_bfly5(kiss_fft_cpx *Fout, const size_t fstride, + const kiss_fft_cfg st, int m) { + kiss_fft_cpx *Fout0, *Fout1, *Fout2, *Fout3, *Fout4; + int u; + kiss_fft_cpx scratch[13]; + kiss_fft_cpx *twiddles = st->twiddles; + kiss_fft_cpx *tw; + kiss_fft_cpx ya, yb; + ya = twiddles[fstride * m]; + yb = twiddles[fstride * 2 * m]; + + Fout0 = Fout; + Fout1 = Fout0 + m; + Fout2 = Fout0 + 2 * m; + Fout3 = Fout0 + 3 * m; + Fout4 = Fout0 + 4 * m; + + tw = st->twiddles; + for (u = 0; u < m; ++u) { + C_FIXDIV(*Fout0, 5); + C_FIXDIV(*Fout1, 5); + C_FIXDIV(*Fout2, 5); + C_FIXDIV(*Fout3, 5); + C_FIXDIV(*Fout4, 5); + scratch[0] = *Fout0; + + C_MUL(scratch[1], *Fout1, tw[u * fstride]); + C_MUL(scratch[2], *Fout2, tw[2 * u * fstride]); + C_MUL(scratch[3], *Fout3, tw[3 * u * fstride]); + C_MUL(scratch[4], *Fout4, tw[4 * u * fstride]); + + C_ADD(scratch[7], scratch[1], scratch[4]); + C_SUB(scratch[10], scratch[1], scratch[4]); + C_ADD(scratch[8], scratch[2], scratch[3]); + C_SUB(scratch[9], scratch[2], scratch[3]); + + Fout0->r += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + + scratch[5].r = + scratch[0].r + S_MUL(scratch[7].r, ya.r) + S_MUL(scratch[8].r, yb.r); + scratch[5].i = + scratch[0].i + S_MUL(scratch[7].i, ya.r) + S_MUL(scratch[8].i, yb.r); + + scratch[6].r = S_MUL(scratch[10].i, ya.i) + S_MUL(scratch[9].i, yb.i); + scratch[6].i = -S_MUL(scratch[10].r, ya.i) - S_MUL(scratch[9].r, yb.i); + + C_SUB(*Fout1, scratch[5], scratch[6]); + C_ADD(*Fout4, scratch[5], scratch[6]); + + scratch[11].r = + scratch[0].r + S_MUL(scratch[7].r, yb.r) + S_MUL(scratch[8].r, ya.r); + scratch[11].i = + scratch[0].i + S_MUL(scratch[7].i, yb.r) + S_MUL(scratch[8].i, ya.r); + scratch[12].r = -S_MUL(scratch[10].i, yb.i) + S_MUL(scratch[9].i, ya.i); + scratch[12].i = S_MUL(scratch[10].r, yb.i) - S_MUL(scratch[9].r, ya.i); + + C_ADD(*Fout2, scratch[11], scratch[12]); + C_SUB(*Fout3, scratch[11], scratch[12]); + + ++Fout0; + ++Fout1; + ++Fout2; + ++Fout3; + ++Fout4; + } +} + +/* perform the butterfly for one stage of a mixed radix FFT */ +static void kf_bfly_generic(kiss_fft_cpx *Fout, const size_t fstride, + const kiss_fft_cfg st, int m, int p) { + int u, k, q1, q; + kiss_fft_cpx *twiddles = st->twiddles; + kiss_fft_cpx t; + int Norig = st->nfft; + + kiss_fft_cpx *scratch = + (kiss_fft_cpx *)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx) * p); + + for (u = 0; u < m; ++u) { + k = u; + for (q1 = 0; q1 < p; ++q1) { + scratch[q1] = Fout[k]; + C_FIXDIV(scratch[q1], p); + k += m; + } + + k = u; + for (q1 = 0; q1 < p; ++q1) { + int twidx = 0; + Fout[k] = scratch[0]; + for (q = 1; q < p; ++q) { + twidx += static_cast(fstride) * k; + if (twidx >= Norig) + twidx -= Norig; + C_MUL(t, scratch[q], twiddles[twidx]); + C_ADDTO(Fout[k], t); + } + k += m; + } + } + KISS_FFT_TMP_FREE(scratch); +} + +static void kf_work(kiss_fft_cpx *Fout, const kiss_fft_cpx *f, + const size_t fstride, int in_stride, int *factors, + const kiss_fft_cfg st) { + kiss_fft_cpx *Fout_beg = Fout; + const int p = *factors++; /* the radix */ + const int m = *factors++; /* stage's fft length/p */ + const kiss_fft_cpx *Fout_end = Fout + p * m; + +#ifdef _OPENMP + // use openmp extensions at the + // top-level (not recursive) + if (fstride == 1 && p <= 5) { + int k; + +// execute the p different work units in different threads +#pragma omp parallel for + for (k = 0; k < p; ++k) + kf_work(Fout + k * m, f + fstride * in_stride * k, fstride * p, in_stride, + factors, st); + // all threads have joined by this point + + switch (p) { + case 2: + kf_bfly2(Fout, fstride, st, m); + break; + case 3: + kf_bfly3(Fout, fstride, st, m); + break; + case 4: + kf_bfly4(Fout, fstride, st, m); + break; + case 5: + kf_bfly5(Fout, fstride, st, m); + break; + default: + kf_bfly_generic(Fout, fstride, st, m, p); + break; + } + return; + } +#endif + + if (m == 1) { + do { + *Fout = *f; + f += fstride * in_stride; + } while (++Fout != Fout_end); + } else { + do { + // recursive call: + // DFT of size m*p performed by doing + // p instances of smaller DFTs of size m, + // each one takes a decimated version of the input + kf_work(Fout, f, fstride * p, in_stride, factors, st); + f += fstride * in_stride; + } while ((Fout += m) != Fout_end); + } + + Fout = Fout_beg; + + // recombine the p smaller DFTs + switch (p) { + case 2: + kf_bfly2(Fout, fstride, st, m); + break; + case 3: + kf_bfly3(Fout, fstride, st, m); + break; + case 4: + kf_bfly4(Fout, fstride, st, m); + break; + case 5: + kf_bfly5(Fout, fstride, st, m); + break; + default: + kf_bfly_generic(Fout, fstride, st, m, p); + break; + } +} + +/* facbuf is populated by p1,m1,p2,m2, ... + where + p[i] * m[i] = m[i-1] + m0 = n */ +static void kf_factor(int n, int *facbuf) { + int p = 4; + double floor_sqrt; + floor_sqrt = floor(sqrt((double)n)); + + /*factor out powers of 4, powers of 2, then any remaining primes */ + do { + while (n % p) { + switch (p) { + case 4: + p = 2; + break; + case 2: + p = 3; + break; + default: + p += 2; + break; + } + if (p > floor_sqrt) + p = n; /* no more factors, skip to end */ + } + n /= p; + *facbuf++ = p; + *facbuf++ = n; + } while (n > 1); +} + +/* + * + * User-callable function to allocate all necessary storage space for the fft. + * + * The return value is a contiguous block of memory, allocated with malloc. As + * such, + * It can be freed with free(), rather than a kiss_fft-specific function. + * */ +kiss_fft_cfg kiss_fft_alloc(int nfft, int inverse_fft, void *mem, + size_t *lenmem) { + kiss_fft_cfg st = NULL; + size_t memneeded = sizeof(struct kiss_fft_state) + + sizeof(kiss_fft_cpx) * (nfft - 1); /* twiddle factors*/ + + if (lenmem == NULL) { + st = (kiss_fft_cfg) new char[memneeded]; + } else { + if (mem != NULL && *lenmem >= memneeded) + st = (kiss_fft_cfg)mem; + *lenmem = memneeded; + } + if (st) { + int i; + st->nfft = nfft; + st->inverse = inverse_fft; + + for (i = 0; i < nfft; ++i) { + const double pi = + 3.141592653589793238462643383279502884197169399375105820974944; + double phase = -2 * pi * i / nfft; + if (st->inverse) + phase *= -1; + kf_cexp(st->twiddles + i, phase); + } + + kf_factor(nfft, st->factors); + } + return st; +} + +void kiss_fft_stride(kiss_fft_cfg st, const kiss_fft_cpx *fin, + kiss_fft_cpx *fout, int in_stride) { + if (fin == fout) { + // NOTE: this is not really an in-place FFT algorithm. + // It just performs an out-of-place FFT into a temp buffer + kiss_fft_cpx *tmpbuf = + (kiss_fft_cpx *)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx) * st->nfft); + kf_work(tmpbuf, fin, 1, in_stride, st->factors, st); + memcpy(fout, tmpbuf, sizeof(kiss_fft_cpx) * st->nfft); + KISS_FFT_TMP_FREE(tmpbuf); + } else { + kf_work(fout, fin, 1, in_stride, st->factors, st); + } +} + +void kiss_fft(kiss_fft_cfg cfg, const kiss_fft_cpx *fin, kiss_fft_cpx *fout) { + kiss_fft_stride(cfg, fin, fout, 1); +} + +void kiss_fft_cleanup(void) { + // nothing needed any more +} + +int kiss_fft_next_fast_size(int n) { + while (1) { + int m = n; + while ((m % 2) == 0) + m /= 2; + while ((m % 3) == 0) + m /= 3; + while ((m % 5) == 0) + m /= 5; + if (m <= 1) + break; /* n is completely factorable by twos, threes, and fives */ + n++; + } + return n; +} diff --git a/Externals/FreeSurround/source/KissFFTR.cpp b/Externals/FreeSurround/source/KissFFTR.cpp new file mode 100644 index 0000000000..41b13d43d3 --- /dev/null +++ b/Externals/FreeSurround/source/KissFFTR.cpp @@ -0,0 +1,185 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted +provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, +this list of conditions +and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, +this list of +conditions and the following disclaimer in the documentation and/or other +materials provided with +the distribution. + * Neither the author nor the names of any contributors may be used to +endorse or promote +products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "FreeSurround/KissFFTR.h" +#include "FreeSurround/_KissFFTGuts.h" + +struct kiss_fftr_state { + kiss_fft_cfg substate; + kiss_fft_cpx *tmpbuf; + kiss_fft_cpx *super_twiddles; +#ifdef USE_SIMD + void *pad; +#endif +}; + +kiss_fftr_cfg kiss_fftr_alloc(int nfft, int inverse_fft, void *mem, + size_t *lenmem) { + int i; + kiss_fftr_cfg st = NULL; + size_t subsize = 65536 * 4, memneeded = 0; + + if (nfft & 1) { + fprintf(stderr, "Real FFT optimization must be even.\n"); + return NULL; + } + nfft >>= 1; + + kiss_fft_alloc(nfft, inverse_fft, NULL, &subsize); + memneeded = sizeof(struct kiss_fftr_state) + subsize + + sizeof(kiss_fft_cpx) * (nfft * 3 / 2); + + if (lenmem == NULL) { + st = (kiss_fftr_cfg) new char[memneeded]; + } else { + if (*lenmem >= memneeded) + st = (kiss_fftr_cfg)mem; + *lenmem = memneeded; + } + if (!st) + return NULL; + + st->substate = (kiss_fft_cfg)(st + 1); /*just beyond kiss_fftr_state struct */ + st->tmpbuf = (kiss_fft_cpx *)(((char *)st->substate) + subsize); + st->super_twiddles = st->tmpbuf + nfft; + kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize); + + for (i = 0; i < nfft / 2; ++i) { + double phase = + -3.14159265358979323846264338327 * ((double)(i + 1) / nfft + .5); + if (inverse_fft) + phase *= -1; + kf_cexp(st->super_twiddles + i, phase); + } + return st; +} + +void kiss_fftr(kiss_fftr_cfg st, const kiss_fft_scalar *timedata, + kiss_fft_cpx *freqdata) { + /* input buffer timedata is stored row-wise */ + int k, ncfft; + kiss_fft_cpx fpnk, fpk, f1k, f2k, tw, tdc; + + if (st->substate->inverse) { + fprintf(stderr, "kiss fft usage error: improper alloc\n"); + exit(1); + } + + ncfft = st->substate->nfft; + + /*perform the parallel fft of two real signals packed in real,imag*/ + kiss_fft(st->substate, (const kiss_fft_cpx *)timedata, st->tmpbuf); + /* The real part of the DC element of the frequency spectrum in st->tmpbuf + * contains the sum of the even-numbered elements of the input time sequence + * The imag part is the sum of the odd-numbered elements + * + * The sum of tdc.r and tdc.i is the sum of the input time sequence. + * yielding DC of input time sequence + * The difference of tdc.r - tdc.i is the sum of the input (dot product) + * [1,-1,1,-1... + * yielding Nyquist bin of input time sequence + */ + + tdc.r = st->tmpbuf[0].r; + tdc.i = st->tmpbuf[0].i; + C_FIXDIV(tdc, 2); + CHECK_OVERFLOW_OP(tdc.r, +, tdc.i); + CHECK_OVERFLOW_OP(tdc.r, -, tdc.i); + freqdata[0].r = tdc.r + tdc.i; + freqdata[ncfft].r = tdc.r - tdc.i; +#ifdef USE_SIMD + freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0); +#else + freqdata[ncfft].i = freqdata[0].i = 0; +#endif + + for (k = 1; k <= ncfft / 2; ++k) { + fpk = st->tmpbuf[k]; + fpnk.r = st->tmpbuf[ncfft - k].r; + fpnk.i = -st->tmpbuf[ncfft - k].i; + C_FIXDIV(fpk, 2); + C_FIXDIV(fpnk, 2); + + C_ADD(f1k, fpk, fpnk); + C_SUB(f2k, fpk, fpnk); + C_MUL(tw, f2k, st->super_twiddles[k - 1]); + + freqdata[k].r = HALF_OF(f1k.r + tw.r); + freqdata[k].i = HALF_OF(f1k.i + tw.i); + freqdata[ncfft - k].r = HALF_OF(f1k.r - tw.r); + freqdata[ncfft - k].i = HALF_OF(tw.i - f1k.i); + } +} + +void kiss_fftri(kiss_fftr_cfg st, const kiss_fft_cpx *freqdata, + kiss_fft_scalar *timedata) { + /* input buffer timedata is stored row-wise */ + int k, ncfft; + + if (st->substate->inverse == 0) { + fprintf(stderr, "kiss fft usage error: improper alloc\n"); + exit(1); + } + + ncfft = st->substate->nfft; + + st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; + st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; + C_FIXDIV(st->tmpbuf[0], 2); + + for (k = 1; k <= ncfft / 2; ++k) { + kiss_fft_cpx fk, fnkc, fek, fok, tmp; + fk = freqdata[k]; + fnkc.r = freqdata[ncfft - k].r; + fnkc.i = -freqdata[ncfft - k].i; + C_FIXDIV(fk, 2); + C_FIXDIV(fnkc, 2); + + C_ADD(fek, fk, fnkc); + C_SUB(tmp, fk, fnkc); + C_MUL(fok, tmp, st->super_twiddles[k - 1]); + C_ADD(st->tmpbuf[k], fek, fok); + C_SUB(st->tmpbuf[ncfft - k], fek, fok); +#ifdef USE_SIMD + st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); +#else + st->tmpbuf[ncfft - k].i *= -1; +#endif + } + kiss_fft(st->substate, st->tmpbuf, (kiss_fft_cpx *)timedata); +} diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj b/Source/Core/AudioCommon/AudioCommon.vcxproj index bd6b469ac6..d1dc1bde89 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj @@ -40,11 +40,11 @@ - + @@ -57,7 +57,6 @@ - @@ -65,6 +64,7 @@ + @@ -79,6 +79,9 @@ {2e6c348c-c75c-4d94-8d1e-9c1fcbf3efe4} + + {8498f2fa-5ca6-4169-9971-de5b1fe6132c} + diff --git a/Source/Core/AudioCommon/AudioCommon.vcxproj.filters b/Source/Core/AudioCommon/AudioCommon.vcxproj.filters index c710630f4a..44ba796b38 100644 --- a/Source/Core/AudioCommon/AudioCommon.vcxproj.filters +++ b/Source/Core/AudioCommon/AudioCommon.vcxproj.filters @@ -9,7 +9,6 @@ - @@ -30,12 +29,12 @@ SoundStreams + - @@ -68,6 +67,7 @@ SoundStreams + diff --git a/Source/Core/AudioCommon/CMakeLists.txt b/Source/Core/AudioCommon/CMakeLists.txt index 8664d4bf70..577bdb41fb 100644 --- a/Source/Core/AudioCommon/CMakeLists.txt +++ b/Source/Core/AudioCommon/CMakeLists.txt @@ -3,8 +3,8 @@ add_library(audiocommon AudioStretcher.cpp CubebStream.cpp CubebUtils.cpp - DPL2Decoder.cpp Mixer.cpp + SurroundDecoder.cpp NullSoundStream.cpp WaveFile.cpp ) @@ -69,4 +69,4 @@ if(WIN32) endif() endif() -target_link_libraries(audiocommon PRIVATE cubeb SoundTouch) +target_link_libraries(audiocommon PRIVATE cubeb SoundTouch FreeSurround) diff --git a/Source/Core/AudioCommon/CubebStream.cpp b/Source/Core/AudioCommon/CubebStream.cpp index 754db1d957..da515aa8f3 100644 --- a/Source/Core/AudioCommon/CubebStream.cpp +++ b/Source/Core/AudioCommon/CubebStream.cpp @@ -6,7 +6,6 @@ #include "AudioCommon/CubebStream.h" #include "AudioCommon/CubebUtils.h" -#include "AudioCommon/DPL2Decoder.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" #include "Common/Thread.h" diff --git a/Source/Core/AudioCommon/DPL2Decoder.cpp b/Source/Core/AudioCommon/DPL2Decoder.cpp deleted file mode 100644 index c48026003a..0000000000 --- a/Source/Core/AudioCommon/DPL2Decoder.cpp +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -// Dolby Pro Logic 2 decoder from ffdshow-tryout -// * Copyright 2001 Anders Johansson ajh@atri.curtin.edu.au -// * Copyright (c) 2004-2006 Milan Cutka -// * based on mplayer HRTF plugin by ylai - -#include -#include -#include -#include -#include -#include -#include - -#include "AudioCommon/DPL2Decoder.h" -#include "Common/CommonTypes.h" -#include "Common/MathUtil.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif -#ifndef M_SQRT1_2 -#define M_SQRT1_2 0.70710678118654752440 -#endif - -static int olddelay = -1; -static unsigned int oldfreq = 0; -static unsigned int dlbuflen; -static int cyc_pos; -static float l_fwr, r_fwr, lpr_fwr, lmr_fwr; -static std::vector fwrbuf_l, fwrbuf_r; -static float adapt_l_gain, adapt_r_gain, adapt_lpr_gain, adapt_lmr_gain; -static std::vector lf, rf, lr, rr, cf, cr; -static float LFE_buf[256]; -static unsigned int lfe_pos; -static std::vector filter_coefs_lfe; -static unsigned int len125; - -template -static float DotProduct(int count, const T* buf, const std::vector& coeffs, int offset) -{ - return std::inner_product(buf, buf + count, coeffs.begin() + offset, T(0)); -} - -template -static T FIRFilter(const T* buf, int pos, int len, int count, const std::vector& coeffs) -{ - int count1, count2; - - if (pos >= count) - { - pos -= count; - count1 = count; - count2 = 0; - } - else - { - count2 = pos; - count1 = count - pos; - pos = len - count1; - } - - // high part of window - const T* ptr = &buf[pos]; - - float r1 = DotProduct(count1, ptr, coeffs, 0); - float r2 = DotProduct(count2, buf, coeffs, count1); - return T(r1 + r2); -} - -/* -// Hamming -// 2*pi*k -// w(k) = 0.54 - 0.46*cos(------), where 0 <= k < N -// N-1 -// -// n window length -// returns buffer with the window parameters -*/ -static std::vector Hamming(int n) -{ - std::vector w(n); - - float k = static_cast(2.0 * M_PI / (n - 1)); - - // Calculate window coefficients - for (int i = 0; i < n; i++) - w[i] = static_cast(0.54 - 0.46 * cos(k * i)); - - return w; -} - -// FIR filter design - -/* Design FIR filter using the Window method - -n filter length must be odd for HP and BS filters -fc cutoff frequencies (1 for LP and HP, 2 for BP and BS) -0 < fc < 1 where 1 <=> Fs/2 -flags window and filter type as defined in filter.h -variables are ored together: i.e. LP|HAMMING will give a -low pass filter designed using a hamming window -opt beta constant used only when designing using kaiser windows - -returns buffer for the filter taps (will be n long) -*/ -static std::vector DesignFIR(unsigned int n, float fc, float opt) -{ - const unsigned int o = n & 1; // Indicator for odd filter length - const unsigned int end = ((n + 1) >> 1) - o; // Loop end - - // Cutoff frequency must be < 0.5 where 0.5 <=> Fs/2 - const float fc1 = MathUtil::Clamp(fc, 0.001f, 1.0f) / 2; - - const float k1 = 2 * static_cast(M_PI) * fc1; // Cutoff frequency in rad/s - const float k2 = 0.5f * static_cast(1 - o); // Time offset if filter has even length - float g = 0.0f; // Gain - - // Sanity check - if (n == 0) - return {}; - - // Get window coefficients - std::vector w = Hamming(n); - - // Low pass filter - - // If the filter length is odd, there is one point which is exactly - // in the middle. The value at this point is 2*fCutoff*sin(x)/x, - // where x is zero. To make sure nothing strange happens, we set this - // value separately. - if (o) - { - w[end] = fc1 * w[end] * 2.0f; - g = w[end]; - } - - // Create filter - for (u32 i = 0; i < end; i++) - { - float t1 = static_cast(i + 1) - k2; - w[end - i - 1] = w[n - end + i] = - static_cast(w[end - i - 1] * sin(k1 * t1) / (M_PI * t1)); // Sinc - g += 2 * w[end - i - 1]; // Total gain in filter - } - - // Normalize gain - g = 1 / g; - for (u32 i = 0; i < n; i++) - w[i] *= g; - - return w; -} - -static void OnSeek() -{ - l_fwr = r_fwr = lpr_fwr = lmr_fwr = 0; - std::fill(fwrbuf_l.begin(), fwrbuf_l.end(), 0.0f); - std::fill(fwrbuf_r.begin(), fwrbuf_r.end(), 0.0f); - adapt_l_gain = adapt_r_gain = adapt_lpr_gain = adapt_lmr_gain = 0; - std::fill(lf.begin(), lf.end(), 0.0f); - std::fill(rf.begin(), rf.end(), 0.0f); - std::fill(lr.begin(), lr.end(), 0.0f); - std::fill(rr.begin(), rr.end(), 0.0f); - std::fill(cf.begin(), cf.end(), 0.0f); - std::fill(cr.begin(), cr.end(), 0.0f); - lfe_pos = 0; - memset(LFE_buf, 0, sizeof(LFE_buf)); -} - -static void Done() -{ - OnSeek(); - - filter_coefs_lfe.clear(); -} - -static std::vector CalculateCoefficients125HzLowpass(int rate) -{ - len125 = 256; - float f = 125.0f / (rate / 2); - std::vector coeffs = DesignFIR(len125, f, 0); - static const float M3_01DB = 0.7071067812f; - for (unsigned int i = 0; i < len125; i++) - { - coeffs[i] *= M3_01DB; - } - return coeffs; -} - -static float PassiveLock(float x) -{ - static const float MATAGCLOCK = - 0.2f; /* AGC range (around 1) where the matrix behaves passively */ - const float x1 = x - 1; - const float ax1s = fabs(x - 1) * (1.0f / MATAGCLOCK); - return x1 - x1 / (1 + ax1s * ax1s) + 1; -} - -static void MatrixDecode(const float* in, const int k, const int il, const int ir, bool decode_rear, - const int _dlbuflen, float _l_fwr, float _r_fwr, float _lpr_fwr, - float _lmr_fwr, float* _adapt_l_gain, float* _adapt_r_gain, - float* _adapt_lpr_gain, float* _adapt_lmr_gain, float* _lf, float* _rf, - float* _lr, float* _rr, float* _cf) -{ - static const float M9_03DB = 0.3535533906f; - static const float MATAGCTRIG = 8.0f; /* (Fuzzy) AGC trigger */ - static const float MATAGCDECAY = 1.0f; /* AGC baseline decay rate (1/samp.) */ - static const float MATCOMPGAIN = - 0.37f; /* Cross talk compensation gain, 0.50 - 0.55 is full cancellation. */ - - const int kr = (k + olddelay) % _dlbuflen; - float l_gain = (_l_fwr + _r_fwr) / (1 + _l_fwr + _l_fwr); - float r_gain = (_l_fwr + _r_fwr) / (1 + _r_fwr + _r_fwr); - // The 2nd axis has strong gain fluctuations, and therefore require - // limits. The factor corresponds to the 1 / amplification of (Lt - // - Rt) when (Lt, Rt) is strongly correlated. (e.g. during - // dialogues). It should be bigger than -12 dB to prevent - // distortion. - float lmr_lim_fwr = _lmr_fwr > M9_03DB * _lpr_fwr ? _lmr_fwr : M9_03DB * _lpr_fwr; - float lpr_gain = (_lpr_fwr + lmr_lim_fwr) / (1 + _lpr_fwr + _lpr_fwr); - float lmr_gain = (_lpr_fwr + lmr_lim_fwr) / (1 + lmr_lim_fwr + lmr_lim_fwr); - float lmr_unlim_gain = (_lpr_fwr + _lmr_fwr) / (1 + _lmr_fwr + _lmr_fwr); - float lpr, lmr; - float l_agc, r_agc, lpr_agc, lmr_agc; - float f, d_gain, c_gain, c_agc_cfk; - - /*** AXIS NO. 1: (Lt, Rt) -> (C, Ls, Rs) ***/ - /* AGC adaption */ - d_gain = (fabs(l_gain - *_adapt_l_gain) + fabs(r_gain - *_adapt_r_gain)) * 0.5f; - f = d_gain * (1.0f / MATAGCTRIG); - f = MATAGCDECAY - MATAGCDECAY / (1 + f * f); - *_adapt_l_gain = (1 - f) * *_adapt_l_gain + f * l_gain; - *_adapt_r_gain = (1 - f) * *_adapt_r_gain + f * r_gain; - /* Matrix */ - l_agc = in[il] * PassiveLock(*_adapt_l_gain); - r_agc = in[ir] * PassiveLock(*_adapt_r_gain); - _cf[k] = (l_agc + r_agc) * static_cast(M_SQRT1_2); - if (decode_rear) - { - _lr[kr] = _rr[kr] = (l_agc - r_agc) * static_cast(M_SQRT1_2); - // Stereo rear channel is steered with the same AGC steering as - // the decoding matrix. Note this requires a fast updating AGC - // at the order of 20 ms (which is the case here). - _lr[kr] *= (_l_fwr + _l_fwr) / (1 + _l_fwr + _r_fwr); - _rr[kr] *= (_r_fwr + _r_fwr) / (1 + _l_fwr + _r_fwr); - } - - /*** AXIS NO. 2: (Lt + Rt, Lt - Rt) -> (L, R) ***/ - lpr = (in[il] + in[ir]) * static_cast(M_SQRT1_2); - lmr = (in[il] - in[ir]) * static_cast(M_SQRT1_2); - /* AGC adaption */ - d_gain = fabs(lmr_unlim_gain - *_adapt_lmr_gain); - f = d_gain * (1.0f / MATAGCTRIG); - f = MATAGCDECAY - MATAGCDECAY / (1 + f * f); - *_adapt_lpr_gain = (1 - f) * *_adapt_lpr_gain + f * lpr_gain; - *_adapt_lmr_gain = (1 - f) * *_adapt_lmr_gain + f * lmr_gain; - /* Matrix */ - lpr_agc = lpr * PassiveLock(*_adapt_lpr_gain); - lmr_agc = lmr * PassiveLock(*_adapt_lmr_gain); - _lf[k] = (lpr_agc + lmr_agc) * static_cast(M_SQRT1_2); - _rf[k] = (lpr_agc - lmr_agc) * static_cast(M_SQRT1_2); - - /*** CENTER FRONT CANCELLATION ***/ - // A heuristic approach exploits that Lt + Rt gain contains the - // information about Lt, Rt correlation. This effectively reshapes - // the front and rear "cones" to concentrate Lt + Rt to C and - // introduce Lt - Rt in L, R. - /* 0.67677 is the empirical lower bound for lpr_gain. */ - c_gain = 8 * (*_adapt_lpr_gain - 0.67677f); - c_gain = c_gain > 0 ? c_gain : 0; - // c_gain should not be too high, not even reaching full - // cancellation (~ 0.50 - 0.55 at current AGC implementation), or - // the center will sound too narrow. */ - c_gain = MATCOMPGAIN / (1 + c_gain * c_gain); - c_agc_cfk = c_gain * _cf[k]; - _lf[k] -= c_agc_cfk; - _rf[k] -= c_agc_cfk; - _cf[k] += c_agc_cfk + c_agc_cfk; -} - -void DPL2Decode(float* samples, int numsamples, float* out) -{ - static const unsigned int FWRDURATION = 240; // FWR average duration (samples) - static const int cfg_delay = 0; - static const unsigned int fmt_freq = 48000; - static const unsigned int fmt_nchannels = 2; // input channels - - int cur = 0; - - if (olddelay != cfg_delay || oldfreq != fmt_freq) - { - Done(); - olddelay = cfg_delay; - oldfreq = fmt_freq; - dlbuflen = std::max(FWRDURATION, (fmt_freq * cfg_delay / 1000)); //+(len7000-1); - cyc_pos = dlbuflen - 1; - fwrbuf_l.resize(dlbuflen); - fwrbuf_r.resize(dlbuflen); - lf.resize(dlbuflen); - rf.resize(dlbuflen); - lr.resize(dlbuflen); - rr.resize(dlbuflen); - cf.resize(dlbuflen); - cr.resize(dlbuflen); - filter_coefs_lfe = CalculateCoefficients125HzLowpass(fmt_freq); - lfe_pos = 0; - memset(LFE_buf, 0, sizeof(LFE_buf)); - } - - float* in = samples; // Input audio data - float* end = in + numsamples * fmt_nchannels; // Loop end - - while (in < end) - { - const int k = cyc_pos; - - const int fwr_pos = (k + FWRDURATION) % dlbuflen; - /* Update the full wave rectified total amplitude */ - /* Input matrix decoder */ - l_fwr += fabs(in[0]) - fabs(fwrbuf_l[fwr_pos]); - r_fwr += fabs(in[1]) - fabs(fwrbuf_r[fwr_pos]); - lpr_fwr += fabs(in[0] + in[1]) - fabs(fwrbuf_l[fwr_pos] + fwrbuf_r[fwr_pos]); - lmr_fwr += fabs(in[0] - in[1]) - fabs(fwrbuf_l[fwr_pos] - fwrbuf_r[fwr_pos]); - - /* Matrix encoded 2 channel sources */ - fwrbuf_l[k] = in[0]; - fwrbuf_r[k] = in[1]; - MatrixDecode(in, k, 0, 1, true, dlbuflen, l_fwr, r_fwr, lpr_fwr, lmr_fwr, &adapt_l_gain, - &adapt_r_gain, &adapt_lpr_gain, &adapt_lmr_gain, &lf[0], &rf[0], &lr[0], &rr[0], - &cf[0]); - - out[cur + 0] = lf[k]; - out[cur + 1] = rf[k]; - out[cur + 2] = cf[k]; - LFE_buf[lfe_pos] = (lf[k] + rf[k] + 2.0f * cf[k] + lr[k] + rr[k]) / 2.0f; - out[cur + 3] = FIRFilter(LFE_buf, lfe_pos, len125, len125, filter_coefs_lfe); - lfe_pos++; - if (lfe_pos == len125) - { - lfe_pos = 0; - } - out[cur + 4] = lr[k]; - out[cur + 5] = rr[k]; - // Next sample... - in += 2; - cur += 6; - cyc_pos--; - if (cyc_pos < 0) - { - cyc_pos += dlbuflen; - } - } -} - -void DPL2Reset() -{ - olddelay = -1; - oldfreq = 0; - filter_coefs_lfe.clear(); -} diff --git a/Source/Core/AudioCommon/DPL2Decoder.h b/Source/Core/AudioCommon/DPL2Decoder.h deleted file mode 100644 index 7e5678d8f2..0000000000 --- a/Source/Core/AudioCommon/DPL2Decoder.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -void DPL2Decode(float* samples, int numsamples, float* out); -void DPL2Reset(); diff --git a/Source/Core/AudioCommon/Mixer.cpp b/Source/Core/AudioCommon/Mixer.cpp index da0f81c87e..7620ba5cec 100644 --- a/Source/Core/AudioCommon/Mixer.cpp +++ b/Source/Core/AudioCommon/Mixer.cpp @@ -7,7 +7,6 @@ #include #include -#include "AudioCommon/DPL2Decoder.h" #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" @@ -16,10 +15,10 @@ #include "Core/ConfigManager.h" Mixer::Mixer(unsigned int BackendSampleRate) - : m_sampleRate(BackendSampleRate), m_stretcher(BackendSampleRate) + : m_sampleRate(BackendSampleRate), m_stretcher(BackendSampleRate), + m_surround_decoder(BackendSampleRate, SURROUND_BLOCK_SIZE) { INFO_LOG(AUDIO_INTERFACE, "Mixer is initialized"); - DPL2Reset(); } Mixer::~Mixer() @@ -167,20 +166,23 @@ unsigned int Mixer::MixSurround(float* samples, unsigned int num_samples) if (!num_samples) return 0; - memset(samples, 0, num_samples * 6 * sizeof(float)); + memset(samples, 0, num_samples * SURROUND_CHANNELS * sizeof(float)); - // Mix() may also use m_scratch_buffer internally, but is safe because it alternates reads and - // writes. - unsigned int available_samples = Mix(m_scratch_buffer.data(), num_samples); - for (size_t i = 0; i < static_cast(available_samples) * 2; ++i) + size_t needed_frames = m_surround_decoder.QueryFramesNeededForSurroundOutput(num_samples); + + // Mix() may also use m_scratch_buffer internally, but is safe because it alternates reads + // and writes. + size_t available_frames = Mix(m_scratch_buffer.data(), static_cast(needed_frames)); + if (available_frames != needed_frames) { - m_float_conversion_buffer[i] = - m_scratch_buffer[i] / static_cast(std::numeric_limits::max()); + ERROR_LOG(AUDIO, "Error decoding surround frames."); + return 0; } - DPL2Decode(m_float_conversion_buffer.data(), available_samples, samples); + m_surround_decoder.PutFrames(m_scratch_buffer.data(), needed_frames); + m_surround_decoder.ReceiveFrames(samples, num_samples); - return available_samples; + return num_samples; } void Mixer::MixerFifo::PushSamples(const short* samples, unsigned int num_samples) diff --git a/Source/Core/AudioCommon/Mixer.h b/Source/Core/AudioCommon/Mixer.h index e2545d6be1..83a13cf5d6 100644 --- a/Source/Core/AudioCommon/Mixer.h +++ b/Source/Core/AudioCommon/Mixer.h @@ -8,6 +8,7 @@ #include #include "AudioCommon/AudioStretcher.h" +#include "AudioCommon/SurroundDecoder.h" #include "AudioCommon/WaveFile.h" #include "Common/CommonTypes.h" @@ -52,6 +53,9 @@ private: static constexpr float CONTROL_FACTOR = 0.2f; static constexpr u32 CONTROL_AVG = 32; // In freq_shift per FIFO size offset + const unsigned int SURROUND_CHANNELS = 6; + const unsigned int SURROUND_BLOCK_SIZE = 512; + class MixerFifo final { public: @@ -86,8 +90,8 @@ private: bool m_is_stretching = false; AudioCommon::AudioStretcher m_stretcher; + AudioCommon::SurroundDecoder m_surround_decoder; std::array m_scratch_buffer; - std::array m_float_conversion_buffer; WaveFileWriter m_wave_writer_dtk; WaveFileWriter m_wave_writer_dsp; diff --git a/Source/Core/AudioCommon/OpenALStream.cpp b/Source/Core/AudioCommon/OpenALStream.cpp index cb1281a88e..4852495d23 100644 --- a/Source/Core/AudioCommon/OpenALStream.cpp +++ b/Source/Core/AudioCommon/OpenALStream.cpp @@ -246,12 +246,6 @@ void OpenALStream::SoundLoop() frames_per_buffer = OAL_MAX_FRAMES; } - // DPL2 needs a minimum number of samples to work (FWRDURATION) - if (use_surround && frames_per_buffer < 240) - { - frames_per_buffer = 240; - } - INFO_LOG(AUDIO, "Using %d buffers, each with %d audio frames for a total of %d.", OAL_BUFFERS, frames_per_buffer, frames_per_buffer * OAL_BUFFERS); @@ -312,15 +306,6 @@ void OpenALStream::SoundLoop() if (rendered_frames < min_frames) continue; - // zero-out the subwoofer channel - DPL2Decode generates a pretty - // good 5.0 but not a good 5.1 output. Sadly there is not a 5.0 - // AL_FORMAT_50CHN32 to make this super-explicit. - // DPL2Decode output: LEFTFRONT, RIGHTFRONT, CENTREFRONT, (sub), LEFTREAR, RIGHTREAR - for (u32 i = 0; i < rendered_frames; ++i) - { - dpl2[i * SURROUND_CHANNELS + 3 /*sub/lfe*/] = 0.0f; - } - if (float32_capable) { palBufferData(m_buffers[next_buffer], AL_FORMAT_51CHN32, dpl2.data(), @@ -332,14 +317,11 @@ void OpenALStream::SoundLoop() for (u32 i = 0; i < rendered_frames * SURROUND_CHANNELS; ++i) { - // For some reason the ffdshow's DPL2 decoder outputs samples bigger than 1. - // Most are close to 2.5 and some go up to 8. Hard clamping here, we need to - // fix the decoder or implement a limiter. - dpl2[i] = dpl2[i] * (INT64_C(1) << 31); - if (dpl2[i] > INT_MAX) - surround_int32[i] = INT_MAX; - else if (dpl2[i] < INT_MIN) - surround_int32[i] = INT_MIN; + dpl2[i] = dpl2[i] * std::numeric_limits::max(); + if (dpl2[i] > std::numeric_limits::max()) + surround_int32[i] = std::numeric_limits::max(); + else if (dpl2[i] < std::numeric_limits::min()) + surround_int32[i] = std::numeric_limits::min(); else surround_int32[i] = static_cast(dpl2[i]); } @@ -353,13 +335,13 @@ void OpenALStream::SoundLoop() for (u32 i = 0; i < rendered_frames * SURROUND_CHANNELS; ++i) { - dpl2[i] = dpl2[i] * (1 << 15); - if (dpl2[i] > SHRT_MAX) - surround_short[i] = SHRT_MAX; - else if (dpl2[i] < SHRT_MIN) - surround_short[i] = SHRT_MIN; + dpl2[i] = dpl2[i] * std::numeric_limits::max(); + if (dpl2[i] > std::numeric_limits::max()) + surround_short[i] = std::numeric_limits::max(); + else if (dpl2[i] < std::numeric_limits::min()) + surround_short[i] = std::numeric_limits::min(); else - surround_short[i] = static_cast(dpl2[i]); + surround_short[i] = static_cast(dpl2[i]); } palBufferData(m_buffers[next_buffer], AL_FORMAT_51CHN16, surround_short.data(), diff --git a/Source/Core/AudioCommon/PulseAudioStream.cpp b/Source/Core/AudioCommon/PulseAudioStream.cpp index e8d5090b25..05d08b1603 100644 --- a/Source/Core/AudioCommon/PulseAudioStream.cpp +++ b/Source/Core/AudioCommon/PulseAudioStream.cpp @@ -22,7 +22,7 @@ PulseAudio::PulseAudio() : m_thread(), m_run_thread() bool PulseAudio::Init() { m_stereo = !SConfig::GetInstance().bDPL2Decoder; - m_channels = m_stereo ? 2 : 5; // will tell PA we use a Stereo or 5.0 channel setup + m_channels = m_stereo ? 2 : 6; // will tell PA we use a Stereo or 5.0 channel setup NOTICE_LOG(AUDIO, "PulseAudio backend using %d channels", m_channels); @@ -96,12 +96,13 @@ bool PulseAudio::PulseInit() m_bytespersample = sizeof(float); channel_map_p = &channel_map; // explicit channel map: - channel_map.channels = 5; + channel_map.channels = 6; channel_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; channel_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; channel_map.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER; - channel_map.map[3] = PA_CHANNEL_POSITION_REAR_LEFT; - channel_map.map[4] = PA_CHANNEL_POSITION_REAR_RIGHT; + channel_map.map[3] = PA_CHANNEL_POSITION_LFE; + channel_map.map[4] = PA_CHANNEL_POSITION_REAR_LEFT; + channel_map.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT; } ss.channels = m_channels; ss.rate = m_mixer->GetSampleRate(); @@ -185,22 +186,9 @@ void PulseAudio::WriteCallback(pa_stream* s, size_t length) } else { - if (m_channels == 5) // Extract dpl2/5.0 Surround + if (m_channels == 6) // Extract dpl2/5.1 Surround { - float floatbuffer_6chan[frames * 6]; - m_mixer->MixSurround(floatbuffer_6chan, frames); - - // DPL2Decode output: LEFTFRONT, RIGHTFRONT, CENTREFRONT, (sub), LEFTREAR, RIGHTREAR - // Discard the subwoofer channel - DPL2Decode generates a pretty - // good 5.0 but not a good 5.1 output. - const int dpl2_to_5chan[] = {0, 1, 2, 4, 5}; - for (int i = 0; i < frames; ++i) - { - for (int j = 0; j < m_channels; ++j) - { - ((float*)buffer)[m_channels * i + j] = floatbuffer_6chan[6 * i + dpl2_to_5chan[j]]; - } - } + m_mixer->MixSurround((float*)buffer, frames); } else { diff --git a/Source/Core/AudioCommon/SurroundDecoder.cpp b/Source/Core/AudioCommon/SurroundDecoder.cpp new file mode 100644 index 0000000000..8ded0ca5e8 --- /dev/null +++ b/Source/Core/AudioCommon/SurroundDecoder.cpp @@ -0,0 +1,93 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include + +#include "AudioCommon/SurroundDecoder.h" + +namespace AudioCommon +{ +constexpr size_t STEREO_CHANNELS = 2; +constexpr size_t SURROUND_CHANNELS = 6; + +SurroundDecoder::SurroundDecoder(u32 sample_rate, u32 frame_block_size) + : m_sample_rate(sample_rate), m_frame_block_size(frame_block_size) +{ + m_fsdecoder = std::make_unique(); + m_fsdecoder->Init(cs_5point1, m_frame_block_size, m_sample_rate); +} + +SurroundDecoder::~SurroundDecoder() = default; + +void SurroundDecoder::Clear() +{ + m_fsdecoder->flush(); + m_decoded_fifo.clear(); +} + +// Currently only 6 channels are supported. +size_t SurroundDecoder::QueryFramesNeededForSurroundOutput(const size_t output_frames) const +{ + if (m_decoded_fifo.size() < output_frames * SURROUND_CHANNELS) + { + // Output stereo frames needed to have at least the desired number of surround frames + size_t frames_needed = output_frames - m_decoded_fifo.size() / SURROUND_CHANNELS; + return frames_needed + m_frame_block_size - frames_needed % m_frame_block_size; + } + + return 0; +} + +// Receive and decode samples +void SurroundDecoder::PutFrames(const short* in, const size_t num_frames_in) +{ + // Maybe check if it is really power-of-2? + s64 remaining_frames = static_cast(num_frames_in); + size_t frame_index = 0; + + while (remaining_frames > 0) + { + // Convert to float + for (size_t i = 0, end = m_frame_block_size * STEREO_CHANNELS; i < end; ++i) + { + m_float_conversion_buffer[i] = in[i + frame_index * STEREO_CHANNELS] / + static_cast(std::numeric_limits::max()); + } + + // Decode + const float* dpl2_fs = m_fsdecoder->decode(m_float_conversion_buffer.data()); + + // Add to ring buffer and fix channel mapping + // Maybe modify FreeSurround to output the correct mapping? + // FreeSurround: + // FL | FC | FR | BL | BR | LFE + // Most backends: + // FL | FR | FC | LFE | BL | BR + for (size_t i = 0; i < m_frame_block_size; ++i) + { + m_decoded_fifo.push(dpl2_fs[i * SURROUND_CHANNELS + 0]); // LEFTFRONT + m_decoded_fifo.push(dpl2_fs[i * SURROUND_CHANNELS + 2]); // RIGHTFRONT + m_decoded_fifo.push(dpl2_fs[i * SURROUND_CHANNELS + 1]); // CENTREFRONT + m_decoded_fifo.push(dpl2_fs[i * SURROUND_CHANNELS + 5]); // sub/lfe + m_decoded_fifo.push(dpl2_fs[i * SURROUND_CHANNELS + 3]); // LEFTREAR + m_decoded_fifo.push(dpl2_fs[i * SURROUND_CHANNELS + 4]); // RIGHTREAR + } + + remaining_frames = remaining_frames - static_cast(m_frame_block_size); + frame_index = frame_index + m_frame_block_size; + } +} + +void SurroundDecoder::ReceiveFrames(float* out, const size_t num_frames_out) +{ + // Copy to output array with desired num_frames_out + for (size_t i = 0, num_samples_output = num_frames_out * SURROUND_CHANNELS; + i < num_samples_output; ++i) + { + out[i] = m_decoded_fifo.pop_front(); + } +} + +} // namespace AudioCommon diff --git a/Source/Core/AudioCommon/SurroundDecoder.h b/Source/Core/AudioCommon/SurroundDecoder.h new file mode 100644 index 0000000000..699be74278 --- /dev/null +++ b/Source/Core/AudioCommon/SurroundDecoder.h @@ -0,0 +1,36 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "Common/CommonTypes.h" +#include "Common/FixedSizeQueue.h" + +class DPL2FSDecoder; + +namespace AudioCommon +{ +class SurroundDecoder +{ +public: + explicit SurroundDecoder(u32 sample_rate, u32 frame_block_size); + ~SurroundDecoder(); + size_t QueryFramesNeededForSurroundOutput(const size_t output_frames) const; + void PutFrames(const short* in, const size_t num_frames_in); + void ReceiveFrames(float* out, const size_t num_frames_out); + void Clear(); + +private: + u32 m_sample_rate; + u32 m_frame_block_size; + + std::unique_ptr m_fsdecoder; + std::array m_float_conversion_buffer; + FixedSizeQueue m_decoded_fifo; +}; + +} // AudioCommon diff --git a/Source/VSProps/Base.props b/Source/VSProps/Base.props index d8789142f8..a247cce115 100644 --- a/Source/VSProps/Base.props +++ b/Source/VSProps/Base.props @@ -36,6 +36,7 @@ $(ExternalsDir);%(AdditionalIncludeDirectories) $(ExternalsDir)Bochs_disasm;%(AdditionalIncludeDirectories) $(ExternalsDir)cpp-optparse;%(AdditionalIncludeDirectories) + $(ExternalsDir)FreeSurround\include;%(AdditionalIncludeDirectories) $(ExternalsDir)cubeb\include;$(ExternalsDir)cubeb\msvc;%(AdditionalIncludeDirectories) $(ExternalsDir)curl\include;%(AdditionalIncludeDirectories) $(ExternalsDir)enet\include;%(AdditionalIncludeDirectories) diff --git a/Source/dolphin-emu.sln b/Source/dolphin-emu.sln index 4afe24b435..daf796987d 100644 --- a/Source/dolphin-emu.sln +++ b/Source/dolphin-emu.sln @@ -83,6 +83,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ed25519", "..\externals\ed2 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Updater", "Core\Updater\Updater.vcxproj", "{E4BECBAB-9C6E-41AB-BB56-F9D70AB6BE03}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSurround", "..\Externals\FreeSurround\FreeSurround.vcxproj", "{8498F2FA-5CA6-4169-9971-DE5B1FE6132C}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "discord-rpc", "..\Externals\discord-rpc\src\discord-rpc.vcxproj", "{4482FD2A-EC43-3FFB-AC20-2E5C54B05EAD}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "..\Externals\minizip\minizip.vcxproj", "{23114507-079A-4418-9707-CFA81A03CA99}" @@ -247,6 +249,10 @@ Global {E4BECBAB-9C6E-41AB-BB56-F9D70AB6BE03}.Debug|x64.Build.0 = Debug|x64 {E4BECBAB-9C6E-41AB-BB56-F9D70AB6BE03}.Release|x64.ActiveCfg = Release|x64 {E4BECBAB-9C6E-41AB-BB56-F9D70AB6BE03}.Release|x64.Build.0 = Release|x64 + {8498F2FA-5CA6-4169-9971-DE5B1FE6132C}.Debug|x64.ActiveCfg = Debug|x64 + {8498F2FA-5CA6-4169-9971-DE5B1FE6132C}.Debug|x64.Build.0 = Debug|x64 + {8498F2FA-5CA6-4169-9971-DE5B1FE6132C}.Release|x64.ActiveCfg = Release|x64 + {8498F2FA-5CA6-4169-9971-DE5B1FE6132C}.Release|x64.Build.0 = Release|x64 {4482FD2A-EC43-3FFB-AC20-2E5C54B05EAD}.Debug|x64.ActiveCfg = Debug|x64 {4482FD2A-EC43-3FFB-AC20-2E5C54B05EAD}.Debug|x64.Build.0 = Debug|x64 {4482FD2A-EC43-3FFB-AC20-2E5C54B05EAD}.Release|x64.ActiveCfg = Release|x64 @@ -296,6 +302,7 @@ Global {38FEE76F-F347-484B-949C-B4649381CFFB} = {87ADDFF9-5768-4DA2-A33B-2477593D6677} {2C0D058E-DE35-4471-AD99-E68A2CAF9E18} = {87ADDFF9-5768-4DA2-A33B-2477593D6677} {5BDF4B91-1491-4FB0-BC27-78E9A8E97DC3} = {87ADDFF9-5768-4DA2-A33B-2477593D6677} + {8498F2FA-5CA6-4169-9971-DE5B1FE6132C} = {87ADDFF9-5768-4DA2-A33B-2477593D6677} {4482FD2A-EC43-3FFB-AC20-2E5C54B05EAD} = {87ADDFF9-5768-4DA2-A33B-2477593D6677} {23114507-079A-4418-9707-CFA81A03CA99} = {87ADDFF9-5768-4DA2-A33B-2477593D6677} {4C3B2264-EA73-4A7B-9CFE-65B0FD635EBB} = {87ADDFF9-5768-4DA2-A33B-2477593D6677}