#ifndef _PSYCHO_CLASS_HPP
#define _PSYCHO_CLASS_HPP

/*
**
** PsychoC.hpp
**
** $VER: PsychoC.hpp 1.0 (26.07.98)
**
** Classe PsychoC
**
** $Revision: 1.4 $
** $State: Exp $
** $Date: 1998/08/16 19:03:46 $
**
** $Log: PsychoC.hpp $
** Revision 1.4  1998/08/16 19:03:46  kakace
** Version Beta3+
**
** Revision 1.3  1998/08/02 15:17:12  kakace
** Fonctionnement OK (Layer 1/2 + Stereo/JStereo)
**
** Revision 1.2  1998/07/27 14:13:38  kakace
** Modification des membres (tableaux) de classe
**
** Revision 1.1  1998/07/27 02:16:53  kakace
** Initial revision
**
**
*/

#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();

        // Fonction utilisée pour contrôler l'analyseur psycho-acoustique.

        void psycho_anal(LONG chn, LONG pass, LONG layer, LONG LTMin[2][32]);

        // 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_F2_32[2][SBLIMIT];
        typedef REAL  T_FCB[CBANDS];
        typedef REAL  T_FCB2[CBANDS][2];
        typedef REAL  T_FCBCB[CBANDS][CBANDS];
        typedef REAL  T_F2BLK2[2][BLKSIZE][2];      // Canal, Sample, Real/Image
        typedef REAL  T_F2BLK[BLKSIZE][2];          // Sample, Real/Image

        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_FCBCB         *psy_pdSpreading;           // (s[][])
        T_F2HBLK32      *psy_pdTmpSave;

        T_IHBLK          psy_abPartition;           // (partition[])
        T_FCB2           psy_adGroupedValues;       // (grouped_e[]/grouped_c[])
        T_ICB            psy_abNumLines;            // (numlines)
        T_FCB            psy_adToneMaskingNoise;    // (tmn[])
        T_FCB            psy_adRNorm;               // (rnorm[])
        T_FCB            psy_adNB;                  // (nb[])
        T_F32            psy_adEnergy2;             // (energy[])

        UBYTE            psy_abCenterBarkVal[64];
        BYTE             psy_abCBands[2][64];
        UWORD            psy_wNew;
        UWORD            psy_wSBLimit;
        UWORD            psy_wCBands;               // = 58 (32 KHz) ou 62 (44.1 et 48 KHz).
        UWORD            psy_wPad;
};

//----------------------------------------------------------------------------------------------------
//======================================== 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

