/*
  stores information after we found a header.
  Copyright (C) 2000  Martin Vogt

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU Library General Public License as published by
  the Free Software Foundation.

  For more information look at the file COPYRIGHT in this package

 */



#include "mpegAudioHeader.h"

static const int frequencies[2][3]= {
    {44100,48000,32000}, // MPEG 1
    {22050,24000,16000}  // MPEG 2
};


static const int bitrate[2][3][15]= {
  // MPEG 1
  {{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448},
   {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384},
   {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320}},

  // MPEG 2
  {{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256},
   {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160},
   {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160}}
};


MpegAudioHeader::MpegAudioHeader() {
  
}


MpegAudioHeader::~MpegAudioHeader() {
}


int MpegAudioHeader::parseHeader(unsigned char* buf){

  int c;
  // Analyzing
  header[0]=buf[0];
  header[1]=buf[1];
  header[2]=buf[2];
  header[3]=buf[3];

  c=buf[1];
  c&=0xf;
  protection=c&1;
  layer=4-((c>>1)&3);
  version=(int)((c>>3)^1);
  c=buf[2];

  c=((c))>>1;
  padding=(c&1);
  c>>=1;
  frequency=(int)(c&3);
  c>>=2;
  bitrateindex=(int)c;
  if(bitrateindex>15) {
    cout << "bitrateindex error"<<endl;
    return false;
  }
  c=buf[3];

  c=((unsigned int)(c))>>4;
  extendedmode=c&3;
  mode=(int)(c>>2);


// Making information
  inputstereo= (mode==_MODE_SINGLE)?0:1;


  channelbitrate=bitrateindex;
  if(inputstereo) {
    if(channelbitrate==4) {
      channelbitrate=1;
    } else {
      channelbitrate-=4;
    }
  }

  if(channelbitrate==1 || channelbitrate==2) {
    tableindex=0;
  } else {
    tableindex=1;
  }

  if(layer==1)subbandnumber=MAXSUBBAND;
  else  {
    if(!tableindex) {
      if(frequency==_FREQUENCY_32000)subbandnumber=12; else subbandnumber=8;
    } else {
      if(frequency==_FREQUENCY_48000||
	 (channelbitrate>=3 && channelbitrate<=5)) {
	subbandnumber=27;
      } else {
	subbandnumber=30;
      }
    }
  }
  if(mode==_MODE_SINGLE)stereobound=0;
  else if(mode==_MODE_JOINT)stereobound=(extendedmode+1)<<2;
  else stereobound=subbandnumber;

  if(stereobound>subbandnumber)stereobound=subbandnumber;

  frequencyHz=frequencies[version][frequency];

  // framesize & slots
  if(layer==1) {
    if (frequencyHz <= 0) {
      return false;
    }
    framesize=(12000*bitrate[version][0][bitrateindex])/frequencyHz;

    if(frequency==_FREQUENCY_44100 && padding)framesize++;
    framesize<<=2;
  } else  {
    int freq=frequencyHz<<version;
    if (freq <= 0) {
      return false;
    }
    framesize=(144000*bitrate[version][layer-1][bitrateindex])/freq;

    if(padding)framesize++;
    if(layer==3) {
      if(version)
        layer3slots=framesize-((mode==_MODE_SINGLE)?9:17)
	  -(protection?0:2)
	  -4;
      else
        layer3slots=framesize-((mode==_MODE_SINGLE)?17:32)
                             -(protection?0:2)
                             -4;
    }
  }


  return true;

}
  

int MpegAudioHeader::getpcmperframe() {
  int s;
  
  s=32;
  if(layer==3) {
    s*=18;
    if(version==0)s*=2;
  }
  else {
    s*=SCALEBLOCK;
    if(layer==2)s*=3;
  }

  return s;
}


void MpegAudioHeader::copyTo(MpegAudioHeader* dest) {
  dest->protection=protection;
  dest->layer=layer;
  dest->version=version;
  dest->padding=padding;
  dest->frequency=frequency;
  dest->frequencyHz=frequencyHz;
  dest->bitrateindex=bitrateindex;
  dest->extendedmode=extendedmode;
  dest->mode=mode;
  dest->inputstereo=inputstereo;
  dest->channelbitrate=channelbitrate;
  dest->tableindex=tableindex;
  dest->subbandnumber=subbandnumber;
  dest->stereobound=stereobound;
  dest->framesize=framesize;
  dest->layer3slots=layer3slots;
    
}


void MpegAudioHeader::print(char* name) {
  cout << "MpegAudioHeader [START]:"<<name<<endl;
  printf("header:%1x%1x%1x%1x\n",header[0],header[1],header[2],header[3]);
  cout << "MpegAudioHeader [END]:"<<name<<endl;
 
}







