mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 16:19:28 +01:00
7b9375875c
Also cleaned up its source code to support only 5.1 and 7.1 setups.
203 lines
8.4 KiB
C
203 lines
8.4 KiB
C
/*
|
|
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 <limits.h>
|
|
|
|
#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 <alloca.h>
|
|
#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
|