Files
UnrealEngine/Engine/Source/Runtime/BinkAudioDecoder/SDK/BinkAudio/Src/radfft.h
2025-05-18 13:04:45 +08:00

136 lines
4.7 KiB
C

// Copyright Epic Games, Inc. All Rights Reserved.
#ifndef RADFFT_H
#define RADFFT_H
#include "egttypes.h"
#ifdef __RADCONSOLE__
#define RADFFT_ALIGN 32
#define RADFFT_AVX // We know it's always there, might as well use it!
#else
#define RADFFT_ALIGN 16
#endif
#ifdef WRAP_PUBLICS
#define rfmerge3(name,add) name##add
#define rfmerge2(name,add) rfmerge3(name,add)
#define rfmerge(name) rfmerge2(name,WRAP_PUBLICS)
#define radfft_init rfmerge(radfft_init)
#define radfft_cfft rfmerge(radfft_cfft)
#define radfft_cifft rfmerge(radfft_cifft)
#define radfft_rfft rfmerge(radfft_rfft)
#define radfft_rifft rfmerge(radfft_rifft)
#define radfft_dct rfmerge(radfft_dct)
#define radfft_idct rfmerge(radfft_idct)
#define radfft_idct_to_S16 rfmerge(radfft_idct_to_S16)
#define radfft_idct_to_S16_stereo_interleave rfmerge(radfft_idct_to_S16_stereo_interleave)
#endif
// Complex numbers are returned in this form
typedef struct rfft_complex
{
F32 re; // real part
F32 im; // imaginary part
} rfft_complex;
// Initialize. Call this first!
RADDEFFUNC void RADLINK radfft_init();
// Complex FFT. Computes
// out[k] = sum_{j=0}^{N-1} in[k] * exp(-i*2*pi/N * (j*k))
//
// This is the typical FFT definition (negative sign in the exponential).
//
// N must be a power of 2, "in" and "out" must be aligned to
// RADFFT_ALIGN.
RADDEFFUNC void RADLINK radfft_cfft(rfft_complex out[], rfft_complex const in[], UINTa N);
// Complex IFFT. Computes
// out[k] = sum_{j=0}^{N-1} in[k] * exp(i*2*pi/N * (j*k))
//
// This is the typical IFFT definition (positive sign in the exponential).
//
// cifft(fft(x)) = x * N
//
// N must be a power of 2, "in" and "out" must be aligned to
// RADFFT_ALIGN.
RADDEFFUNC void RADLINK radfft_cifft(rfft_complex out[], rfft_complex const in[], UINTa N);
// Real FFT of N elements in[0..N-1].
// This computes (except for out[0] and out[N/2], see below!)
// out[k] = sum_{j=0}^{N-1} in[j] * exp(i*2*pi/N * (j*k))
//
// Engineers often use the opposite sign convention (-i instead of i in the
// "exp"), and so does the "cfft" in here (sorry). We use this convention
// here because the code this replaced used it.
//
// Returns the first half of the N complex FFT coeffs in out[0..N/2-1].
// The DC bin out[0] is always real for a real FFT.
// We use the imaginary part of out[0] to hold the (also always real) Nyquist bin
// that would otherwise be in out[N/2].
//
// N must be a power of 2, "in" and "out" must be aligned to
// RADFFT_ALIGN.
RADDEFFUNC void RADLINK radfft_rfft(rfft_complex out[], F32 const in[], UINTa N);
// Real IFFT matching "radfft_rfft".
// This computes
// out[k] = (1/2) * sum_{j=0}^{N-1} in'[j] * exp(-i*2*pi/N * (j*k))
// where
// in'[0] = real(in[0])
// in'[N/2] = imag(in[0])
// in'[k] = in[k], 1 <= k < N/2
// in'[N-k] = conj(in[k]), 1 <= k < N/2
//
// i.e. "in'" is "in" expanded from N/2 to N values with conjugate (Hermitian)
// symmetry (whew). Same comment as for "rfft" applies: this is the opposite
// exponent sign convention from what's typical in engineering, but it matches
// the code we're replacing.
//
// With these rules, we have
// rifft(rfft(x)) == (N/2) * x
//
// N must be a power of 2, "in" and "out" must be aligned to
// RADFFT_ALIGN.
RADDEFFUNC void RADLINK radfft_rifft(F32 out[], rfft_complex in[], UINTa N);
// DCT-II
//
// Computes the type-II discrete cosine transform ("the" DCT) of "in":
// out[k] = sum_{j=0}^{N-1} in[j] * cos(pi/N * (j+0.5)*k)
//
// Input data is in in[0..N-1]; output is written to out[0..N-1].
// The input data is destroyed.
//
// N must be a power of 2, "in" and "out" must be aligned to
// RADFFT_ALIGN.
RADDEFFUNC void RADLINK radfft_dct(F32 out[], F32 in[], UINTa N);
// DCT-III
//
// Computes the type-III discrete cosine transform ("the" inverse DCT) of "in":
// out[k] = sum_{j=0}^{N-1} in[j] * cos(pi/N * j*(k+0.5))
//
// Input data is in in[0..N-1]; output is written to out[0..N-1].
// The input data is destroyed.
//
// Note that this is using the standard normalization which means it's only
// *almost* an inverse of "dct"; to be precise, the inverse of
//
// dct(data, work, N)
//
// is
//
// data[0] *= 0.5f;
// idct(data, work, N);
// // scale data by 2/N
//
// N must be a power of 2, "in" and "out" must be aligned to
// RADFFT_ALIGN.
RADDEFFUNC void RADLINK radfft_idct(F32 out[], F32 in[], UINTa N);
RADDEFFUNC void RADLINK radfft_idct_to_S16(S16 outs16[], F32 scale, F32 tmp[], F32 in[], UINTa N);
RADDEFFUNC void RADLINK radfft_idct_to_S16_stereo_interleave(S16 outs16[], S16 left[], F32 scale, F32 tmp[], F32 in[], UINTa N);
#endif