/*
 * 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include "siren7.h"

int region_size;
float region_size_inverse;

float standard_deviation[64];
float deviation_inverse[64];
float region_power_table_boundary[63];

int expected_bits_table[8] = {52, 47, 43, 37, 29, 22, 16, 0};
int vector_dimension[8] = {2, 2, 2, 4, 4, 5, 5, 1};
int number_of_vectors[8] = {10, 10, 10, 5, 5, 4, 4, 20};
float dead_zone[8] = {0.3f, 0.33f, 0.36f, 0.39f, 0.42f, 0.45f, 0.5f, 0.5f};

int max_bin[8] = {
  13,
  9,
  6,
  4,
  3,
  2,
  1,
  1};

float step_size[8] = {
  0.3536f,
  0.5f,
  0.70709997f,
  1.0f,
  1.4141999f,
  2.0f,
  2.8283999f,
  2.8283999f};

float step_size_inverse[8];

static int siren_initialized = 0;

/*
  STEPSIZE = 2.0 * log(sqrt(2));
*/
#define STEPSIZE 0.3010299957

void siren_init() {
  int i;
  float region_power;

  if (siren_initialized == 1)
    return;

  region_size = 20;
  region_size_inverse = 1.0f/region_size;

  for (i = 0; i < 64; i++) {
    region_power = (float) pow(10, (i-24) * STEPSIZE);
    standard_deviation[i] = (float) sqrt(region_power);
    deviation_inverse[i] = (float) 1.0 / standard_deviation[i];
  }

  for (i = 0; i < 63; i++)
    region_power_table_boundary[i] = (float) pow(10, (i-24 + 0.5) * STEPSIZE);

  for (i = 0; i < 8; i++)
    step_size_inverse[i] = (float) 1.0 / step_size[i];

  siren_dct4_init();
  siren_rmlt_init();

  siren_initialized = 1;
}


int categorize_regions(int number_of_regions, int number_of_available_bits, int *absolute_region_power_index, int *power_categories, int *category_balance) {
  int region, delta, i, temp;
  int expected_number_of_code_bits;
  int min, max;
  int offset,
      num_rate_control_possibilities,
      raw_value,
      raw_max_idx = 0,
      raw_min_idx = 0;
  int max_rate_categories[28];
  int min_rate_categories[28];
  int temp_category_balances[64];
  int *min_rate_ptr = NULL;
  int *max_rate_ptr = NULL;

  if (number_of_regions == 14) {
    num_rate_control_possibilities = 16;
    if ( number_of_available_bits > 320)
      number_of_available_bits = ((number_of_available_bits - 320) * 5/8) + 320;
  } else {
    num_rate_control_possibilities = 32;
    if (number_of_regions  == 28 && number_of_available_bits > 640)
      number_of_available_bits = ((number_of_available_bits - 640) * 5/8) + 640;
  }

  offset = -32;
  for (delta = 32; number_of_regions > 0 && delta > 0; delta /= 2) {
    expected_number_of_code_bits = 0;
    for (region = 0; region < number_of_regions; region++) {
      i = (delta + offset - absolute_region_power_index[region]) >> 1;
      if (i > 7)
        i = 7;
      else if (i < 0)
        i = 0;

      power_categories[region] = i;
      expected_number_of_code_bits += expected_bits_table[i];

    }
    if (expected_number_of_code_bits >= number_of_available_bits-32)
      offset += delta;
  }

  expected_number_of_code_bits = 0;
  for (region = 0; region  < number_of_regions; region++) {
    i = (offset - absolute_region_power_index[region]) >> 1;
    if (i > 7)
      i = 7;
    else if (i < 0)
      i = 0;
    max_rate_categories[region] = min_rate_categories[region] = power_categories[region] = i;
    expected_number_of_code_bits += expected_bits_table[i];
  }


  min = max = expected_number_of_code_bits;
  min_rate_ptr = max_rate_ptr = temp_category_balances + num_rate_control_possibilities;
  for (i = 0; i < num_rate_control_possibilities -1; i++) {
    if (min + max > number_of_available_bits * 2) {
      raw_value = -99;
      for (region = number_of_regions-1; region >= 0; region--) {
        if (min_rate_categories[region] < 7) {
          temp = offset - absolute_region_power_index[region] - 2*min_rate_categories[region];
          if (temp > raw_value) {
            raw_value = temp;
            raw_min_idx = region;
          }
        }
      }
      *min_rate_ptr++ = raw_min_idx;
      min += expected_bits_table[min_rate_categories[raw_min_idx] + 1] - expected_bits_table[min_rate_categories[raw_min_idx]];
      min_rate_categories[raw_min_idx]++;
    } else {
      raw_value = 99;
      for (region = 0; region < number_of_regions; region++) {
        if (max_rate_categories[region] > 0 ) {
          temp = offset - absolute_region_power_index[region] - 2*max_rate_categories[region];
          if (temp < raw_value) {
            raw_value = temp;
            raw_max_idx = region;
          }
        }
      }

      *--max_rate_ptr = raw_max_idx;
      max += expected_bits_table[max_rate_categories[raw_max_idx] - 1] - expected_bits_table[max_rate_categories[raw_max_idx]];
      max_rate_categories[raw_max_idx]--;
    }
  }

  for (region = 0; region < number_of_regions; region++)
    power_categories[region] = max_rate_categories[region];

  for (i = 0; i < num_rate_control_possibilities-1; i++)
    category_balance[i] = *max_rate_ptr++;


  return 0;
}



/*
  Looks like the flag means what kind of encoding is used
  for now, it looks like :
  0 : the sample rate is not encoded in the frame
  1 - 2 : the sample rate is fixed in the frame
  3 : sample rate is variable and there is one for each frame
*/

int GetSirenCodecInfo(int flag, int sample_rate, int *number_of_coefs, int *sample_rate_bits, int *rate_control_bits, int *rate_control_possibilities, int *checksum_bits, int *esf_adjustment, int *scale_factor, int *number_of_regions, int *sample_rate_code, int *bits_per_frame ) {
  switch (flag) {
    case 0:
      *number_of_coefs = 320;
      *sample_rate_bits = 0;
      *rate_control_bits = 4;
      *rate_control_possibilities = 16;
      *checksum_bits = 0;
      *esf_adjustment = 7;
      *number_of_regions = 14;
      *sample_rate_code = 0;
      *scale_factor = 22;
      break;
    case 1:
      *number_of_coefs = 320;
      *sample_rate_bits = 2;
      *rate_control_bits = 4;
      *rate_control_possibilities = 16;
      *checksum_bits = 4;
      *esf_adjustment = -2;
      *number_of_regions = 14;
      *scale_factor = 1;
      if (sample_rate == 16000)
        *sample_rate_code = 1;
      else if (sample_rate == 24000)
        *sample_rate_code = 2;
      else if (sample_rate == 32000)
        *sample_rate_code = 3;
      else
        return 3;
      break;
    case 2:
      *number_of_coefs = 640;
      *sample_rate_bits = 2;
      *rate_control_bits = 5;
      *rate_control_possibilities = 32;
      *checksum_bits = 4;
      *esf_adjustment = 7;
      *number_of_regions = 28;
      *scale_factor = 33;

      if (sample_rate == 24000)
        *sample_rate_code = 1;
      else if (sample_rate == 24000)
        *sample_rate_code = 2;
      else if (sample_rate == 48000)
        *sample_rate_code = 3;
      else
        return 3;

      break;
    case 3:
      *number_of_coefs = 640;
      *sample_rate_bits = 6;
      *rate_control_bits = 5;
      *rate_control_possibilities = 32;
      *checksum_bits = 4;
      *esf_adjustment = 7;
      *scale_factor = 33;

      switch (sample_rate) {
        case 8800:
          *number_of_regions = 12;
          *sample_rate_code = 59;
          break;
        case 9600:
          *number_of_regions = 12;
          *sample_rate_code = 1;
          break;
        case 10400:
          *number_of_regions = 12;
          *sample_rate_code = 13;
          break;
        case 10800:
          *number_of_regions = 12;
          *sample_rate_code = 14;
          break;
        case 11200:
          *number_of_regions = 12;
          *sample_rate_code = 15;
          break;
        case 11600:
          *number_of_regions = 12;
          *sample_rate_code = 16;
          break;
        case 12000:
          *number_of_regions = 12;
          *sample_rate_code = 2;
          break;
        case 12400:
          *number_of_regions = 12;
          *sample_rate_code = 17;
          break;
        case 12800:
          *number_of_regions = 12;
          *sample_rate_code = 18;
          break;
        case 13200:
          *number_of_regions = 12;
          *sample_rate_code = 19;
          break;
        case 13600:
          *number_of_regions = 12;
          *sample_rate_code = 20;
          break;
        case 14000:
          *number_of_regions = 12;
          *sample_rate_code = 21;
          break;
        case 14400:
          *number_of_regions = 16;
          *sample_rate_code = 3;
          break;
        case 14800:
          *number_of_regions = 16;
          *sample_rate_code = 22;
          break;
        case 15200:
          *number_of_regions = 16;
          *sample_rate_code = 23;
          break;
        case 15600:
          *number_of_regions = 16;
          *sample_rate_code = 24;
          break;
        case 16000:
          *number_of_regions = 16;
          *sample_rate_code = 25;
          break;
        case 16400:
          *number_of_regions = 16;
          *sample_rate_code = 26;
          break;
        case 16800:
          *number_of_regions = 18;
          *sample_rate_code = 4;
          break;
        case 17200:
          *number_of_regions = 18;
          *sample_rate_code = 27;
          break;
        case 17600:
          *number_of_regions = 18;
          *sample_rate_code = 28;
          break;
        case 18000:
          *number_of_regions = 18;
          *sample_rate_code = 29;
          break;
        case 18400:
          *number_of_regions = 18;
          *sample_rate_code = 30;
          break;
        case 18800:
          *number_of_regions = 18;
          *sample_rate_code = 31;
          break;
        case 19200:
          *number_of_regions = 20;
          *sample_rate_code = 5;
          break;
        case 19600:
          *number_of_regions = 20;
          *sample_rate_code = 32;
          break;
        case 20000:
          *number_of_regions = 20;
          *sample_rate_code = 33;
          break;
        case 20400:
          *number_of_regions = 20;
          *sample_rate_code = 34;
          break;
        case 20800:
          *number_of_regions = 20;
          *sample_rate_code = 35;
          break;
        case 21200:
          *number_of_regions = 20;
          *sample_rate_code = 36;
          break;
        case 21600:
          *number_of_regions = 22;
          *sample_rate_code = 6;
          break;
        case 22000:
          *number_of_regions = 22;
          *sample_rate_code = 37;
          break;
        case 22400:
          *number_of_regions = 22;
          *sample_rate_code = 38;
          break;
        case 22800:
          *number_of_regions = 22;
          *sample_rate_code = 39;
          break;
        case 23200:
          *number_of_regions = 22;
          *sample_rate_code = 40;
          break;
        case 23600:
          *number_of_regions = 22;
          *sample_rate_code = 41;
          break;
        case 24000:
          *number_of_regions = 24;
          *sample_rate_code = 7;
          break;
        case 24400:
          *number_of_regions = 24;
          *sample_rate_code = 42;
          break;
        case 24800:
          *number_of_regions = 24;
          *sample_rate_code = 43;
          break;
        case 25200:
          *number_of_regions = 24;
          *sample_rate_code = 44;
          break;
        case 25600:
          *number_of_regions = 24;
          *sample_rate_code = 45;
          break;
        case 26000:
          *number_of_regions = 24;
          *sample_rate_code = 46;
          break;
        case 26400:
          *number_of_regions = 26;
          *sample_rate_code = 8;
          break;
        case 26800:
          *number_of_regions = 26;
          *sample_rate_code = 47;
          break;
        case 27200:
          *number_of_regions = 26;
          *sample_rate_code = 48;
          break;
        case 27600:
          *number_of_regions = 26;
          *sample_rate_code = 49;
          break;
        case 28000:
          *number_of_regions = 26;
          *sample_rate_code = 50;
          break;
        case 28400:
          *number_of_regions = 26;
          *sample_rate_code = 51;
          break;
        case 28800:
          *number_of_regions = 28;
          *sample_rate_code = 9;
          break;
        case 29200:
          *number_of_regions = 28;
          *sample_rate_code = 52;
          break;
        case 29600:
          *number_of_regions = 28;
          *sample_rate_code = 53;
          break;
        case 30000:
          *number_of_regions = 28;
          *sample_rate_code = 54;
          break;
        case 30400:
          *number_of_regions = 28;
          *sample_rate_code = 55;
          break;
        case 30800:
          *number_of_regions = 28;
          *sample_rate_code = 56;
          break;
        case 31200:
          *number_of_regions = 28;
          *sample_rate_code = 10;
          break;
        case 31600:
          *number_of_regions = 28;
          *sample_rate_code = 57;
          break;
        case 32000:
          *number_of_regions = 28;
          *sample_rate_code = 58;
          break;
        default:
          return 3;
          break;
      }
      break;
    default:
      return 6;
  }

  *bits_per_frame  = sample_rate / 50;
  return 0;
}