home *** CD-ROM | disk | FTP | other *** search
- /*
- **
- ** FastFFT.cpp
- **
- ** $VER: FastFFT.cpp 1.0 (11.07.98)
- **
- ** Calcul de la transformée de Fourier rapide
- **
- ** $Revision: 1.4 $
- ** $State: Exp $
- ** $Date: 1998/08/16 19:03:44 $
- **
- ** $Log: FastFFTC.cpp $
- ** Revision 1.4 1998/08/16 19:03:44 kakace
- ** Version Beta3+
- **
- ** Revision 1.3 1998/08/09 19:21:36 kakace
- ** Correction d'un bug dans la routine FFT (avec tableà
- **
- ** Revision 1.2 1998/08/02 15:17:10 kakace
- ** Fonctionnement OK (Layer 1/2 + Stereo/JStereo)
- **
- */
-
-
- #ifndef _INCLUDE_MATH_H
- #include <math.h>
- #endif
-
- #ifndef _MEMORY_HPP
- #include "Memory.hpp"
- #endif
-
- #ifndef _FASTFFT_CLASS_HPP
- #include "FastFFTC.hpp"
- #endif
-
- #ifndef _PEGASECOND_HPP
- #include "PegaseCond.hpp"
- #endif
-
-
- //----------------------------------------------------------------------------------------------------
-
- // Fonctions "inline"
-
- /// FastFFTC::GetShuffleIndex_?()
- /****** Class FastFFTC/GetShuffleIndex_10 ***********************************
- *
- * NAME
- * FastFFTC::GetShuffleIndex_10 -- Obtenir un index sur 10 bits.
- * FastFFTC::GetShuffleIndex_8 -- Obtenir un index sur 8 bits.
- *
- * SYNOPSIS
- * Index = FastFFTC::GetShuffleIndex_10(input)
- * Index = FastFFTC::GetShuffleIndex_8(input)
- *
- * inline ULONG FastFFTC::GetShuffleIndex_10(ULONG);
- * inline ULONG FastFFTC::GetShuffleIndex_8(ULONG);
- *
- * FUNCTION
- * Retourne la valeur transmise en argument après avoir inversé le champs
- * binaire (bitreverse). La longueur du champs de bits doit correspondre à
- * longueur indiquée dans le nom de la fonction.
- *
- * INPUTS
- * input - Valeur à traiter.
- *
- * RESULT
- * Index - Index obtenu après inversion du masque binaire.
- *
- *****************************************************************************
- *
- */
-
-
- static UBYTE ShuffleArray[] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
-
- inline ULONG FastFFTC::GetShuffleIndex_10(ULONG input)
- {
- ULONG k;
- ULONG bitrev = 0;
-
- for (k = 0; k < 3; k++)
- {
- bitrev = (bitrev * 16) | (::ShuffleArray[input & 15]);
- input >>= 4;
- }
-
- return (bitrev >> 2);
- }
-
-
- inline ULONG FastFFTC::GetShuffleIndex_8(ULONG input)
- {
- return ( (::ShuffleArray[input & 15] * 16) | (::ShuffleArray[input >> 4]) );
- }
- ///
-
- // Constructeur et destructeur.
-
- /// FastFFTC::FastFFTC
- FastFFTC::FastFFTC()
- {
- int i;
-
- #if _USE_SINCOS_TABLE_ == 1
-
- // Initialiser la table SinCos (68020/68030)
-
- REAL cos_alpha;
- REAL f = - (PI / 512.0);
-
- for (i = 0; i < SINCOSSIZE / 3; i++)
- {
- cos_alpha = cos(f * i);
- FFT_dSinCos[i] = cos_alpha;
- FFT_dSinCos[SINCOSSIZE * 2 / 3 - i] = - cos_alpha;
- FFT_dSinCos[SINCOSSIZE * 2 / 3 + i] = - cos_alpha;
- }
-
- FFT_dSinCos[SINCOSSIZE / 3] = 0;
-
- #else
-
- // Initialiser la table SinCos réduite (68040/68060)
-
- REAL f = - (PI / 512.0);
-
- for (i = 9; i >= 0; i--)
- {
- FFT_dSinCos[0][i] = cos(f);
- FFT_dSinCos[1][i] = sin(f);
- f += f;
- }
-
- #endif
-
- FFT_MemoryError = FALSE;
-
- FFT_MemoryError |= !(FFT_pdWinSmplShuffled = (T_FFTBUFF *) AllocAlignedBuffer(sizeof(T_FFTBUFF)));
- FFT_MemoryError |= !(FFT_pdHannWindowShuffled = (T_HANN *) AllocAlignedBuffer(sizeof(T_HANN)));
-
- // Initialiser la table HannWindow.
- // Cette table est réordonnée pour faciliter l'initialisation des tampons d'entrée
- // des FFTs.
-
- {
- REAL cos_alpha, sin_alpha;
- REAL cos_delta, sin_delta;
- REAL f;
-
- f = - (PI / 1024.0);
- cos_alpha = cos(f);
- sin_alpha = sin(f);
-
- f = cos_alpha + cos_alpha; // = 2.cos(a)
- cos_delta = f * cos_alpha - 1.0; // cos(2a) = 2.cos²(a) - 1
- sin_delta = - f * sin_alpha; // sin(2a) = 2.sin(a).cos(a)
-
- for (i = 0; i < BLKSIZE; i++)
- {
- f = 0.5 * (1.0 - cos_alpha);
- (*FFT_pdHannWindowShuffled)[GetShuffleIndex_10(i)] = f;
-
- f = cos_alpha;
- cos_alpha = f * cos_delta - sin_alpha * sin_delta;
- sin_alpha = f * sin_delta + sin_alpha * cos_delta;
- }
- }
- }
- ///
- /// FastFFTC::~FastFFTC()
- FastFFTC::~FastFFTC()
- {
- if (FFT_pdWinSmplShuffled) FreeAlignedBuffer(FFT_pdWinSmplShuffled);
- if (FFT_pdHannWindowShuffled) FreeAlignedBuffer(FFT_pdHannWindowShuffled);
- }
- ///
-
- // Fonctions privées.
-
- /// FastFFTC::FastFFT()
- /****** Class FastFFTC/FastFFT **********************************************
- *
- * NAME
- * FastFFTC::FastFFT -- Calculer la transformée de Fourier.
- *
- * SYNOPSIS
- * FastFFTC::FastFFT(pdFFTIn, iFFTSize)
- *
- * void FastFFTC::FastFFT(REAL *, UWORD);
- *
- * FUNCTION
- * Calcule la transformée de Fourier sur un ensemble d'échantillons.
- *
- * INPUTS
- * pdFFTIn - Tableau contenant les échantillons (série de nombres complexes
- * dans l'ordre : [partie réelle][partie imaginaire].
- * iFFTSize - Nombre d'échantillons à traiter.
- *
- * NOTES
- * Cette fonction a été fortement optimisée en tirant partie de quelques
- * angles particuliers. Elle est capable de calculer une FFT sur un ensemble
- * de 1024 échantillons au maximum.
- *
- * BUGS
- * Fonction contrôlée conforme le 20.06.98
- *
- * SEE ALSO
- * FastFFTC::ComputeFastFFT_Stereo()
- *
- *****************************************************************************
- *
- * Benchmark (3148 cycles par seconde (global)) :
- * 21.06.98 : 1'45.53
- *
- * 06.07.98 :
- * - Utilisation d'une table SinCos[] en lieu et place des calculs
- * trigonométriques (si _USE_SINCOS_TABLE_ == 1).
- */
-
- #if _USE_ASM_FCT_ == 0
-
- void FastFFTC::FastFFT(T_FFTDATAS *pdFFTIn, UWORD iFFTSize)
- {
- #define MAX_FFT_BLOCK 256
-
- ULONG i, j, delta;
- LONG k;
- ULONG BlockSize, BlockEnd, n;
- ULONG iBandSize = (iFFTSize < MAX_FFT_BLOCK) ? iFFTSize : MAX_FFT_BLOCK;
-
- double tr, ti;
- T_FFTDATAS *pd_J, *pd_K, *pd_J2, *pd_K2;
-
- #if _USE_SINCOS_TABLE_ == 1
- ULONG step;
- float *Cosin = &FFT_dSinCos[0];
- float *Sinus = &FFT_dSinCos[SINCOSSIZE / 3];
- #endif
-
- // Appliquer la FFT sur le tampon d'entrée.
- // Les passes 0 à 7 sont calculées ici, par colonnes de "iBandSize" échantillons
- // (pour tirer un meilleur parti des caches).
- // Les passes 8 et 9 sont quant à elles calculées à part.
-
- // On commence par la fin pour profiter du fait que le tampon d'entrée vient d'être
- // initialisé, et donc que les derniers échantillons sont toujours dans le cache.
-
- for (k = iFFTSize - iBandSize; k >= 0; k -= iBandSize)
- {
- BlockEnd = 1;
-
- #if _USE_SINCOS_TABLE_ == 0
- delta = 0;
- #else
- step = 512;
- #endif
-
- for (BlockSize = 2; BlockSize <= iBandSize; BlockSize += BlockSize)
- {
- #if _USE_SINCOS_TABLE_ == 1
- delta = 0;
- #endif
-
- n = BlockSize + BlockSize;
-
- pd_J = pd_J2 = &pdFFTIn[k + k];
- pd_K = pd_K2 = &pd_J2[BlockSize];
-
- // Première partie : ar = 1, ai = 0 (commune à toutes les passes)
-
- for (i = 0; i < iBandSize; i += BlockSize) // Boucle exécutée 1020 fois
- {
- tr = pd_K[0]; ti = pd_J[0];
- pd_K[0] = ti - tr;
- pd_J[0] = ti + tr;
-
- tr = pd_J[1]; ti = pd_K[1];
- pd_K[1] = tr - ti;
- pd_J[1] = tr + ti;
-
- pd_K = &pd_K[n]; // <==> pd_J += n
- pd_J = &pd_J[n]; // <==> pd_J += n
- }
- pd_J2 += 2;
- pd_K2 += 2;
-
- // Deuxième partie : ar et ai quelconques.
-
- if (BlockEnd > 4)
- {
- double ar, ai;
-
- #if _USE_SINCOS_TABLE_ == 0
- double cos_alpha, sin_alpha;
-
- ar = cos_alpha = FFT_dSinCos[0][delta]; // = cos(2.PI/BlockSize)
- ai = sin_alpha = FFT_dSinCos[1][delta]; // = sin(2.PI/BlockSize)
- #endif
-
- for (j = 1; j < BlockEnd; j++)
- {
- pd_J = pd_J2;
- pd_K = pd_K2;
-
- #if _USE_SINCOS_TABLE_ == 1
- delta += step;
- ar = Cosin[delta];
- ai = Sinus[delta];
- #endif
- for (i = 0; i < iBandSize; i += BlockSize)
- {
- ti = pd_K[0];
- tr = ar * ti - ai * pd_K[1];
- ti = ar * pd_K[1] + ai * ti;
-
- pd_K[0] = pd_J[0] - tr;
- pd_J[0] = pd_J[0] + tr;
-
- tr = pd_J[1];
- pd_K[1] = tr - ti;
- pd_J[1] = tr + ti;
-
- pd_K = &pd_K[n]; // <==> pd_J += n
- pd_J = &pd_J[n]; // <==> pd_J += n
- }
- pd_J2 += 2;
- pd_K2 += 2;
-
- #if _USE_SINCOS_TABLE_ == 0
- tr = ar;
- ar = ar * cos_alpha - ai * sin_alpha;
- ai = tr * sin_alpha + ai * cos_alpha;
- #endif
- }
- }
- else
- {
- // Troisième partie : ar = 0, ai = -1.
-
- pd_J = pd_J2;
- pd_K = pd_K2;
-
- if (BlockEnd == 2)
- {
- for (i = 0; i < iBandSize; i += 4)
- {
- double tz;
-
- ti = pd_K[1]; // ai = -1
- tr = pd_K[0]; // ar = 0
-
- tz = pd_J[0];
- pd_K[0] = tz - ti;
- pd_J[0] = tz + ti;
-
- tz = pd_J[1];
- pd_K[1] = tz + tr;
- pd_J[1] = tz - tr;
-
- pd_K += 8;
- pd_J += 8;
- }
- }
- // Quatrième partie : ar = {1; 0.707; 0; -0.707}, ai = {0; -0.707; -1; -0.707}
-
- if (BlockEnd == 4)
- {
- double ar, tz;
-
- #if _USE_SINCOS_TABLE_ == 0
- ar = FFT_dSinCos[0][delta]; // = cos(2.PI/8) = sqrt(2) / 2
- #else
- ar = Cosin[SINCOSSIZE / 6];
- #endif
-
- for (i = 0; i < iBandSize; i += 8)
- {
- ti = pd_K[0];
- tz = pd_K[1];
- tr = ar * (ti + tz); // ar = -ai = sqrt(2) / 2
- ti = ar * (tz - ti);
-
- tz = pd_J[0];
- pd_K[0] = tz - tr;
- pd_J[0] = tz + tr;
-
- tz = pd_J[1];
- pd_K[1] = tz - ti;
- pd_J[1] = tz + ti;
-
- tr = pd_K[2]; // ar = 0
- ti = pd_K[3]; // ai = -1
-
- tz = pd_J[2];
- pd_K[2] = tz - ti;
- pd_J[2] = tz + ti;
-
- tz = pd_J[3];
- pd_K[3] = tz + tr;
- pd_J[3] = tz - tr;
-
- ti = pd_K[4];
- tz = pd_K[5];
- tr = ar * (ti - tz); // ar = ai = - sqrt(2) / 2
- ti = ar * (tz + ti);
-
- tz = pd_J[4];
- pd_K[4] = tz + tr;
- pd_J[4] = tz - tr;
-
- tz = pd_J[5];
- pd_K[5] = tz + ti;
- pd_J[5] = tz - ti;
-
- pd_K += 16;
- pd_J += 16;
- }
- }
- }
-
- BlockEnd = BlockSize;
-
- #if _USE_SINCOS_TABLE_ == 0
- ++delta;
- #else
- step >>= 1;
- #endif
-
- }
- }
-
- // ================================================================
- // Dernière passe : BlockSize = 512, BlockEnd = 256 (passes 8 et 9)
- // ================================================================
-
- for ( ; BlockSize <= iFFTSize; BlockSize += BlockSize)
- {
- #if _USE_SINCOS_TABLE_ == 0
- double cos_alpha, sin_alpha, ar, ai;
-
- cos_alpha = FFT_dSinCos[0][delta];
- sin_alpha = FFT_dSinCos[1][delta];
- #else
- double ar, ai;
- delta = 0;
- #endif
-
- pd_J = &pdFFTIn[0];
- pd_K = &pdFFTIn[BlockSize];
-
- ar = 1.0;
- ai = 0.0;
-
- for (j = 0; j < BlockEnd; j++)
- {
- if (BlockEnd == 256 && iFFTSize == 1024)
- {
- ti = pd_K[1024];
- tr = ar * ti - ai * pd_K[1025];
- ti = ar * pd_K[1025] + ai * ti;
-
- pd_K[1025] = pd_J[1025] - ti;
- pd_J[1025] = pd_J[1025] + ti;
-
- ti = pd_J[1024];
- pd_K[1024] = ti - tr;
- pd_J[1024] = ti + tr;
- }
-
- ti = pd_K[0];
- tr = ar * ti - ai * pd_K[1];
- ti = ar * pd_K[1] + ai * ti;
-
- pd_K[0] = pd_J[0] - tr;
- pd_J[0] = pd_J[0] + tr;
-
- tr = pd_J[1];
- pd_K[1] = tr - ti;
- pd_J[1] = tr + ti;
-
- pd_J += 2; pd_K += 2;
-
- #if _USE_SINCOS_TABLE_ == 0
- tr = ar;
- ar = ar * cos_alpha - ai * sin_alpha;
- ai = tr * sin_alpha + ai * cos_alpha;
- #else
- delta += step;
- ar = Cosin[delta];
- ai = Sinus[delta];
- #endif
- }
-
- BlockEnd = BlockSize;
-
- #if _USE_SINCOS_TABLE_ == 0
- ++delta;
- #else
- step >>= 1;
- #endif
- }
- }
-
- #endif // _USE_ASM_FCT_
- ///
- /// FastFFTC::FixFFT_Stereo()
- /****** Class FastFFTC/FixFFT_Stereo ****************************************
- *
- * NAME
- * FastFFTC::FixFFT_Stereo -- Calcule une FFT.
- *
- * SYNOPSIS
- * FastFFTC::FixFFT_Stereo(pd_FFTIn, iFFTSize)
- *
- * void FastFFTC::FixFFT_Stereo(REAL *, UWORD);
- *
- * FUNCTION
- * Calcule la FFT d'un ensemble d'échantillons stéréo.
- *
- * INPUTS
- * pd_FFTIn - Tableau de sortie de la FFT.
- * iFFTSize - Nombre d'échantillons à traiter.
- *
- * NOTES
- * La routine FFT effectue son calcul sur les deux canaux simultanément (les
- * échantillons ayant été placés dans l'ordre correct auparavant).
- * Dès lors, il suffit de réordonner les valeurs fournies par la FFT en
- * profitant des symétries pour obtenir la véritable FFT de chacun des deux
- * canaux.
- *
- * BUGS
- * Fonction contrôlée conforme le 20.06.98
- *
- * SEE ALSO
- * FastFFTC::FastFFT()
- *
- *****************************************************************************
- *
- * Benchmark (3 cycles par seconde) :
- * 21.06.98 : 0'19.61
- */
-
- #if _USE_ASM_FCT_ == 0
-
- void FastFFTC::FixFFT_Stereo(T_FFTDATAS *pd_FFTIn, UWORD iFFTSize)
- {
- T_FFTDATAS *pd_FFTOut = &pd_FFTIn[BLKSIZE * 2]; // &(*FFT_pdWinSmplShuffled)[1][0][0];
- T_FFTDATAS *pd_FFTIn2 = &pd_FFTIn[iFFTSize * 2]; // &(*FFT_pdWinSmplShuffled)[0][iFFTSize][0];
- double dOneHalf = 0.5;
-
- ULONG j;
- ULONG iFFTLen = iFFTSize >> 1;
-
- // Décoder les données en sortie de FFT pour obtenir la table finale.
-
- pd_FFTOut[0] = pd_FFTIn[1];
- pd_FFTIn[1] = pd_FFTOut[1] = 0.0;
-
- pd_FFTIn += 2;
- pd_FFTOut += 2;
-
- for (j = iFFTLen; j > 0; j--)
- {
- pd_FFTIn2 += (-2);
-
- *pd_FFTOut++ = dOneHalf * (pd_FFTIn[1] + pd_FFTIn2[1]);
- *pd_FFTOut++ = dOneHalf * (pd_FFTIn2[0] - pd_FFTIn[0]);
-
- *pd_FFTIn++ = dOneHalf * (*pd_FFTIn + pd_FFTIn2[0]);
- *pd_FFTIn++ = dOneHalf * (*pd_FFTIn - pd_FFTIn2[1]);
- }
- }
-
- #endif // _USE_ASM_FCT_
- ///
- /// FastFFTC::FixFFT_Mono()
- /****** Class FastFFTC/FixFFT_Mono ******************************************
- *
- * NAME
- * FastFFTC::FixFFT_Mono -- Calcule une FFT
- *
- * SYNOPSIS
- * FastFFTC::FixFFT_Mono(pd_FFTIn, iFFTSize)
- *
- * void FastFFTC::FixFFT_Mono(REAL *, UWORD);
- *
- * FUNCTION
- * Calcule une FFT sur un groupe d'échantillons (fichier mono).
- *
- * INPUTS
- * pd_FFTIn - Tableau de sortie de la FFT.
- * iFFTSize - Taille de la fenêtre FFT (est égale à la moitié du nombre d'
- * échantillons à analyser).
- *
- * NOTES
- * Les échantillons sont placés dans un ordre particulier afin de limiter
- * le nombre de calculs (échantillons d'index pair comme partie réelle,
- * échantillons d'index impair comme partie imaginaire).
- * Cette solution permet de limiter la taille de la fenêtre FFT à la moitié
- * de sa taille normale.
- * Il suffit de réordonner les nombres complexes en sortie de FFT pour
- * obtenir le résultat recherché.
- *
- * BUGS
- * Fonction contrôlée conforme le 05/07/98
- *
- * SEE ALSO
- * FastFFTC::FastFFT()
- *
- *****************************************************************************
- *
- */
-
- #if _USE_ASM_FCT_ == 0
-
- void FastFFTC::FixFFT_Mono(T_FFTDATAS *pd_FFTIn, UWORD iFFTSize)
- {
- T_FFTDATAS *pd_FFTIn2 = &pd_FFTIn[iFFTSize * 2]; // &(*FFT_pdWinSmplShuffled)[0][iFFTSize][0];
- T_FFTDATAS *pd_FFTOrg = pd_FFTIn;
-
- ULONG i;
- ULONG iFFTLen = iFFTSize >> 1;
-
- double wr, wi;
-
- #if _USE_SINCOS_TABLE_ == 0
- double wpr, wpi;
- #else
- ULONG delta = 0;
- float *Cosin = &FFT_dSinCos[0];
- float *Sinus = &FFT_dSinCos[SINCOSSIZE / 3];
- #endif
-
- double h1r, h1i, h2r, h2i;
- double dOneHalf = 0.5;
-
- // Décoder les données en sortie de FFT pour obtenir la table finale.
-
- #if _USE_SINCOS_TABLE_ == 0
- wpr = FFT_dSinCos[0][9]; // cos(PI/iFFTSize);
- wpi = FFT_dSinCos[1][9]; // sin(PI/iFFTSize);
-
- wr = wpr; // = cos(theta)
- wi = wpi; // = sin(theta)
- #endif
-
- pd_FFTIn += 2;
-
- for (i = 1; i <= iFFTLen; i++)
- {
- #if _USE_SINCOS_TABLE_ == 1
- ++delta;
- wr = Cosin[delta];
- wi = Sinus[delta];
- #endif
-
- pd_FFTIn2 += (-2);
-
- h2r = dOneHalf * (pd_FFTIn[1] + pd_FFTIn2[1]);
- h2i = dOneHalf * (pd_FFTIn2[0] - pd_FFTIn[0]);
-
- h1r = h2r;
- h2r = wr * h1r - wi * h2i;
- h2i = wr * h2i + wi * h1r;
-
- h1r = dOneHalf * (pd_FFTIn[0] + pd_FFTIn2[0]);
- h1i = dOneHalf * (pd_FFTIn[1] - pd_FFTIn2[1]);
-
- *pd_FFTIn++ = h2r + h1r; // + wr * h2r - wi * h2i;
- *pd_FFTIn++ = h2i + h1i; // + wr * h2i + wi * h2r;
- pd_FFTIn2[0] = h1r - h2r; // - wr * h2r + wi * h2i;
- pd_FFTIn2[1] = h2i - h1i; // + wr * h2i + wi * h2r;
-
- #if _USE_SINCOS_TABLE_ == 0
- h1r = wr;
- wr = h1r * wpr - wi * wpi; // = cos(x).cos(theta) - sin(x).sin(theta) = cos(x+theta)
- wi = wi * wpr + h1r * wpi; // = sin(x).cos(theta) + cos(x).sin(theta) = sin(x+theta)
- #endif
- }
-
- iFFTSize *= 2;
-
- pd_FFTOrg[iFFTSize] = pd_FFTOrg[0] - pd_FFTOrg[1];
- pd_FFTOrg[0] += pd_FFTOrg[1];
-
- ++pd_FFTOrg;
- pd_FFTOrg[0] = pd_FFTOrg[iFFTSize] = 0.0;
- }
-
- #endif // _USE_ASM_FCT_
- ///
- /// FastFFTC::SetupWinSamples_1024()
- /****** Class FastFFTC/SetupWinSamples_1024 *********************************
- *
- * NAME
- * FastFFTC::SetupWinSamples_1024 -- Préparer les données pour la FFT.
- *
- * SYNOPSIS
- * FastFFTC::SetupWinSamples_1024(pSamples, wNumChannels)
- *
- * void FastFFTC::SetupWinSamples_1024(WORD *, UWORD);
- *
- * FUNCTION
- * Initialise le tampon d'entrée de la FFT à partir d'un bloc contenant 1024
- * échantillons.
- * Lorsque le fichier audio traité est stéréo, les deux canaux sont préparés
- * simultanément.
- *
- * INPUTS
- * pSamples - Pointeur vers les échantillons.
- * wNumChannels - Nombre de canaux.
- *
- * NOTES
- * Afin de tirer partie des symétries de la FFT, les deux canaux sont
- * préparés de sorte que l'un corresponde à la partie réelle, et l'autre
- * à la partie imaginaire. De fait, la FFT effectue son calcul sur les deux
- * canaux simultanément.
- *
- * Pour un fichier mono, les échantillons sont alternativement placés dans
- * la partie réelle (échantillons d'indices pairs) ou la partie imaginaire
- * (échantillons d'indices impairs) du tampon d'entrée. De cette façon, la
- * fonction FFT peut être fortement optimisée.
- *
- * BUGS
- *
- * SEE ALSO
- * FastFFTC::ComputeFastFFT_Stereo()
- *
- *****************************************************************************
- *
- * Benchmarks (12 cycles par seconde) :
- * 21.06.98 : 0'25.42
- *
- */
-
- #if _USE_ASM_FCT_ == 0
-
- void FastFFTC::SetupWinSamples_1024(WORD *pSamples, UWORD wNumChannels)
- {
- const T_FFTDATAS *pdHANNWindow = &(*FFT_pdHannWindowShuffled)[0];
- T_FFTDATAS *pdWSmpls = &(*FFT_pdWinSmplShuffled)[0][0][0];
- double f;
-
- WORD *pwSmpl;
- ULONG i, k;
-
- if (wNumChannels == 2)
- {
- for (i = 0; i < 1024 / 4; i++)
- {
- k = GetShuffleIndex_8(i) * 2;
- pwSmpl = &pSamples[k];
-
- f = *pdHANNWindow++;
- *pdWSmpls++ = pwSmpl[0] * f; // Canal gauche.
- *pdWSmpls++ = pwSmpl[1] * f; // Canal droit.
-
- f = *pdHANNWindow++;
- *pdWSmpls++ = pwSmpl[512 * 2] * f; // Canal gauche.
- *pdWSmpls++ = pwSmpl[512 * 2 + 1] * f; // Canal droit.
-
- f = *pdHANNWindow++;
- *pdWSmpls++ = pwSmpl[256 * 2] * f; // Canal gauche.
- *pdWSmpls++ = pwSmpl[256 * 2 + 1] * f; // Canal droit.
-
- f = *pdHANNWindow++;
- *pdWSmpls++ = pwSmpl[768 * 2] * f; // Canal gauche.
- *pdWSmpls++ = pwSmpl[768 * 2 + 1] * f; // Canal droit.
- }
- }
- else
- {
- for (i = 0; i < 1024 / 4; i++)
- {
- k = GetShuffleIndex_8(i) * 2;
- pwSmpl = &pSamples[k];
-
- *pdWSmpls++ = pwSmpl[0] * *pdHANNWindow++;
- *pdWSmpls++ = pwSmpl[1] * pdHANNWindow[511];
- *pdWSmpls++ = pwSmpl[512] * *pdHANNWindow++;
- *pdWSmpls++ = pwSmpl[513] * pdHANNWindow[511];
- }
- }
- }
-
- #endif // _USE_ASM_FCT_
- ///
-
-
-