#ifndef VALIB_AC3_PARSER_H
#define VALIB_AC3_PARSER_H

#include "../../parser.h"
#include "../../bitstream.h"
#include "ac3_defs.h"
#include "ac3_imdct.h"



class AC3Info
{
public:
  int       bitrate;     
  int       halfrate;    

  int       fscod;       
  int       frmsizecod;  

  int       bsid;        
  int       bsmod;       

  int       acmod;       
  int       dsurmod;     
  bool      lfeon;       

  sample_t  clev;        
  sample_t  slev;        

  bool      compre;      
  sample_t  compr;       
  bool      compr2e;     
  sample_t  compr2;      

  int       dialnorm;    
  int       dialnorm2;   

  bool      langcode;    
  int       langcod;     
  bool      langcod2e;   
  int       langcod2;    

  bool      audprodie;   
  int       mixlevel;    
  int       roomtyp;     
                        
  bool      audprodi2e;  
  int       mixlevel2;   
  int       roomtyp2;    

  bool      copyrightb;  
  bool      origbs;      

  struct {
    int hours;
    int mins;
    int secs;
    int frames;
    int fracs;
  } timecode;            
};

class AC3FrameState
{
public:
  
  bool blksw[5];         
  bool dithflag[5];      

  sample_t dynrng;       
  sample_t dynrng2;      

  

  bool cplinu;
  bool chincpl[5];
  bool phsflginu;
  int  cplstrtmant;
  int  cplendmant;
  int  ncplbnd;
  int  cplbnd[18];
  sample_t cplco[5][18];

  

  int rematflg;
  int endmant[5];

  

  int8_t cplexps[256];
  int8_t exps[5][256];
  int8_t gainrng[5];     
  int8_t lfeexps[7];

  

  int sdecay;
  int fdecay;
  int sgain;
  int dbknee;
  int floor;

  int cplsnroffset;
  int snroffset[5];
  int lfesnroffset;

  int cplfgain;
  int fgain[5];
  int lfefgain;

  int cplfleak;
  int cplsleak;

  

  int  cpldeltbae;       
  int  deltbae[5];       

  int8_t cpldeltba[50];
  int8_t deltba[5][50];

  

  int8_t cplbap[256];
  int8_t bap[5][256];
  int8_t lfebap[7];
};

class AC3Parser : public FrameParser, public AC3Info, public AC3FrameState
{
public:
  bool do_crc;        
  bool do_dither;     
  bool do_imdct;      

  int frames;
  int errors;

public:
  AC3Parser();
  ~AC3Parser();

  
  

  virtual const HeaderParser *header_parser() const;

  virtual void reset();
  virtual bool parse_frame(uint8_t *frame, size_t size);

  virtual Speakers  get_spk()      const { return spk;               }
  virtual samples_t get_samples()  const { return samples;           }
  virtual size_t    get_nsamples() const { return AC3_FRAME_SAMPLES; }
  virtual uint8_t  *get_rawdata()  const { return 0;                 }
  virtual size_t    get_rawsize()  const { return 0;                 }

  virtual size_t stream_info(char *buf, size_t size) const;
  virtual size_t frame_info(char *buf, size_t size) const;

#ifndef AC3_DEBUG 
protected:
#else
public:
#endif

  
  

  Speakers  spk;        
  uint8_t  *frame;      
  size_t    frame_size; 
  int       bs_type;    

  SampleBuf samples;    
  SampleBuf delay;      
  IMDCT     imdct;      
  ReadBS    bs;         

  int block;

  bool start_parse(uint8_t *frame, size_t size);
  bool crc_check();
  bool decode_block();
  bool parse_header();
  bool parse_block();
  bool parse_exponents(int8_t *exps, int8_t absexp, int expstr, int nexpgrps);
  bool parse_deltba(int8_t *deltba);
  void parse_coeff(samples_t samples);

};

#endif
