/*
 * Siren Encoder/Decoder library
 *
 *   @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
 *
 * This library 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; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */


#include "siren7.h"

SirenDecoder
Siren7_NewDecoder (int sample_rate)
{
  SirenDecoder decoder = (SirenDecoder) malloc (sizeof (struct stSirenDecoder));
  decoder->sample_rate = sample_rate;

  decoder->WavHeader.riff.RiffId = ME_TO_LE32 (RIFF_ID);
  decoder->WavHeader.riff.RiffSize = sizeof (PCMWavHeader) - 2 * sizeof (int);
  decoder->WavHeader.riff.RiffSize =
      ME_TO_LE32 (decoder->WavHeader.riff.RiffSize);
  decoder->WavHeader.WaveId = ME_TO_LE32 (WAVE_ID);

  decoder->WavHeader.FmtId = ME_TO_LE32 (FMT__ID);
  decoder->WavHeader.FmtSize = ME_TO_LE32 (sizeof (FmtChunk));

  decoder->WavHeader.fmt.Format = ME_TO_LE16 (0x01);
  decoder->WavHeader.fmt.Channels = ME_TO_LE16 (1);
  decoder->WavHeader.fmt.SampleRate = ME_TO_LE32 (16000);
  decoder->WavHeader.fmt.ByteRate = ME_TO_LE32 (32000);
  decoder->WavHeader.fmt.BlockAlign = ME_TO_LE16 (2);
  decoder->WavHeader.fmt.BitsPerSample = ME_TO_LE16 (16);

  decoder->WavHeader.FactId = ME_TO_LE32 (FACT_ID);
  decoder->WavHeader.FactSize = ME_TO_LE32 (sizeof (int));
  decoder->WavHeader.Samples = ME_TO_LE32 (0);

  decoder->WavHeader.DataId = ME_TO_LE32 (DATA_ID);
  decoder->WavHeader.DataSize = ME_TO_LE32 (0);

  memset (decoder->context, 0, sizeof (decoder->context));
  memset (decoder->backup_frame, 0, sizeof (decoder->backup_frame));

  decoder->dw1 = 1;
  decoder->dw2 = 1;
  decoder->dw3 = 1;
  decoder->dw4 = 1;

  siren_init ();
  return decoder;
}

void
Siren7_CloseDecoder (SirenDecoder decoder)
{
  free (decoder);
}

int
Siren7_DecodeFrame (SirenDecoder decoder, unsigned char *DataIn,
    unsigned char *DataOut)
{
  int number_of_coefs,
      sample_rate_bits,
      rate_control_bits,
      rate_control_possibilities,
      checksum_bits,
      esf_adjustment,
      scale_factor, number_of_regions, sample_rate_code, bits_per_frame;
  int decoded_sample_rate_code;

  static int absolute_region_power_index[28] = { 0 };
  static float decoder_standard_deviation[28] = { 0 };
  static int power_categories[28] = { 0 };
  static int category_balance[28] = { 0 };
  int ChecksumTable[4] = { 0x7F80, 0x7878, 0x6666, 0x5555 };
  int i, j;

  int dwRes = 0;
  int envelope_bits = 0;
  int rate_control = 0;
  int number_of_available_bits;
  int number_of_valid_coefs;
  int frame_error = 0;

  int In[20];
  float coefs[320];
  float BufferOut[320];
  int sum;
  int checksum;
  int calculated_checksum;
  int idx;
  int temp1;
  int temp2;

  for (i = 0; i < 20; i++)
#ifdef __BIG_ENDIAN__
    In[i] = ((short *) DataIn)[i];
#else
    In[i] =
        ((((short *) DataIn)[i] << 8) & 0xFF00) | ((((short *) DataIn)[i] >> 8)
        & 0x00FF);
#endif

  dwRes =
      GetSirenCodecInfo (1, decoder->sample_rate, &number_of_coefs,
      &sample_rate_bits, &rate_control_bits, &rate_control_possibilities,
      &checksum_bits, &esf_adjustment, &scale_factor, &number_of_regions,
      &sample_rate_code, &bits_per_frame);

  if (dwRes != 0)
    return dwRes;


  set_bitstream (In);

  decoded_sample_rate_code = 0;
  for (i = 0; i < sample_rate_bits; i++) {
    decoded_sample_rate_code <<= 1;
    decoded_sample_rate_code |= next_bit ();
  }


  if (decoded_sample_rate_code != sample_rate_code)
    return 7;

  number_of_valid_coefs = region_size * number_of_regions;
  number_of_available_bits = bits_per_frame - sample_rate_bits - checksum_bits;


  envelope_bits =
      decode_envelope (number_of_regions, decoder_standard_deviation,
      absolute_region_power_index, esf_adjustment);

  number_of_available_bits -= envelope_bits;

  for (i = 0; i < rate_control_bits; i++) {
    rate_control <<= 1;
    rate_control |= next_bit ();
  }

  number_of_available_bits -= rate_control_bits;

  categorize_regions (number_of_regions, number_of_available_bits,
      absolute_region_power_index, power_categories, category_balance);

  for (i = 0; i < rate_control; i++) {
    power_categories[category_balance[i]]++;
  }

  number_of_available_bits =
      decode_vector (decoder, number_of_regions, number_of_available_bits,
      decoder_standard_deviation, power_categories, coefs, scale_factor);


  frame_error = 0;
  if (number_of_available_bits > 0) {
    for (i = 0; i < number_of_available_bits; i++) {
      if (next_bit () == 0)
        frame_error = 1;
    }
  } else if (number_of_available_bits < 0
      && rate_control + 1 < rate_control_possibilities) {
    frame_error |= 2;
  }

  for (i = 0; i < number_of_regions; i++) {
    if (absolute_region_power_index[i] > 33
        || absolute_region_power_index[i] < -31)
      frame_error |= 4;
  }

  if (checksum_bits > 0) {
    bits_per_frame >>= 4;
    checksum = In[bits_per_frame - 1] & ((1 << checksum_bits) - 1);
    In[bits_per_frame - 1] &= ~checksum;
    sum = 0;
    idx = 0;
    do {
      sum ^= (In[idx] & 0xFFFF) << (idx % 15);
    } while (++idx < bits_per_frame);

    sum = (sum >> 15) ^ (sum & 0x7FFF);
    calculated_checksum = 0;
    for (i = 0; i < 4; i++) {
      temp1 = ChecksumTable[i] & sum;
      for (j = 8; j > 0; j >>= 1) {
        temp2 = temp1 >> j;
        temp1 ^= temp2;
      }
      calculated_checksum <<= 1;
      calculated_checksum |= temp1 & 1;
    }

    if (checksum != calculated_checksum)
      frame_error |= 8;
  }

  if (frame_error != 0) {
    for (i = 0; i < number_of_valid_coefs; i++) {
      coefs[i] = decoder->backup_frame[i];
      decoder->backup_frame[i] = 0;
    }
  } else {
    for (i = 0; i < number_of_valid_coefs; i++)
      decoder->backup_frame[i] = coefs[i];
  }


  for (i = number_of_valid_coefs; i < number_of_coefs; i++)
    coefs[i] = 0;


  dwRes = siren_rmlt_decode_samples (coefs, decoder->context, 320, BufferOut);


  for (i = 0; i < 320; i++) {
    if (BufferOut[i] > 32767.0)
      ((short *) DataOut)[i] = (short) ME_TO_LE16 ((short) 32767);
    else if (BufferOut[i] <= -32768.0)
      ((short *) DataOut)[i] = (short) ME_TO_LE16 ((short) 32768);
    else
      ((short *) DataOut)[i] = (short) ME_TO_LE16 ((short) BufferOut[i]);
  }

  decoder->WavHeader.Samples = ME_FROM_LE32 (decoder->WavHeader.Samples);
  decoder->WavHeader.Samples += 320;
  decoder->WavHeader.Samples = ME_TO_LE32 (decoder->WavHeader.Samples);
  decoder->WavHeader.DataSize = ME_FROM_LE32 (decoder->WavHeader.DataSize);
  decoder->WavHeader.DataSize += 640;
  decoder->WavHeader.DataSize = ME_TO_LE32 (decoder->WavHeader.DataSize);
  decoder->WavHeader.riff.RiffSize =
      ME_FROM_LE32 (decoder->WavHeader.riff.RiffSize);
  decoder->WavHeader.riff.RiffSize += 640;
  decoder->WavHeader.riff.RiffSize =
      ME_TO_LE32 (decoder->WavHeader.riff.RiffSize);


  return 0;
}
