#ifndef _PSYCHO_CLASS_HPP
#define _PSYCHO_CLASS_HPP

/*
**
** $VER: PsychoC.hpp 1.8 (15.8.2000)
**
*/

#ifndef  _PEGASECOND_HPP
#include "PegaseCond.hpp"
#endif

#ifndef  _FASTFFT_CLASS_HPP
#include "FastFFTC.hpp"
#endif

#ifndef  _CODER_CLASS_HPP
#include "CoderC.hpp"
#endif

#ifndef  _MEMORY_HPP
#include "Memory.hpp"
#endif


//----------------------------------------------------------------------------------------------------
//========================================== Classe PsychoC ==========================================
//----------------------------------------------------------------------------------------------------


class PsychoC : public FastFFTC
{
    public:

        // Constructeur et destructeur.

        PsychoC(CoderC &roCoderC);
        virtual ~PsychoC();

        // Fonctions de gestion.

        int    CheckPsychoStatus() const {return psy_MemoryError;}

        virtual void    PsychoAnal(LONG LTMin[MAX_CH][SBLIMIT]) = 0;
        virtual int     InitPsychoAnalyzer(int iSBLimit);

    protected:

        void    CalcGroupedValues(UWORD wChannel, UWORD wNew);
        void    CalcPermissibleNoise();

        // Données privées.

        typedef REAL  T_F2HBLK[2][HBLKSIZE];
        typedef REAL  T_FHBLK[HBLKSIZE];
        typedef UBYTE T_IHBLK[HBLKSIZE+3];          // +7 pour alignement.
        typedef UBYTE T_ICB[CBANDS+1];              // +1 pour alignement.
        typedef REAL  T_F32[SBLIMIT];
        typedef REAL  T_FCB[CBANDS];
        typedef REAL  T_FCB2[CBANDS][2];
        typedef REAL  T_FCBCB[CBANDS][CBANDS];

        typedef T_FFTDATAS T_F2HBLK32[2][HBLKSIZE][3][2];// Canal, Value, Var, Old

        // PsychoAnal()

        CoderC          &psy_roCoderC;
        int             psy_MemoryError;           // TRUE si un tampon n'a pu être alloué.

        const REAL      *psy_pdAbsThreshold;        // (absthr[][])
        T_F2HBLK32      *psy_pdTmpSave;

        // Le bloc suivant est utilisé par la version assembleur de CalcPermissibleNoise.
        T_FCB            psy_adToneMaskingNoise;    // (tmn[])
        T_FCB            psy_adNB;                  // (nb[])
        BYTE             psy_abCBands[2][64];
        T_FCB2           psy_adGroupedValues;       // (grouped_e[]/grouped_c[])
        UBYTE            psy_abCenterBarkVal[64];
        T_FCB            psy_adRNorm;               // (rnorm[])
        T_FCBCB         *psy_pdSpreading;           // (s[][])
        UWORD            psy_wCBands;               // = 58 (32 KHz) ou 62 (44.1 et 48 KHz).

        UWORD            psy_wPad;
        T_F32            psy_adEnergy2;             // (energy[])
        T_IHBLK          psy_abPartition;           // (partition[])
        T_ICB            psy_abNumLines;            // (numlines)
        UWORD            psy_wNew;
        UWORD            psy_wSBLimit;
};

//----------------------------------------------------------------------------------------------------
//======================================== Classe Psycho_L1C =========================================
//----------------------------------------------------------------------------------------------------


class Psycho_L1C : public PsychoC
{
    public:

        Psycho_L1C(CoderC &roCoderC) : PsychoC(roCoderC) {
            psy_MemoryError |= !(psy_pdLThr = (T_F2HBLK *) AllocAlignedBuffer(sizeof(T_F2HBLK)));
        }

        ~Psycho_L1C() {
            if (psy_pdLThr) FreeAlignedBuffer(psy_pdLThr);
        }

        int     InitPsychoAnalyzer(int iSBLimit);
        void    PsychoAnal(LONG LTMin[MAX_CH][SBLIMIT]);

    private:

        void    TranslateThreshold(UWORD wChannel);

        // Fonctions privées spécifiques.

        REAL    GetNoiseLevel(REAL dNoiseBand, REAL dThreshold, REAL *p_LThr);

        T_F32            psy_adSNRTemp;             // (snrtmp[])
        T_F2HBLK        *psy_pdLThr;                // (lthr[][])
};


//----------------------------------------------------------------------------------------------------
//======================================== Classe Psycho_L2C =========================================
//----------------------------------------------------------------------------------------------------


class Psycho_L2C : public PsychoC
{
    public:

        Psycho_L2C(CoderC &roCoderC) : PsychoC(roCoderC) {}
        void    PsychoAnal(LONG LTMin[MAX_CH][SBLIMIT]);

    private:

        void    TranslateThreshold(REAL *pSNR);

        typedef REAL T_F22_32[2][2][SBLIMIT];

        T_F22_32         psy_adSNRTemp;             // (snrtmp[][])
};


//----------------------------------------------------------------------------------------------------

#endif  // _PSYCHO_CLASS_HPP

