text: /*
   * g722_1 - a library for the G.722.1 and Annex C codecs
   *
   * common.c
   *
   * Adapted by Steve Underwood <steveu@coppice.org> from the reference
   * code supplied with ITU G.722.1, which is:
   *
   *   (C) 2004 Polycom, Inc.
   *   All rights reserved.
   *
   * This program 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.
   */
  
  /*! \file */
  
  #if defined(HAVE_CONFIG_H)
  #include <config.h>
  #endif
  
  #include <inttypes.h>
  #include <stdlib.h>
  
  #include "g722_1/g722_1.h"
  
  #include "defs.h"
  #include "huff_tab.h"
  #include "tables.h"
  
  #if defined(G722_1_USE_FIXED_POINT)
  
  static void compute_raw_pow_categories(int16_t *power_categories,
                                         int16_t *rms_index,
                                         int16_t number_of_regions,
                                         int16_t offset);
  
  /* Compute a series of categorizations */
  void categorize(int16_t number_of_available_bits,
                  int16_t number_of_regions,
                  int16_t num_categorization_control_possibilities,
                  int16_t *rms_index,
                  int16_t *power_categories,
                  int16_t *category_balances)
  {
  
      int16_t offset;
      int16_t temp;
      int16_t frame_size;
  
      /* At higher bit rates, there is an increase for most categories in average bit
         consumption per region. We compensate for this by pretending we have fewer
         available bits. */
      frame_size = (number_of_regions == NUMBER_OF_REGIONS)  ?  DCT_LENGTH  :  MAX_DCT_LENGTH;
  
      temp = sub(number_of_available_bits, frame_size);
      if (temp > 0)
      {
          number_of_available_bits = sub(number_of_available_bits, frame_size);
          number_of_available_bits = (int16_t) L_mult0(number_of_available_bits, 5);
          number_of_available_bits = shr(number_of_available_bits, 3);
          number_of_available_bits = add(number_of_available_bits, frame_size);
      }
  
      /* calculate the offset using the original category assignments */
      offset = calc_offset(rms_index, number_of_regions, number_of_available_bits);
  
      /* compute the power categories based on the uniform offset */
      compute_raw_pow_categories(power_categories, rms_index, number_of_regions,offset);
  
      /* adjust the category assignments */
      /* compute the new power categories and category balances */
      comp_powercat_and_catbalance(power_categories ,category_balances, rms_index, number_of_available_bits, number_of_regions, num_categorization_control_possibilities, offset);
  }
  /*- End of function --------------------------------------------------------*/
  
  /* Compute the power_categories and the category balances */
  void comp_powercat_and_catbalance(int16_t *power_categories,
                                    int16_t *category_balances,
                                    int16_t *rms_index,
                                    int16_t number_of_available_bits,
                                    int16_t number_of_regions,
                                    int16_t num_categorization_control_possibilities,
                                    int16_t offset)
  {
      int16_t expected_number_of_code_bits;
      int16_t region;
      int16_t max_region;
      int16_t j;
      int16_t max_rate_categories[MAX_NUMBER_OF_REGIONS];
      int16_t min_rate_categories[MAX_NUMBER_OF_REGIONS];
      int16_t temp_category_balances[2*MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES];
      int16_t raw_max;
      int16_t raw_min;
      int16_t raw_max_index;
      int16_t raw_min_index;
      int16_t max_rate_pointer;
      int16_t min_rate_pointer;
      int16_t max;
      int16_t min;
      int16_t itemp0;
      int16_t itemp1;
      int16_t min_plus_max;
      int16_t two_x_number_of_available_bits;
      int16_t temp;
  
      expected_number_of_code_bits = 0;
      raw_max_index = 0;
      raw_min_index = 0;
  
      for (region = 0;  region < number_of_regions;  region++)
          expected_number_of_code_bits = add(expected_number_of_code_bits, expected_bits_table[power_categories[region]]);
  
      for (region = 0;  region < number_of_regions;  region++)
      {
          max_rate_categories[region] = power_categories[region];
          min_rate_categories[region] = power_categories[region];
      }
  
      max = expected_number_of_code_bits;
      min = expected_number_of_code_bits;
      max_rate_pointer = num_categorization_control_possibilities;
      min_rate_pointer = num_categorization_control_possibilities;
  
      for (j = 0;  j < num_categorization_control_possibilities - 1;  j++)
      {
          min_plus_max = add(max, min);
          two_x_number_of_available_bits = shl(number_of_available_bits, 1);
  
          temp = sub(min_plus_max, two_x_number_of_available_bits);
          if (temp <= 0)
          {
              raw_min = 99;
              /* Search from lowest freq regions to highest for best */
              /* region to reassign to a higher bit rate category.   */
              for (region = 0;  region < number_of_regions;  region++)
              {
                  if (max_rate_categories[region] > 0)
                  {
                      itemp0 = shl(max_rate_categories[region], 1);
                      itemp1 = sub(offset, rms_index[region]);
                      itemp0 = sub(itemp1, itemp0);
  
                      temp = sub(itemp0, raw_min);
                      if (temp < 0)
                      {
                          raw_min = itemp0;
                          raw_min_index = region;
                      }
                  }
              }
              max_rate_pointer = sub(max_rate_pointer, 1);
              temp_category_balances[max_rate_pointer] = raw_min_index;
  
              max = sub(max,expected_bits_table[max_rate_categories[raw_min_index]]);
              max_rate_categories[raw_min_index] = sub(max_rate_categories[raw_min_index], 1);
  
              max = add(max,expected_bits_table[max_rate_categories[raw_min_index]]);
          }
          else
          {
              raw_max = -99;
              /* Search from highest freq regions to lowest for best region to reassign to
              a lower bit rate category. */
              max_region = sub(number_of_regions, 1);
              for (region = max_region;  region >= 0;  region--)
              {
                  temp = sub(min_rate_categories[region], (NUM_CATEGORIES - 1));
                  if (temp < 0)
                  {
                      itemp0 = shl(min_rate_categories[region], 1);
                      itemp1 = sub(offset, rms_index[region]);
                      itemp0 = sub(itemp1, itemp0);
  
                      temp = sub(itemp0, raw_max);
                      if (temp > 0)
                      {
                          raw_max = itemp0;
                          raw_max_index = region;
                      }
                  }
              }
              temp_category_balances[min_rate_pointer] = raw_max_index;
              min_rate_pointer = add(min_rate_pointer, 1);
              min = sub(min, expected_bits_table[min_rate_categories[raw_max_index]]);
  
              min_rate_categories[raw_max_index] = add(min_rate_categories[raw_max_index], 1);
              min = add(min, expected_bits_table[min_rate_categories[raw_max_index]]);
          }
      }
  
      for (region = 0;  region < number_of_regions;  region++)
          power_categories[region] = max_rate_categories[region];
  
      for (j = 0;  j < num_categorization_control_possibilities - 1;  j++)
          category_balances[j] = temp_category_balances[max_rate_pointer++];
  }
  /*- End of function --------------------------------------------------------*/
  
  /* Calculate the the category offset. This is the shift required
     To get the most out of the number of available bits.  A binary
     type search is used to find the offset. */
  int16_t calc_offset(int16_t *rms_index, int16_t number_of_regions, int16_t available_bits)
  {
      int16_t answer;
      int16_t delta;
      int16_t test_offset;
      int16_t region;
      int16_t j;
      int16_t power_cats[MAX_NUMBER_OF_REGIONS];
      int16_t bits;
      int16_t offset;
      int16_t temp;
  
      /* initialize vars */
      answer = -32;
      delta = 32;
  
      do
      {
          test_offset = add(answer, delta);
  
          /* obtain a category for each region */
          /* using the test offset             */
          for (region = 0;  region < number_of_regions;  region++)
          {
              j = sub(test_offset, rms_index[region]);
              j = shr(j, 1);
  
              /* Ensure j is between 0 and NUM_CAT-1 */
              if (j < 0)
                  j = 0;
              temp = sub(j, NUM_CATEGORIES - 1);
              if (temp > 0)
                  j = sub(NUM_CATEGORIES, 1);
              power_cats[region] = j;
          }
          bits = 0;
  
          /* compute the number of bits that will be used given the cat assignments */
          for (region = 0;  region < number_of_regions;  region++)
              bits = add(bits, expected_bits_table[power_cats[region]]);
  
          /* If (bits > available_bits - 32) then divide the offset region for the bin search */
          offset = sub(available_bits, 32);
          temp = sub(bits, offset);
          if (temp >= 0)
              answer = test_offset;
          delta = shr(delta, 1);
      }
      while (delta > 0);
  
      return answer;
  }
  /*- End of function --------------------------------------------------------*/
  
  /* Compute the power categories given the offset
     This is kind of redundant since they were already computed
     in calc_offset to determine the offset. */
  static void compute_raw_pow_categories(int16_t *power_categories, int16_t *rms_index, int16_t number_of_regions, int16_t offset)
  {
      int16_t region;
      int16_t j;
      int16_t temp;
  
      for (region = 0;  region < number_of_regions;  region++)
      {
          j = sub(offset, rms_index[region]);
          j = shr(j, 1);
  
          /* make sure j is between 0 and NUM_CAT-1 */
          if (j < 0)
              j = 0;
          temp = sub(j, (NUM_CATEGORIES - 1));
          if (temp > 0)
              j = sub(NUM_CATEGORIES, 1);
  
          power_categories[region] = j;
      }
  }
  /*- End of function --------------------------------------------------------*/
  #endif
  /*- End of file ------------------------------------------------------------*/
  