/*C
  (c) 2005 bl0rg.net
**/

#ifndef MP3_H__
#define MP3_H__

/*M
  \emph{Size allocated for the ''raw'' content of an MP3 frame.}

  This is an arbitrary size.
**/
#define MP3_RAW_SIZE 4000
/*M
  \emph{Maximal number of synchronisation errors allowed while
  reading an MP3 stream.}
**/
#define MP3_MAX_SYNC 4000
/*M
  \emph{MPEG Audio Frame Header size.}
**/
#define MP3_HDR_SIZE 4

/*M
  \emph{Scalefactor information contained in a single granule.}
**/
typedef struct {
  unsigned int l[23];     /* long window */
  unsigned int s[3][13];  /* short window */
} mp3_sf_t;

typedef struct {
  int   s;
  float x;
} mp3_sample_t;

/*M
  \emph{MP3 granule.}
**/
typedef struct mp3_granule_s {
  int part2_3_length;
  int part2_length;
  int part3_length;
  
  unsigned int big_values;
  unsigned int global_gain;

  unsigned int scale_comp;
  unsigned int slen0;
  unsigned int slen1;
  
  unsigned int blocksplit_flag;
  unsigned int block_type;
  unsigned int switch_point;
  unsigned int tbl_sel[3];
  unsigned int reg0_cnt;
  unsigned int reg1_cnt;
  unsigned int sub_gain[3];
  unsigned int maxband[3];
  unsigned int maxbandl;
  unsigned int maxb;
  unsigned int region1start;
  unsigned int region2start;
  unsigned int preflag;
  unsigned int scale_scale;
  unsigned int cnt1tbl_sel;
  float        *full_gain[3];
  float        *pow2gain;

  mp3_sf_t     sf; /* scale factor */
  mp3_sample_t samples[576];
} mp3_granule_t;

/*M
  \emph{MP3 stereo channel.}
**/
typedef struct mp3_channel_s {
  unsigned char scfsi[4];
  mp3_granule_t granule[2];
} mp3_channel_t;

/*M
  \emph{MP3 side information.}

  In mono MP3s only the first channel structure is used.
**/
typedef struct mp3_si_s {
  unsigned int  main_data_end;
  unsigned int  private_bits;
  
  mp3_channel_t channel[2];
} mp3_si_t;

/*M
  \emph{Single MP3 frame.}
**/
typedef struct mp3_frame_s {
  unsigned char id;
  unsigned char layer;
  unsigned char protected;
  unsigned char bitrate_index;
  unsigned char samplerfindex;
  unsigned char padding_bit;
  unsigned char private_bit; 
  unsigned char mode;
  unsigned char mode_ext;
  unsigned char copyright;    
  unsigned char original;    
  unsigned char emphasis;

  unsigned char crc[2];
  
  mp3_si_t      si;
  unsigned long si_size;
  unsigned long si_bitsize;
  unsigned long adu_bitsize;
  unsigned long adu_size;
  
  /* calculated information */
  unsigned short syncskip;
  unsigned long  bitrate;
  unsigned long  samplerate;
  unsigned long  samplelen;
  unsigned long  frame_size;
  unsigned long  frame_data_size;
  unsigned long  usec;
  
  /* XXX add length counter for overflow checking */
  unsigned char  raw[MP3_RAW_SIZE];
} mp3_frame_t;

/*M
  \emph{Prototypes and macros.}
**/
#define mp3_frame_data_begin(f) \
  ((f)->raw + 4 + ((f)->protected ? 0 : 2) + (f)->si_size)

#include "file.h"

int mp3_read_si(mp3_frame_t *frame);
int mp3_read_hdr(mp3_frame_t *frame);
int mp3_read_sf(mp3_frame_t *frame);
int mp3_next_frame(file_t *mp3, mp3_frame_t *frame);
int mp3_unpack(mp3_frame_t *frame);

int mp3_fill_si(mp3_frame_t *frame);
int mp3_fill_hdr(mp3_frame_t *frame);
int mp3_write_frame(file_t *file, mp3_frame_t *frame);

int mp3_trans_frame(mp3_frame_t *frame);

void mp3_calc_hdr(mp3_frame_t *frame);
unsigned long mp3_frame_size(mp3_frame_t *frame);

/*M
**/
#endif /* MP3_H__ */
