#include <ctype.h>
#include <stdlib.h>
#include <signal.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "mpg123.h"

struct parameter param = { 1, 1, 0, 0 };

int tabsel_123[2][3][16] = {
  {{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,}},

  {{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,}}
};

long freqs[9] = { 44100, 48000, 32000,
  22050, 24000, 16000,
  11025, 12000, 8000
};

int bitindex;
unsigned char *wordpointer;
unsigned char *pcm_sample;
int pcm_point = 0;


#define HDRCMPMASK 0xfffffd00

#if 0
int
head_check (unsigned long head)
{
  if ((head & 0xffe00000) != 0xffe00000)
    return FALSE;
  if (!((head >> 17) & 3))
    return FALSE;
  if (((head >> 12) & 0xf) == 0xf)
    return FALSE;
  if (((head >> 10) & 0x3) == 0x3)
    return FALSE;
  return TRUE;
}
#endif


int
decode_header_bitrate (struct frame *fr, unsigned long head)	// header inverted
{
  if (head & 0x1000)
    fr->lsf = ((head >> 11) & 1) ^ 1;
  else
    fr->lsf = 1;

  fr->bitrate_index = (head >> 20) & 0xf;

  return tabsel_123[fr->lsf][2][fr->bitrate_index];
}


float
decode_header_gens (struct frame *fr, unsigned long head)	// header inverted
{
  if (head & 0x1000)
    {
      fr->lsf = ((head >> 11) & 1) ^ 1;
      fr->mpeg25 = 0;
    }
  else
    {
      fr->lsf = 1;
      fr->mpeg25 = 1;
    }

  if (fr->mpeg25)
    fr->sampling_frequency = 6 + ((head >> 18) & 3);
  else
    fr->sampling_frequency = ((head >> 18) & 3) + (fr->lsf * 3);

  fr->bitrate_index = (head >> 20) & 0xf;
  fr->padding = (head >> 17) & 1;

  fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000;
  fr->framesize /= freqs[fr->sampling_frequency] << (fr->lsf);
  fr->framesize = fr->framesize + fr->padding - 4;

  return (float) (fr->framesize +
		  4) /
    (float) (tabsel_123[fr->lsf][2][fr->bitrate_index] >> 3);
}


/*
 * the code a header and write the information
 * into the frame structure
 */
int
decode_header (struct frame *fr, unsigned long newhead)
{
  if (newhead & (1 << 20))
    {
      fr->lsf = (newhead & (1 << 19)) ? 0x0 : 0x1;
      fr->mpeg25 = 0;
    }
  else
    {
      fr->lsf = 1;
      fr->mpeg25 = 1;
    }

  fr->lay = 4 - ((newhead >> 17) & 3);
  if (((newhead >> 10) & 0x3) == 0x3)
    {
      fprintf (stderr, "Stream error\n");
      exit (1);
    }
  if (fr->mpeg25)
    {
      fr->sampling_frequency = 6 + ((newhead >> 10) & 0x3);
    }
  else
    fr->sampling_frequency = ((newhead >> 10) & 0x3) + (fr->lsf * 3);
  fr->error_protection = ((newhead >> 16) & 0x1) ^ 0x1;

  if (fr->mpeg25)		/* allow Bitrate change for 2.5 ... */
    fr->bitrate_index = ((newhead >> 12) & 0xf);

  fr->bitrate_index = ((newhead >> 12) & 0xf);
  fr->padding = ((newhead >> 9) & 0x1);
  fr->extension = ((newhead >> 8) & 0x1);
  fr->mode = ((newhead >> 6) & 0x3);
  fr->mode_ext = ((newhead >> 4) & 0x3);
  fr->copyright = ((newhead >> 3) & 0x1);
  fr->original = ((newhead >> 2) & 0x1);
  fr->emphasis = newhead & 0x3;

  fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2;

  if (!fr->bitrate_index)
    {
      fprintf (stderr, "Free format not supported.\n");
      return (0);
    }

  switch (fr->lay)
    {
    case 1:
#ifdef LAYER1
#if 0
      fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ?
	(fr->mode_ext << 2) + 4 : 32;
#endif
      fr->framesize =
	(long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000;
      fr->framesize /= freqs[fr->sampling_frequency];
      fr->framesize = ((fr->framesize + fr->padding) << 2) - 4;
#else
      fprintf (stderr, "Not supported!\n");
#endif
      break;
    case 2:
#ifdef LAYER2
#if 0
      fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ?
	(fr->mode_ext << 2) + 4 : fr->II_sblimit;
#endif
      fr->framesize =
	(long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000;
      fr->framesize /= freqs[fr->sampling_frequency];
      fr->framesize += fr->padding - 4;
#else
      fprintf (stderr, "Not supported!\n");
#endif
      break;
    case 3:
#if 0
      fr->do_layer = do_layer3;
      if (fr->lsf)
	ssize = (fr->stereo == 1) ? 9 : 17;
      else
	ssize = (fr->stereo == 1) ? 17 : 32;
#endif

#if 0
      if (fr->error_protection)
	ssize += 2;
#endif
      fr->framesize =
	(long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000;
      fr->framesize /= freqs[fr->sampling_frequency] << (fr->lsf);
      fr->framesize = fr->framesize + fr->padding - 4;
      break;
    default:
      fprintf (stderr, "Sorry, unknown layer type.\n");
      return (0);
    }
  return 1;
}

#if 0
void
print_header (struct frame *fr)
{
  static char *modes[4] =
    { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" };
  static char *layers[4] = { "Unknown", "I", "II", "III" };

  fprintf (stderr,
	   "MPEG %s, Layer: %s, Freq: %ld, mode: %s, modext: %d, BPF : %d\n",
	   fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), layers[fr->lay],
	   freqs[fr->sampling_frequency], modes[fr->mode], fr->mode_ext,
	   fr->framesize + 4);
  fprintf (stderr,
	   "Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n",
	   fr->stereo, fr->copyright ? "Yes" : "No",
	   fr->original ? "Yes" : "No", fr->error_protection ? "Yes" : "No",
	   fr->emphasis);
  fprintf (stderr, "Bitrate: %d Kbits/s, Extension value: %d\n",
	   tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index],
	   fr->extension);
}

void
print_header_compact (struct frame *fr)
{
  static char *modes[4] =
    { "stereo", "joint-stereo", "dual-channel", "mono" };
  static char *layers[4] = { "Unknown", "I", "II", "III" };

  fprintf (stderr, "MPEG %s layer %s, %d kbit/s, %ld Hz %s\n",
	   fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"),
	   layers[fr->lay],
	   tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index],
	   freqs[fr->sampling_frequency], modes[fr->mode]);
}

#endif

unsigned int
getbits (int number_of_bits)
{
  unsigned long rval;

  if (!number_of_bits)
    return 0;

  {
    rval = wordpointer[0];
    rval <<= 8;
    rval |= wordpointer[1];
    rval <<= 8;
    rval |= wordpointer[2];
    rval <<= bitindex;
    rval &= 0xffffff;

    bitindex += number_of_bits;

    rval >>= (24 - number_of_bits);

    wordpointer += (bitindex >> 3);
    bitindex &= 7;
  }
  return rval;
}

unsigned int
getbits_fast (int number_of_bits)
{
  unsigned long rval;

  {
    rval = wordpointer[0];
    rval <<= 8;
    rval |= wordpointer[1];
    rval <<= bitindex;
    rval &= 0xffff;
    bitindex += number_of_bits;

    rval >>= (16 - number_of_bits);

    wordpointer += (bitindex >> 3);
    bitindex &= 7;
  }
  return rval;
}

unsigned int
get1bit (void)
{
  unsigned char rval;
  rval = *wordpointer << bitindex;

  bitindex++;
  wordpointer += (bitindex >> 3);
  bitindex &= 7;

  return rval >> 7;
}
