/*	header.cpp

	Implementation of MPEG header class

	A few layer III, MPEG-2 LSF, and seeking modifications made by
   Jeff Tsay. MPEG-2 LSF is not yet supported.

   Last modified : 04/19/97 */


/*
 *  Changes from version 1.1 to 1.2:
 *    - iostreams manipulator calls like "cerr << setw (2) << ..." replaced by
 *      "cerr.width (2); ..." due to problems with older GNU C++ releases.
 *    - syncword recognition slightly changed
 */



//#define NULL 0
#include "header.h"

const uint32 Header::frequencies[2][4] =
{{22050, 24000, 16000, 1},
 {44100, 48000, 32000, 1}};

Header::Header()
{
  	framesize = 0;
   nSlots    = 0;
  	crc       = NULL;
   offset    = NULL;

   initial_sync = FALSE;
}

Header::~Header()
{
   delete [] offset;
}

BOOL Header::read_header(Ibitstream *stream, Crc16 **crcp)
//BOOL Header::read_header(FILE *stream, Crc16 **crcp)
{
  uint32 headerstring, channel_bitrate;

  if (!initial_sync) {

  	if (!stream->get_header(&headerstring, INITIAL_SYNC))
	 	return(FALSE);

  	h_version = (e_version) ((headerstring >> 19) & 1);

   // temporary code, take out when MPEG-2 LSF is implemented
   if (h_version == MPEG2_LSF)
   {

; //		 cerr << "Sorry, MPEG-2 LSF is not supported yet." << endl;

	    return(FALSE);
   }

   if ((h_sample_frequency = (e_sample_frequency)
                             ((headerstring >> 10) & 3)) == 3)
   {

; //		 cerr << "Unknown sample frequency!" << endl;

	    return(FALSE);
   }

   stream->set_syncword(headerstring & 0xFFF80CC0);

   initial_sync = TRUE;

  } else {

	  	if (!stream->get_header(&headerstring, STRICT_SYNC))
		 	return(FALSE);
  } // initial_sync



  h_layer   = 4 - (headerstring >> 17) & 3;

  h_protection_bit = (headerstring >> 16) & 1;



  h_bitrate_index  = (headerstring >> 12) & 0xF;

  h_padding_bit = (headerstring >> 9) & 1;
  h_mode        = (e_mode)((headerstring >> 6) & 3);



  h_mode_extension = (headerstring >> 4) & 3;

  if (h_mode == joint_stereo)
	 h_intensity_stereo_bound = (h_mode_extension << 2) + 4;
  else
	 h_intensity_stereo_bound = 0;		// should never be used

  h_copyright = (BOOL) ((headerstring >> 3) & 1);
  h_original  = (BOOL) ((headerstring >> 2) & 1);

  // calculate number of subbands:
  if (h_layer == 1)
	 h_number_of_subbands = 32;
  else
  {
	 channel_bitrate = h_bitrate_index;

	 // calculate bitrate per channel:
	 if (h_mode != single_channel)
		if (channel_bitrate == 4)
			channel_bitrate = 1;
		else
			channel_bitrate -= 4;

	 if ((channel_bitrate == 1) || (channel_bitrate == 2))
		if (h_sample_frequency == thirtytwo)
			h_number_of_subbands = 12;
		else
			h_number_of_subbands = 8;
	 else
		if ((h_sample_frequency == fourtyeight) || ((channel_bitrate >= 3) &&
      													  	  (channel_bitrate <= 5)))
			h_number_of_subbands = 27;
		else
			h_number_of_subbands = 30;
  }

  if (h_intensity_stereo_bound > h_number_of_subbands)
     h_intensity_stereo_bound = h_number_of_subbands;


  // calculate framesize and nSlots
	calculate_framesize();

  // read framedata:
  if (stream->read_frame(framesize) == FALSE)
     return(FALSE);

  if (!h_protection_bit)
  {
	 // frame contains a crc checksum
	 checksum = (uint16) stream->get_bits(16);
	 if (!crc)
       crc = new Crc16;
	 crc->add_bits(headerstring, 16);
	 *crcp = crc;
  }
  else
	 *crcp = NULL;

  if (h_sample_frequency == fourtyfour_point_one) {

	 if (!offset) {

    	uint32 max = max_number_of_frames(stream);

		offset = new uint32[max];

      for(uint32 i=0; i<max; i++)
      	offset[i] = 0;
    }

    {
     int32 cf = stream->current_frame();
     int32 lf = stream->last_frame();
	  if ((cf > 0) && (cf == lf)) {
		   offset[cf] = offset[cf-1] + h_padding_bit;
     } else {
  	      offset[0] = h_padding_bit;
     }
    }
  }

  return(TRUE);
}


uint32 Header::calculate_framesize()
// calculates framesize in bytes excluding header size
{
  static const int32 bitrates[2][3][16] = {
  {{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,
    112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0},
   {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,
    56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0},
   {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,
    56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}},
  {{0 /*free format*/, 32000, 64000, 96000, 128000, 160000, 192000,
	 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000, 0},
	{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,
	 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, 0},
	{0 /*free format*/, 32000, 40000, 48000, 56000, 64000, 80000,
	 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0}}
  };

  if (h_layer == 1)
  {
	 framesize = (12 * bitrates[h_version][0][h_bitrate_index]) /
                 frequencies[h_version][h_sample_frequency];

	 if (h_padding_bit) framesize++;

	 framesize <<= 2;		// one slot is 4 bytes long
  }
  else
  {
	 framesize = (144 * bitrates[h_version][h_layer - 1][h_bitrate_index]) /
                 frequencies[h_version][h_sample_frequency];

	 if (h_version == MPEG2_LSF)
    	framesize >>= 1;

	 if (h_padding_bit) framesize++;

	 // Layer III slots
	 if (h_layer == 3) {

       if (h_version == MPEG1) {

			 nSlots = framesize - ((h_mode == single_channel) ? 17 : 32) // side info size
									  -  (h_protection_bit ? 0 : 2) 		       // CRC size
									  - 4; 								             // header size
       } else {  // MPEG-2 LSF
        	 nSlots = framesize - ((h_mode == single_channel) ?  9 : 17) // side info size
						   		  -  (h_protection_bit ? 0 : 2) 		       // CRC size
									  - 4; 								             // header size
       }
	 } else {
    	 nSlots = 0;
    }
  }

  framesize -= 4;             // subtract header size

  return(framesize);
}

const char *Header::layer_string()
{
  switch (h_layer)
  {
	 case 1:
		return "I";
	 case 2:
		return "II";
	 case 3:
		return "III";
  }
  return NULL;			// dummy
}


const char *Header::bitrate_string()
{

  static const char *bitrate_str[2][3][16] = {
  {{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",
    "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s",
    "160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s",
    "forbidden"},
   {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",
    "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",
    "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",
    "forbidden"},
   {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",
    "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",
    "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",
    "forbidden"}},
  {{"free format", "32 kbit/s", "64 kbit/s", "96 kbit/s", "128 kbit/s",
    "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "288 kbit/s",
    "320 kbit/s", "352 kbit/s", "384 kbit/s", "416 kbit/s", "448 kbit/s",
    "forbidden"},
	{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",
    "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "160 kbit/s",
    "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s", "384 kbit/s",
    "forbidden"},
	{"free format", "32 kbit/s", "40 kbit/s", "48 kbit/s", "56 kbit/s",
    "64 kbit/s", "80 kbit/s" , "96 kbit/s", "112 kbit/s", "128 kbit/s",
    "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s",
    "forbidden"}}
  };

  return(bitrate_str[h_version][h_layer - 1][h_bitrate_index]);
}

const char *Header::sample_frequency_string()
{
  switch (h_sample_frequency)
  {
	 case thirtytwo:
    	if (h_version == MPEG1)
			return("32 kHz");
      else
      	return("16 kHz");
	 case fourtyfour_point_one:
    	if (h_version == MPEG1)
			return("44.1 kHz");
      else
      	return("22.05 kHz");
	 case fourtyeight:
    	if (h_version == MPEG1)
			return("48 kHz");
      else
      	return("24 kHz");
  }
  return(NULL);			// dummy
}

const char *Header::mode_string()
{
  switch (h_mode)
  {
	 case stereo:
		return("Stereo");
	 case joint_stereo:
		return("Joint stereo");
	 case dual_channel:
		return("Dual channel");
	 case single_channel:
		return("Single channel");
  }
  return(NULL);			// dummy
}

const char *Header::version_string()
{
 	switch (h_version)
   {
   	case MPEG1:
        return("MPEG-1");
      case MPEG2_LSF:
        return("MPEG-2 LSF");
   }
   return(NULL);
}

#ifdef SEEK_STOP
// Stream searching routines
BOOL Header::stream_seek(Ibitstream *stream, uint32 seek_pos)
//BOOL Header::stream_seek(FILE *stream, uint32 seek_pos)
{

   return ((h_sample_frequency != fourtyfour_point_one) ?
   		  stream->seek(seek_pos, framesize) :
           stream->seek_pad(seek_pos, framesize - h_padding_bit,
                            this, offset));
}
#endif

uint32 Header::max_number_of_frames(Ibitstream *stream)
//uint32 Header::max_number_of_frames(FILE *stream)
// Returns the maximum number of frames in the stream
{
	  return(stream->file_size() / (framesize + 4 - h_padding_bit));
}

uint32 Header::min_number_of_frames(Ibitstream *stream)
//uint32 Header::min_number_of_frames(FILE *stream)
// Returns the minimum number of frames in the stream
{
	  return(stream->file_size() / (framesize + 5 - h_padding_bit));
}

real Header::ms_per_frame()
{
	static real ms_per_frame_array[3][3] = {{8.707483f,  8.0f, 12.0f},
												       {26.12245f, 24.0f, 36.0f},
   	                                     {26.12245f, 24.0f, 36.0f}};

	return(ms_per_frame_array[h_layer-1][h_sample_frequency]);
}

real Header::total_ms(Ibitstream *stream)
//real Header::total_ms(FILE *stream)
{
	return(max_number_of_frames(stream) * ms_per_frame());
}

