[FFmpeg-devel] [TOY] Siren7 encoder/decoder using aMSN libsiren

Peter Ross pross at xvid.org
Tue Jul 17 14:51:36 CEST 2012


---
Crude wrapper around aMSN libsiren. Posted here for posterity.

 Changelog                             |    1 +
 MAINTAINERS                           |    1 +
 doc/general.texi                      |    2 +
 libavcodec/Makefile                   |    3 +
 libavcodec/allcodecs.c                |    1 +
 libavcodec/avcodec.h                  |    1 +
 libavcodec/libsiren7/common.c         |  505 +++++++++++++++++++++++++++++++
 libavcodec/libsiren7/common.h         |  144 +++++++++
 libavcodec/libsiren7/dct4.c           |  184 ++++++++++++
 libavcodec/libsiren7/dct4.h           |   30 ++
 libavcodec/libsiren7/decoder.c        |  234 +++++++++++++++
 libavcodec/libsiren7/decoder.h        |   52 ++++
 libavcodec/libsiren7/encoder.c        |  234 +++++++++++++++
 libavcodec/libsiren7/encoder.h        |   47 +++
 libavcodec/libsiren7/huffman.c        |  382 ++++++++++++++++++++++++
 libavcodec/libsiren7/huffman.h        |   35 +++
 libavcodec/libsiren7/huffman_consts.h |  528 +++++++++++++++++++++++++++++++++
 libavcodec/libsiren7/rmlt.c           |  133 +++++++++
 libavcodec/libsiren7/rmlt.h           |   30 ++
 libavcodec/libsiren7/siren7.h         |   30 ++
 libavcodec/libsiren7dec.c             |   95 ++++++
 libavcodec/libsiren7enc.c             |   94 ++++++
 libavformat/riff.c                    |    1 +
 23 files changed, 2767 insertions(+)
 create mode 100644 libavcodec/libsiren7/common.c
 create mode 100644 libavcodec/libsiren7/common.h
 create mode 100644 libavcodec/libsiren7/dct4.c
 create mode 100644 libavcodec/libsiren7/dct4.h
 create mode 100644 libavcodec/libsiren7/decoder.c
 create mode 100644 libavcodec/libsiren7/decoder.h
 create mode 100644 libavcodec/libsiren7/encoder.c
 create mode 100644 libavcodec/libsiren7/encoder.h
 create mode 100644 libavcodec/libsiren7/huffman.c
 create mode 100644 libavcodec/libsiren7/huffman.h
 create mode 100644 libavcodec/libsiren7/huffman_consts.h
 create mode 100644 libavcodec/libsiren7/rmlt.c
 create mode 100644 libavcodec/libsiren7/rmlt.h
 create mode 100644 libavcodec/libsiren7/siren7.h
 create mode 100644 libavcodec/libsiren7dec.c
 create mode 100644 libavcodec/libsiren7enc.c

diff --git a/Changelog b/Changelog
index e7b8a02..f8c7350 100644
--- a/Changelog
+++ b/Changelog
@@ -29,6 +29,7 @@ version next:
 - new option: -progress
 - 3GPP Timed Text decoder
 - GeoTIFF decoder support
+- Siren7 encoder/decoder using aMSN libsiren
 
 
 version 0.11:
diff --git a/MAINTAINERS b/MAINTAINERS
index 1a9f29b..d8792b8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -208,6 +208,7 @@ Codecs:
   rv3*                                  Kostya Shishkov
   rv4*                                  Kostya Shishkov
   s3tc*                                 Ivo van Poorten
+  siren7.c                              Peter Ross
   smacker.c                             Kostya Shishkov
   smc.c                                 Mike Melanson
   snow.c                                Michael Niedermayer, Loren Merritt
diff --git a/doc/general.texi b/doc/general.texi
index f390cb7..bdca37f 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -840,6 +840,8 @@ following image formats are supported:
 @item Shorten                @tab     @tab  X
 @item Sierra VMD audio       @tab     @tab  X
     @tab Used in Sierra VMD files.
+ at item Siren7                 @tab     @tab  X
+    @tab Used by Microsoft MSN Communicator
 @item Smacker audio          @tab     @tab  X
 @item SMPTE 302M AES3 audio  @tab     @tab  X
 @item Sonic                  @tab  X  @tab  X
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index bbe188a..8a0f9c5 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -687,6 +687,9 @@ OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER)    += libschroedingerdec.o \
                                              libschroedinger.o
 OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER)    += libschroedingerenc.o \
                                              libschroedinger.o
+LIBSIREN7=libsiren7/common.o libsiren7/dct4.o libsiren7/decoder.o libsiren7/encoder.o libsiren7/huffman.o libsiren7/rmlt.o
+OBJS-$(CONFIG_LIBSIREN7_DECODER)          += libsiren7dec.o $(LIBSIREN7)
+OBJS-$(CONFIG_LIBSIREN7_ENCODER)          += libsiren7enc.o $(LIBSIREN7)
 OBJS-$(CONFIG_LIBSPEEX_DECODER)           += libspeexdec.o
 OBJS-$(CONFIG_LIBSPEEX_ENCODER)           += libspeexenc.o audio_frame_queue.o
 OBJS-$(CONFIG_LIBSTAGEFRIGHT_H264_DECODER)+= libstagefright.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 3b18f57..35ae207 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -428,6 +428,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER (LIBOPENCORE_AMRWB, libopencore_amrwb);
     REGISTER_ENCDEC  (LIBOPENJPEG, libopenjpeg);
     REGISTER_ENCDEC  (LIBSCHROEDINGER, libschroedinger);
+    REGISTER_ENCDEC  (LIBSIREN7, libsiren7);
     REGISTER_ENCDEC  (LIBSPEEX, libspeex);
     REGISTER_DECODER (LIBSTAGEFRIGHT_H264, libstagefright_h264);
     REGISTER_ENCODER (LIBTHEORA, libtheora);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 3c18040..0f2772a 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -420,6 +420,7 @@ enum CodecID {
     CODEC_ID_SONIC       = MKBETAG('S','O','N','C'),
     CODEC_ID_SONIC_LS    = MKBETAG('S','O','N','L'),
     CODEC_ID_PAF_AUDIO   = MKBETAG('P','A','F','A'),
+    CODEC_ID_SIREN7,
 
     /* subtitle codecs */
     CODEC_ID_FIRST_SUBTITLE = 0x17000,          ///< A dummy ID pointing at the start of subtitle codecs.
diff --git a/libavcodec/libsiren7/common.c b/libavcodec/libsiren7/common.c
new file mode 100644
index 0000000..e5b2565
--- /dev/null
+++ b/libavcodec/libsiren7/common.c
@@ -0,0 +1,505 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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(void) {
+  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;
+}
+
diff --git a/libavcodec/libsiren7/common.h b/libavcodec/libsiren7/common.h
new file mode 100644
index 0000000..9743aa7
--- /dev/null
+++ b/libavcodec/libsiren7/common.h
@@ -0,0 +1,144 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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.
+ */
+
+
+#ifndef _SIREN_COMMON_H
+#define _SIREN_COMMON_H
+
+typedef struct {
+  unsigned int RiffId;
+  unsigned int RiffSize;
+} RiffHeader;
+
+typedef struct  {
+  unsigned short Format;
+  unsigned short Channels;
+  unsigned int SampleRate;
+  unsigned int ByteRate;
+  unsigned short BlockAlign;
+  unsigned short BitsPerSample;
+} FmtChunk;
+
+
+typedef struct  {
+  FmtChunk fmt;
+  unsigned short ExtraSize;
+  unsigned short DctLength;
+} SirenFmtChunk;
+
+typedef struct {
+  RiffHeader riff;
+  unsigned int WaveId;
+
+  unsigned int FmtId;
+  unsigned int FmtSize;
+
+  SirenFmtChunk fmt;
+
+  unsigned int FactId;
+  unsigned int FactSize;
+  unsigned int Samples;
+
+  unsigned int DataId;
+  unsigned int DataSize;
+} SirenWavHeader;
+
+typedef struct {
+  RiffHeader riff;
+  unsigned int WaveId;
+
+  unsigned int FmtId;
+  unsigned int FmtSize;
+
+  FmtChunk fmt;
+
+  unsigned int FactId;
+  unsigned int FactSize;
+  unsigned int Samples;
+
+  unsigned int DataId;
+  unsigned int DataSize;
+} PCMWavHeader;
+
+#define RIFF_ID 0x46464952
+#define WAVE_ID 0x45564157
+#define FMT__ID 0x20746d66
+#define DATA_ID 0x61746164
+#define FACT_ID 0x74636166
+
+
+extern int region_size;
+extern float region_size_inverse;
+extern float standard_deviation[64];
+extern float deviation_inverse[64];
+extern float region_power_table_boundary[63];
+extern int expected_bits_table[8];
+extern int vector_dimension[8];
+extern int number_of_vectors[8];
+extern float dead_zone[8];
+extern int max_bin[8];
+extern float step_size[8];
+extern float step_size_inverse[8];
+
+
+
+extern void siren_init(void);
+extern int categorize_regions(int number_of_regions, int number_of_available_bits, int *absolute_region_power_index, int *power_categories, int *category_balance);
+extern 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 );
+
+
+#ifdef __BIG_ENDIAN__
+
+#define POW_2_8 256
+#define POW_2_16 65536
+#define POW_2_24 16777216
+
+#define IDX(val, i) ((unsigned int) ((unsigned char *) &val)[i])
+
+
+
+#define ME_FROM_LE16(val) ( (unsigned short) ( IDX(val, 0) + IDX(val, 1) * 256 ))
+#define ME_FROM_LE32(val) ( (unsigned int) (IDX(val, 0) + IDX(val, 1) * 256 + \
+          IDX(val, 2) * 65536 + IDX(val, 3) * 16777216))
+
+
+#define ME_TO_LE16(val) ( (unsigned short) (                    \
+          (((unsigned short)val % 256) & 0xff) << 8 |           \
+          ((((unsigned short)val / POW_2_8) % 256) & 0xff) ))
+
+#define ME_TO_LE32(val) ( (unsigned int) (                              \
+          ((((unsigned int) val           ) % 256)  & 0xff) << 24 |     \
+          ((((unsigned int) val / POW_2_8 ) % 256) & 0xff) << 16|       \
+          ((((unsigned int) val / POW_2_16) % 256) & 0xff) << 8 |       \
+          ((((unsigned int) val / POW_2_24) % 256) & 0xff) ))
+
+#else
+
+#define ME_TO_LE16(val) ( (unsigned short) (val))
+#define ME_TO_LE32(val) ( (unsigned int) (val))
+#define ME_FROM_LE16(val) ( (unsigned short) (val))
+#define ME_FROM_LE32(val) ( (unsigned int) (val))
+
+
+#endif
+
+#endif /* _SIREN_COMMON_H */
+
diff --git a/libavcodec/libsiren7/dct4.c b/libavcodec/libsiren7/dct4.c
new file mode 100644
index 0000000..707c13b
--- /dev/null
+++ b/libavcodec/libsiren7/dct4.c
@@ -0,0 +1,184 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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"
+
+
+#define PI 3.1415926
+
+typedef struct {
+  float cos;
+  float msin;
+} dct_table_type;
+
+static float dct_core_320[100];
+static float dct_core_640[100];
+static dct_table_type dct_table_5[5];
+static dct_table_type dct_table_10[10];
+static dct_table_type dct_table_20[20];
+static dct_table_type dct_table_40[40];
+static dct_table_type dct_table_80[80];
+static dct_table_type dct_table_160[160];
+static dct_table_type dct_table_320[320];
+static dct_table_type dct_table_640[640];
+static dct_table_type *dct_tables[8] = {dct_table_5,
+                                        dct_table_10,
+                                        dct_table_20,
+                                        dct_table_40,
+                                        dct_table_80,
+                                        dct_table_160,
+                                        dct_table_320,
+                                        dct_table_640};
+
+static int dct4_initialized = 0;
+
+void siren_dct4_init(void) {
+  int i, j = 0;
+  double scale_320 = (float) sqrt(2.0/320);
+  double scale_640 = (float) sqrt(2.0/640);
+  double angle;
+  double scale;
+
+  /* set up dct4 tables */
+  for(i = 0; i < 10; i++) {
+    angle = (float) ((i + 0.5) *  PI);
+    for (j = 0 ; j < 10; j++) {
+      dct_core_320[(i*10)+j] = (float) (scale_320 * cos((j + 0.5) * angle / 10));
+      dct_core_640[(i*10)+j] = (float) (scale_640 * cos((j + 0.5) * angle / 10));
+    }
+  }
+
+  for(i = 0; i < 8; i++) {
+    scale = (float) (PI / ((5 << i) * 4));
+    for (j = 0 ; j < (5 << i); j++) {
+      angle = (float) (j + 0.5) * scale;
+      dct_tables[i][j].cos = (float) cos(angle);
+      dct_tables[i][j].msin = (float)  -sin(angle);
+    }
+  }
+
+  dct4_initialized = 1;
+}
+
+
+void siren_dct4(float *Source, float *Destination, int dct_length) {
+  int log_length = 0;
+  float * dct_core = NULL;
+  dct_table_type ** dct_table_ptr_ptr = NULL;
+  dct_table_type * dct_table_ptr = NULL;
+  float OutBuffer1[640];
+  float OutBuffer2[640];
+  float *Out_ptr;
+  float *NextOut_ptr;
+  float *In_Ptr = NULL;
+  float *In_Ptr_low = NULL;
+  float *In_Ptr_high = NULL;
+  float In_val_low;
+  float In_val_high;
+  float *Out_ptr_low = NULL;
+  float *Out_ptr_high = NULL;
+  float mult1, mult2, mult3, mult4, mult5, mult6, mult7, mult8, mult9, mult10;
+  int i,j;
+
+  if (dct4_initialized == 0)
+    siren_dct4_init();
+
+  if (dct_length == 640) {
+    log_length = 5;
+    dct_core = dct_core_640;
+  } else {
+    log_length = 4;
+    dct_core = dct_core_320;
+  }
+
+  Out_ptr = OutBuffer1;
+  NextOut_ptr = OutBuffer2;
+  In_Ptr = Source;
+  for (i = 0; i <= log_length; i++) {
+    for (j = 0; j < (1 << i); j++) {
+      Out_ptr_low = Out_ptr + (j * (dct_length >> i));
+      Out_ptr_high = Out_ptr + ( (j+1) * (dct_length >> i));
+      do {
+        In_val_low = *In_Ptr++;
+        In_val_high = *In_Ptr++;
+        *Out_ptr_low++ = In_val_low + In_val_high;
+        *--Out_ptr_high = In_val_low - In_val_high;
+      } while (Out_ptr_low < Out_ptr_high);
+    }
+
+    In_Ptr = Out_ptr;
+    Out_ptr = NextOut_ptr;
+    NextOut_ptr = In_Ptr;
+  }
+
+  for (i = 0; i < (2 << log_length); i++) {
+    for (j = 0 ; j < 10 ;  j ++) {
+      mult1 = In_Ptr[(i*10)] * dct_core[j*10];
+      mult2 = In_Ptr[(i*10) + 1] * dct_core[(j*10) + 1];
+      mult3 = In_Ptr[(i*10) + 2] * dct_core[(j*10) + 2];
+      mult4 = In_Ptr[(i*10) + 3] * dct_core[(j*10) + 3];
+      mult5 = In_Ptr[(i*10) + 4] * dct_core[(j*10) + 4];
+      mult6 = In_Ptr[(i*10) + 5] * dct_core[(j*10) + 5];
+      mult7 = In_Ptr[(i*10) + 6] * dct_core[(j*10) + 6];
+      mult8 = In_Ptr[(i*10) + 7] * dct_core[(j*10) + 7];
+      mult9 = In_Ptr[(i*10) + 8] * dct_core[(j*10) + 8];
+      mult10 = In_Ptr[(i*10) + 9] * dct_core[(j*10) + 9];
+      Out_ptr[(i*10)+j] = mult1 + mult2 + mult3 + mult4 +
+          mult5 + mult6 + mult7 + mult8 +
+          mult9 + mult10;
+    }
+  }
+
+
+  In_Ptr = Out_ptr;
+  Out_ptr = NextOut_ptr;
+  NextOut_ptr = In_Ptr;
+  dct_table_ptr_ptr = dct_tables;
+  for (i = log_length; i >= 0; i--) {
+    dct_table_ptr_ptr++;
+    for (j = 0; j < (1 << i); j++) {
+      dct_table_ptr = *dct_table_ptr_ptr;
+      if ( i == 0 )
+        Out_ptr_low = Destination + (j * (dct_length >> i));
+      else
+        Out_ptr_low = Out_ptr + (j * (dct_length >> i));
+
+      Out_ptr_high = Out_ptr_low + (dct_length >> i);
+
+      In_Ptr_low = In_Ptr + (j * (dct_length >> i));
+      In_Ptr_high = In_Ptr_low + (dct_length >> (i+1));
+      do {
+        *Out_ptr_low++ = (*In_Ptr_low * (*dct_table_ptr).cos) - (*In_Ptr_high * (*dct_table_ptr).msin);
+        *--Out_ptr_high = (*In_Ptr_high++ * (*dct_table_ptr).cos) + (*In_Ptr_low++ * (*dct_table_ptr).msin);
+        dct_table_ptr++;
+        *Out_ptr_low++ = (*In_Ptr_low * (*dct_table_ptr).cos) + (*In_Ptr_high * (*dct_table_ptr).msin);
+        *--Out_ptr_high = (*In_Ptr_low++ * (*dct_table_ptr).msin) - (*In_Ptr_high++ * (*dct_table_ptr).cos);
+        dct_table_ptr++;
+      } while (Out_ptr_low < Out_ptr_high);
+    }
+
+    In_Ptr = Out_ptr;
+    Out_ptr = NextOut_ptr;
+    NextOut_ptr = In_Ptr;
+  }
+
+}
diff --git a/libavcodec/libsiren7/dct4.h b/libavcodec/libsiren7/dct4.h
new file mode 100644
index 0000000..5bdd0e0
--- /dev/null
+++ b/libavcodec/libsiren7/dct4.h
@@ -0,0 +1,30 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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.
+ */
+
+
+#ifndef _SIREN7_DCT4_H_
+#define _SIREN7_DCT4_H_
+
+extern void siren_dct4_init(void);
+extern void siren_dct4(float *Source, float *Destination, int dct_length);
+
+
+#endif /* _SIREN7_DCT4_H_ */
diff --git a/libavcodec/libsiren7/decoder.c b/libavcodec/libsiren7/decoder.c
new file mode 100644
index 0000000..5a18389
--- /dev/null
+++ b/libavcodec/libsiren7/decoder.c
@@ -0,0 +1,234 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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"
+
+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;
+}
+
diff --git a/libavcodec/libsiren7/decoder.h b/libavcodec/libsiren7/decoder.h
new file mode 100644
index 0000000..a5614e3
--- /dev/null
+++ b/libavcodec/libsiren7/decoder.h
@@ -0,0 +1,52 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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.
+ */
+
+
+#ifndef _SIREN_DECODER_H
+#define _SIREN_DECODER_H
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "dct4.h"
+#include "rmlt.h"
+#include "common.h"
+
+
+typedef struct stSirenDecoder {
+	int sample_rate;
+	PCMWavHeader WavHeader;
+	float context[320];
+	float backup_frame[320];
+	int dw1;
+	int dw2;
+	int dw3;
+	int dw4;
+} * SirenDecoder;
+
+#include "huffman.h"
+
+/* MUST be 16000 to be compatible with MSN Voice clips (I think) */
+extern SirenDecoder Siren7_NewDecoder(int sample_rate);
+extern void Siren7_CloseDecoder(SirenDecoder decoder);
+extern int Siren7_DecodeFrame(SirenDecoder decoder, unsigned char *DataIn, unsigned char *DataOut);
+
+#endif /* _SIREN_DECODER_H */
diff --git a/libavcodec/libsiren7/encoder.c b/libavcodec/libsiren7/encoder.c
new file mode 100644
index 0000000..9d89eb5
--- /dev/null
+++ b/libavcodec/libsiren7/encoder.c
@@ -0,0 +1,234 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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"
+
+
+SirenEncoder Siren7_NewEncoder(int sample_rate) {
+  SirenEncoder encoder = (SirenEncoder) malloc(sizeof(struct stSirenEncoder));
+  encoder->sample_rate = sample_rate;
+
+  encoder->WavHeader.riff.RiffId = ME_TO_LE32(RIFF_ID);
+  encoder->WavHeader.riff.RiffSize = sizeof(SirenWavHeader) - 2*sizeof(int);
+  encoder->WavHeader.riff.RiffSize = ME_TO_LE32(encoder->WavHeader.riff.RiffSize);
+  encoder->WavHeader.WaveId = ME_TO_LE32(WAVE_ID);
+
+  encoder->WavHeader.FmtId = ME_TO_LE32(FMT__ID);
+  encoder->WavHeader.FmtSize = ME_TO_LE32(sizeof(SirenFmtChunk));
+
+  encoder->WavHeader.fmt.fmt.Format = ME_TO_LE16(0x028E);
+  encoder->WavHeader.fmt.fmt.Channels = ME_TO_LE16(1);
+  encoder->WavHeader.fmt.fmt.SampleRate = ME_TO_LE32(16000);
+  encoder->WavHeader.fmt.fmt.ByteRate = ME_TO_LE32(2000);
+  encoder->WavHeader.fmt.fmt.BlockAlign = ME_TO_LE16(40);
+  encoder->WavHeader.fmt.fmt.BitsPerSample = ME_TO_LE16(0);
+  encoder->WavHeader.fmt.ExtraSize = ME_TO_LE16(2);
+  encoder->WavHeader.fmt.DctLength = ME_TO_LE16(320);
+
+  encoder->WavHeader.FactId = ME_TO_LE32(FACT_ID);
+  encoder->WavHeader.FactSize = ME_TO_LE32(sizeof(int));
+  encoder->WavHeader.Samples = ME_TO_LE32(0);
+
+  encoder->WavHeader.DataId = ME_TO_LE32(DATA_ID);
+  encoder->WavHeader.DataSize = ME_TO_LE32(0);
+
+  memset(encoder->context, 0, sizeof(encoder->context));
+
+  siren_init();
+  return encoder;
+}
+
+void Siren7_CloseEncoder(SirenEncoder encoder) {
+  free(encoder);
+}
+
+
+
+int Siren7_EncodeFrame(SirenEncoder encoder, 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 sample_rate = encoder->sample_rate;
+
+  static int absolute_region_power_index[28] = {0};
+  static int power_categories[28] = {0};
+  static int category_balance[28] = {0};
+  static int drp_num_bits[30] = {0};
+  static int drp_code_bits[30] = {0};
+  static int region_mlt_bit_counts[28] = {0};
+  static int region_mlt_bits[112] = {0};
+  int ChecksumTable[4] = {0x7F80, 0x7878, 0x6666, 0x5555};
+  int i, j;
+
+  int dwRes = 0;
+  short out_word;
+  int bits_left;
+  int current_word_bits_left;
+  int region_bit_count;
+  unsigned int current_word;
+  unsigned int sum;
+  unsigned int checksum;
+  int temp1 = 0;
+  int temp2 = 0;
+  int region;
+  int idx = 0;
+  int envelope_bits = 0;
+  int rate_control;
+  int number_of_available_bits;
+
+  float coefs[320];
+  float In[320];
+  short BufferOut[20];
+  float *context = encoder->context;
+
+  for (i = 0; i < 320; i++)
+    In[i] = (float) ((short) ME_FROM_LE16(((short *) DataIn)[i]));
+
+  dwRes = siren_rmlt_encode_samples(In, context, 320, coefs);
+
+
+  if (dwRes != 0)
+    return dwRes;
+
+  dwRes = GetSirenCodecInfo(1, 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;
+
+  envelope_bits = compute_region_powers(number_of_regions, coefs, drp_num_bits, drp_code_bits, absolute_region_power_index, esf_adjustment);
+
+  number_of_available_bits = bits_per_frame - rate_control_bits - envelope_bits - sample_rate_bits  - checksum_bits ;
+
+  categorize_regions(number_of_regions, number_of_available_bits, absolute_region_power_index, power_categories, category_balance);
+
+  for(region = 0; region < number_of_regions; region++) {
+    absolute_region_power_index[region] += 24;
+    region_mlt_bit_counts[region] = 0;
+  }
+
+  rate_control = quantize_mlt(number_of_regions, rate_control_possibilities, number_of_available_bits, coefs, absolute_region_power_index, power_categories, category_balance, region_mlt_bit_counts, region_mlt_bits);
+
+  idx = 0;
+  bits_left = 16 - sample_rate_bits;
+  out_word = sample_rate_code << (16 - sample_rate_bits);
+  drp_num_bits[number_of_regions] = rate_control_bits;
+  drp_code_bits[number_of_regions] = rate_control;
+  for (region = 0; region <= number_of_regions; region++) {
+    i = drp_num_bits[region] - bits_left;
+    if (i < 0) {
+      out_word += drp_code_bits[region] << -i;
+      bits_left -= drp_num_bits[region];
+    } else {
+      BufferOut[idx++] = out_word + (drp_code_bits[region] >> i);
+      bits_left += 16 - drp_num_bits[region];
+      out_word = drp_code_bits[region] << bits_left;
+    }
+  }
+
+  for (region = 0; region < number_of_regions && (16*idx) < bits_per_frame; region++) {
+    current_word_bits_left = region_bit_count = region_mlt_bit_counts[region];
+    if (current_word_bits_left > 32)
+      current_word_bits_left = 32;
+
+    current_word = region_mlt_bits[region*4];
+    i = 1;
+    while(region_bit_count > 0 && (16*idx) < bits_per_frame) {
+      if (current_word_bits_left < bits_left) {
+        bits_left -= current_word_bits_left;
+        out_word += (current_word >> (32 - current_word_bits_left)) << bits_left;
+        current_word_bits_left = 0;
+      } else {
+        BufferOut[idx++] = (short) (out_word + (current_word >> (32 - bits_left)));
+        current_word_bits_left -= bits_left;
+        current_word <<= bits_left;
+        bits_left = 16;
+        out_word = 0;
+      }
+      if (current_word_bits_left == 0) {
+        region_bit_count -= 32;
+        current_word = region_mlt_bits[(region*4) + i++];
+        current_word_bits_left = region_bit_count;
+        if (current_word_bits_left > 32)
+          current_word_bits_left = 32;
+      }
+    }
+  }
+
+
+  while ( (16*idx) < bits_per_frame) {
+    BufferOut[idx++] = (short) ((0xFFFF >> (16 - bits_left)) + out_word);
+    bits_left = 16;
+    out_word = 0;
+  }
+
+  if (checksum_bits > 0) {
+    BufferOut[idx-1] &= (-1 << checksum_bits);
+    sum = 0;
+    idx = 0;
+    do {
+      sum ^= (BufferOut[idx] & 0xFFFF) << (idx % 15);
+    } while ((16*++idx) < bits_per_frame);
+
+    sum = (sum >> 15) ^ (sum & 0x7FFF);
+    checksum = 0;
+    for (i = 0; i < 4; i++) {
+      temp1 = ChecksumTable[i] & sum;
+      for (j = 8; j > 0; j >>= 1) {
+        temp2 = temp1 >> j;
+        temp1 ^= temp2;
+      }
+      checksum <<= 1;
+      checksum |= temp1 & 1;
+    }
+    BufferOut[idx-1] |= ((1 << checksum_bits) -1) & checksum;
+  }
+
+
+  for (i = 0; i < 20; i++)
+#ifdef __BIG_ENDIAN__
+    ((short *) DataOut)[i] = BufferOut[i];
+#else
+  ((short *) DataOut)[i] = ((BufferOut[i] << 8) & 0xFF00) | ((BufferOut[i] >> 8) & 0x00FF);
+#endif
+
+  encoder->WavHeader.Samples = ME_FROM_LE32(encoder->WavHeader.Samples);
+  encoder->WavHeader.Samples += 320;
+  encoder->WavHeader.Samples = ME_TO_LE32(encoder->WavHeader.Samples);
+  encoder->WavHeader.DataSize = ME_FROM_LE32(encoder->WavHeader.DataSize);
+  encoder->WavHeader.DataSize += 40;
+  encoder->WavHeader.DataSize = ME_TO_LE32(encoder->WavHeader.DataSize);
+  encoder->WavHeader.riff.RiffSize = ME_FROM_LE32(encoder->WavHeader.riff.RiffSize);
+  encoder->WavHeader.riff.RiffSize += 40;
+  encoder->WavHeader.riff.RiffSize = ME_TO_LE32(encoder->WavHeader.riff.RiffSize);
+
+
+  return 0;
+}
+
diff --git a/libavcodec/libsiren7/encoder.h b/libavcodec/libsiren7/encoder.h
new file mode 100644
index 0000000..a53185c
--- /dev/null
+++ b/libavcodec/libsiren7/encoder.h
@@ -0,0 +1,47 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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.
+ */
+
+
+#ifndef _SIREN_ENCODER_H
+#define _SIREN_ENCODER_H
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "dct4.h"
+#include "rmlt.h"
+#include "huffman.h"
+#include "common.h"
+
+
+typedef struct stSirenEncoder {
+	int sample_rate;
+	SirenWavHeader WavHeader;
+	float context[320];
+} * SirenEncoder;
+
+/* sample_rate MUST be 16000 to be compatible with MSN Voice clips (I think) */
+extern SirenEncoder Siren7_NewEncoder(int sample_rate);
+extern void Siren7_CloseEncoder(SirenEncoder encoder);
+extern int Siren7_EncodeFrame(SirenEncoder encoder, unsigned char *DataIn, unsigned char *DataOut);
+
+
+#endif /* _SIREN_ENCODER_H */
diff --git a/libavcodec/libsiren7/huffman.c b/libavcodec/libsiren7/huffman.c
new file mode 100644
index 0000000..e53af8d
--- /dev/null
+++ b/libavcodec/libsiren7/huffman.c
@@ -0,0 +1,382 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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"
+#include "huffman_consts.h"
+
+
+static short current_word = 0;
+static int bit_idx = 0;
+static int *bitstream_ptr = NULL;
+
+int next_bit(void) {
+  if (bitstream_ptr == NULL)
+    return -1;
+
+  if (bit_idx == 0) {
+    current_word = *bitstream_ptr++;
+    bit_idx = 16;
+  }
+
+  return (current_word >> --bit_idx) & 1;
+}
+
+void set_bitstream(int *stream) {
+  bitstream_ptr = stream;
+  current_word =  *bitstream_ptr;
+  bit_idx = 0;
+}
+
+
+int compute_region_powers(int number_of_regions, float *coefs, int *drp_num_bits, int *drp_code_bits, int *absolute_region_power_index, int esf_adjustment) {
+  float region_power = 0;
+  int num_bits;
+  int idx;
+  int max_idx, min_idx;
+  int region, i;
+
+  for (region = 0; region < number_of_regions; region++) {
+    region_power = 0.0f;
+    for (i = 0 ; i < region_size; i++) {
+      region_power += coefs[(region*region_size)+i] * coefs[(region*region_size)+i];
+    }
+    region_power *= region_size_inverse;
+
+    min_idx = 0;
+    max_idx = 64;
+    for (i = 0; i < 6; i++) {
+      idx = (min_idx + max_idx) / 2;
+      if (region_power_table_boundary[idx-1] <= region_power) {
+        min_idx = idx;
+      } else {
+        max_idx = idx;
+      }
+    }
+    absolute_region_power_index[region] = min_idx - 24;
+
+  }
+
+  for (region = number_of_regions-2; region >= 0; region--) {
+    if (absolute_region_power_index[region] < absolute_region_power_index[region+1] - 11)
+      absolute_region_power_index[region] = absolute_region_power_index[region+1] - 11;
+  }
+
+  if (absolute_region_power_index[0] < (1-esf_adjustment))
+    absolute_region_power_index[0] = (1-esf_adjustment);
+
+  if (absolute_region_power_index[0] > (31-esf_adjustment))
+    absolute_region_power_index[0] = (31-esf_adjustment);
+
+  drp_num_bits[0] = 5;
+  drp_code_bits[0] = absolute_region_power_index[0] + esf_adjustment;
+
+
+  for(region = 1; region < number_of_regions; region++) {
+    if (absolute_region_power_index[region] < (-8 - esf_adjustment))
+      absolute_region_power_index[region] = (-8 - esf_adjustment);
+    if (absolute_region_power_index[region] > (31-esf_adjustment))
+      absolute_region_power_index[region] = (31-esf_adjustment);
+  }
+
+  num_bits = 5;
+
+  for(region = 0; region < number_of_regions-1; region++) {
+    idx = absolute_region_power_index[region+1] - absolute_region_power_index[region] + 12;
+    if (idx < 0)
+      idx = 0;
+
+    absolute_region_power_index[region+1] = absolute_region_power_index[region] + idx - 12;
+    drp_num_bits[region+1] = differential_region_power_bits[region][idx];
+    drp_code_bits[region+1] = differential_region_power_codes[region][idx];
+    num_bits += drp_num_bits[region+1];
+  }
+
+  return num_bits;
+}
+
+
+int decode_envelope(int number_of_regions, float *decoder_standard_deviation, int *absolute_region_power_index, int esf_adjustment) {
+  int index;
+  int i;
+  int envelope_bits = 0;
+
+  index = 0;
+  for (i = 0; i < 5; i++)
+    index = (index<<1) | next_bit();
+  envelope_bits = 5;
+
+  absolute_region_power_index[0] = index - esf_adjustment;
+  decoder_standard_deviation[0] = standard_deviation[absolute_region_power_index[0] + 24];
+
+  for (i = 1; i < number_of_regions; i++) {
+    index = 0;
+    do {
+      index = differential_decoder_tree[i-1][index][next_bit()];
+      envelope_bits++;
+    } while (index > 0);
+
+    absolute_region_power_index[i] = absolute_region_power_index[i-1] - index - 12;
+    decoder_standard_deviation[i] = standard_deviation[absolute_region_power_index[i] + 24];
+  }
+
+  return envelope_bits;
+}
+
+
+
+static int huffman_vector(int category, int power_idx, float *mlts, int *out) {
+  int i, j;
+  float temp_value = deviation_inverse[power_idx] * step_size_inverse[category];
+  int sign_idx, idx, non_zeroes, max, bits_available;
+  int current_word = 0;
+  int region_bits = 0;
+
+  bits_available = 32;
+  for (i = 0; i < number_of_vectors[category]; i++) {
+    sign_idx = idx = non_zeroes = 0;
+    for (j = 0; j < vector_dimension[category]; j++) {
+      max = (int) ((fabs(*mlts) * temp_value) + dead_zone[category]);
+      if (max != 0) {
+        sign_idx <<= 1;
+        non_zeroes++;
+        if (*mlts  > 0)
+          sign_idx++;
+        if (max > max_bin[category] || max < 0)
+          max = max_bin[category];
+
+      }
+      mlts++;
+      idx = (idx * (max_bin[category] + 1)) + max;
+    }
+
+    region_bits += bitcount_tables[category][idx] + non_zeroes;
+    bits_available -= bitcount_tables[category][idx] + non_zeroes;
+    if (bits_available < 0) {
+      *out++ = current_word + (((code_tables[category][idx] << non_zeroes) + sign_idx) >> -bits_available);
+      bits_available += 32;
+      current_word =  ((code_tables[category][idx] << non_zeroes) + sign_idx) << bits_available;
+    } else {
+      current_word += ((code_tables[category][idx] << non_zeroes) + sign_idx) << bits_available;
+    }
+
+  }
+
+  *out = current_word;
+  return region_bits;
+}
+
+int quantize_mlt(int number_of_regions, int rate_control_possibilities, int number_of_available_bits, float *coefs, int *absolute_region_power_index, int *power_categories, int *category_balance, int *region_mlt_bit_counts, int *region_mlt_bits) {
+  int region;
+  int mlt_bits = 0;
+  int rate_control;
+
+  for (rate_control = 0; rate_control < ((rate_control_possibilities >> 1) - 1); rate_control++)
+    power_categories[category_balance[rate_control]]++;
+
+  for (region = 0; region < number_of_regions; region++) {
+    if (power_categories[region] > 6)
+      region_mlt_bit_counts[region] = 0;
+    else
+      region_mlt_bit_counts[region] = huffman_vector(power_categories[region], absolute_region_power_index[region], coefs + (region_size * region),
+          region_mlt_bits + (4*region));
+    mlt_bits += region_mlt_bit_counts[region];
+  }
+
+  while (mlt_bits < number_of_available_bits && rate_control > 0) {
+    rate_control--;
+    region = category_balance[rate_control];
+    power_categories[region]--;
+
+    if (power_categories[region] < 0)
+      power_categories[region] = 0;
+
+    mlt_bits -= region_mlt_bit_counts[region];
+
+    if (power_categories[region] > 6)
+      region_mlt_bit_counts[region] = 0;
+    else
+      region_mlt_bit_counts[region] = huffman_vector(power_categories[region], absolute_region_power_index[region], coefs + (region_size * region),
+          region_mlt_bits + (4*region));
+
+    mlt_bits += region_mlt_bit_counts[region];
+  }
+
+  while(mlt_bits > number_of_available_bits && rate_control < rate_control_possibilities) {
+    region = category_balance[rate_control];
+    power_categories[region]++;
+    mlt_bits -= region_mlt_bit_counts[region];
+
+    if (power_categories[region] > 6)
+      region_mlt_bit_counts[region] = 0;
+    else
+      region_mlt_bit_counts[region] = huffman_vector(power_categories[region], absolute_region_power_index[region], coefs + (region_size * region),
+          region_mlt_bits + (4*region));
+
+    mlt_bits += region_mlt_bit_counts[region];
+
+    rate_control++;
+  }
+
+  return rate_control;
+}
+
+static int get_dw(SirenDecoder decoder) {
+  int ret = decoder->dw1 + decoder->dw4;
+
+  if ((ret & 0x8000) != 0)
+    ret++;
+
+  decoder->dw1 = decoder->dw2;
+  decoder->dw2 = decoder->dw3;
+  decoder->dw3 = decoder->dw4;
+  decoder->dw4 = ret;
+
+  return ret;
+}
+
+
+
+
+int decode_vector(SirenDecoder decoder, int number_of_regions, int number_of_available_bits, float *decoder_standard_deviation, int *power_categories, float *coefs, int scale_factor) {
+  float *coefs_ptr;
+  float decoded_value;
+  float noise;
+  int *decoder_tree;
+
+  int region;
+  int category;
+  int i, j;
+  int index;
+  int error;
+  int dw1;
+  int dw2;
+
+  error = 0;
+  for (region = 0; region < number_of_regions; region++) {
+    category = power_categories[region];
+    coefs_ptr = coefs + (region * region_size);
+
+    if (category < 7) {
+      decoder_tree = decoder_tables[category];
+
+      for (i = 0; i < number_of_vectors[category]; i++) {
+        index = 0;
+        do {
+          if (number_of_available_bits <= 0) {
+            error = 1;
+            break;
+          }
+
+          index = decoder_tree[index + next_bit()];
+          number_of_available_bits--;
+        } while ((index & 1) == 0);
+
+        index >>= 1;
+
+        if (error == 0 && number_of_available_bits >= 0) {
+          for (j = 0; j < vector_dimension[category]; j++) {
+            decoded_value = mlt_quant[category][index & ((1 << index_table[category]) - 1)];
+            index >>= index_table[category];
+
+            if (decoded_value != 0) {
+              if (next_bit() == 0)
+                decoded_value *= -decoder_standard_deviation[region];
+              else
+                decoded_value *= decoder_standard_deviation[region];
+              number_of_available_bits--;
+            }
+
+            *coefs_ptr++ = decoded_value * scale_factor;
+          }
+        } else {
+          error = 1;
+          break;
+        }
+      }
+
+      if (error == 1) {
+        for (j = region + 1; j < number_of_regions; j++)
+          power_categories[j] = 7;
+        category = 7;
+      }
+    }
+
+
+    coefs_ptr = coefs + (region * region_size);
+
+    if (category == 5) {
+      i = 0;
+      for (j = 0; j < region_size; j++) {
+        if (*coefs_ptr != 0) {
+          i++;
+          if (fabs(*coefs_ptr) > 2.0 * decoder_standard_deviation[region]) {
+            i += 3;
+          }
+        }
+        coefs_ptr++;
+      }
+
+      noise = decoder_standard_deviation[region] * noise_category5[i];
+    } else if (category == 6) {
+      i = 0;
+      for (j = 0; j < region_size; j++) {
+        if (*coefs_ptr++ != 0)
+          i++;
+      }
+
+      noise = decoder_standard_deviation[region] * noise_category6[i];
+    } else if (category == 7) {
+      noise =  decoder_standard_deviation[region] * noise_category7;
+    } else {
+      noise = 0;
+    }
+
+    coefs_ptr = coefs + (region * region_size);
+
+    if (category == 5 || category == 6 || category == 7) {
+      dw1 = get_dw(decoder);
+      dw2 = get_dw(decoder);
+
+      for (j=0; j<10; j++) {
+        if (category == 7 || *coefs_ptr == 0) {
+          if ((dw1 & 1))
+            *coefs_ptr = noise;
+          else
+            *coefs_ptr = -noise;
+        }
+        coefs_ptr++;
+        dw1 >>= 1;
+
+        if (category == 7 || *coefs_ptr == 0) {
+          if ((dw2 & 1))
+            *coefs_ptr = noise;
+          else
+            *coefs_ptr = -noise;
+        }
+        coefs_ptr++;
+        dw2 >>= 1;
+      }
+    }
+  }
+
+  return error == 1 ? -1 : number_of_available_bits;
+}
diff --git a/libavcodec/libsiren7/huffman.h b/libavcodec/libsiren7/huffman.h
new file mode 100644
index 0000000..ea4fab0
--- /dev/null
+++ b/libavcodec/libsiren7/huffman.h
@@ -0,0 +1,35 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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.
+ */
+
+#ifndef _SIREN7_HUFFMAN_H_
+#define _SIREN7_HUFFMAN_H_
+
+#include "decoder.h"
+
+extern int compute_region_powers(int number_of_regions, float *coefs, int *drp_num_bits, int *drp_code_bits, int *absolute_region_power_index, int esf_adjustment);
+extern int quantize_mlt(int number_of_regions, int rate_control_possibilities, int number_of_available_bits, float *coefs, int *absolute_region_power_index, int *power_categories, int *category_balance, int *region_mlt_bit_counts, int *region_mlt_bits);
+extern int decode_envelope(int number_of_regions, float *decoder_standard_deviation, int *absolute_region_power_index, int esf_adjustment);
+extern int decode_vector(SirenDecoder decoder, int number_of_regions, int number_of_available_bits, float *decoder_standard_deviation, int *power_categories, float *coefs, int scale_factor);
+
+extern void set_bitstream(int *stream);
+extern int next_bit(void);
+
+#endif /* _SIREN7_HUFFMAN_H_ */
diff --git a/libavcodec/libsiren7/huffman_consts.h b/libavcodec/libsiren7/huffman_consts.h
new file mode 100644
index 0000000..0a38c0b
--- /dev/null
+++ b/libavcodec/libsiren7/huffman_consts.h
@@ -0,0 +1,528 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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.
+ */
+
+
+#ifndef _HUFFMAN_CONSTS_H
+#define _HUFFMAN_CONSTS_H
+
+
+static int differential_region_power_bits[28][24] = {
+  {4, 6, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 5, 7, 8, 9, 11, 11, 12, 12, 12, 12},
+  {10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 7, 9, 11, 12, 13, 15, 15, 15, 16, 16},
+  {12, 10, 8, 6, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 5, 5, 7, 9, 11, 13, 14, 14},
+  {13, 10, 9, 9, 7, 7, 5, 5, 4, 3, 3, 3, 3, 3, 4, 4, 4, 5, 7, 9, 11, 13, 13, 13},
+  {12, 13, 10, 8, 6, 6, 5, 5, 4, 4, 3, 3, 3, 3, 3, 4, 5, 5, 6, 7, 9, 11, 14, 14},
+  {12, 11, 9, 8, 8, 7, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 5, 7, 8, 10, 13, 14, 14},
+  {15, 16, 15, 12, 10, 8, 6, 5, 4, 3, 3, 3, 2, 3, 4, 5, 5, 7, 9, 11, 13, 16, 16, 16},
+  {14, 14, 11, 10, 9, 7, 7, 5, 5, 4, 3, 3, 2, 3, 3, 4, 5, 7, 9, 9, 12, 14, 15, 15},
+  {9, 9, 9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 13},
+  {14, 12, 10, 8, 6, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 8, 8, 9, 11, 14, 14, 14},
+  {13, 10, 9, 8, 6, 6, 5, 4, 4, 4, 3, 3, 2, 3, 4, 5, 6, 8, 9, 9, 11, 12, 14, 14},
+  {16, 13, 12, 11, 9, 6, 5, 5, 4, 4, 4, 3, 2, 3, 3, 4, 5, 7, 8, 10, 14, 16, 16, 16},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14},
+  {13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14}
+};
+
+
+static int differential_region_power_codes[28][24] = {
+  {8, 38, 18, 10, 7, 6, 3, 2, 0, 1, 7, 6, 5, 4, 11, 78, 158, 318, 1278, 1279, 2552, 2553, 2554, 2555},
+  {36, 8, 3, 5, 0, 1, 7, 6, 4, 3, 2, 5, 3, 4, 5, 19, 74, 150, 302, 1213, 1214, 1215, 2424, 2425},
+  {2582, 644, 160, 41, 5, 11, 7, 5, 4, 1, 0, 6, 4, 7, 3, 6, 4, 21, 81, 323, 1290, 5167, 10332, 10333},
+  {2940, 366, 181, 180, 47, 46, 27, 10, 8, 5, 1, 0, 3, 7, 4, 9, 12, 26, 44, 182, 734, 2941, 2942, 2943},
+  {3982, 7967, 994, 249, 63, 26, 19, 18, 14, 8, 6, 1, 0, 2, 5, 7, 12, 30, 27, 125, 496, 1990, 15932, 15933},
+  {3254, 1626, 407, 206, 202, 100, 30, 14, 3, 5, 3, 0, 2, 4, 2, 13, 24, 31, 102, 207, 812, 6511, 13020, 13021},
+  {1110, 2216, 1111, 139, 35, 9, 3, 20, 11, 4, 2, 1, 3, 3, 1, 0, 21, 5, 16, 68, 276, 2217, 2218, 2219},
+  {1013, 1014, 127, 62, 29, 6, 4, 16, 0, 1, 3, 2, 3, 1, 5, 9, 17, 5, 28, 30, 252, 1015, 2024, 2025},
+  {381, 380, 372, 191, 94, 44, 16, 10, 7, 3, 1, 0, 2, 6, 9, 17, 45, 92, 187, 746, 1494, 2991, 5980, 5981},
+  {3036, 758, 188, 45, 43, 10, 4, 3, 6, 4, 2, 0, 3, 7, 11, 20, 42, 44, 46, 95, 378, 3037, 3038, 3039},
+  {751, 92, 45, 20, 26, 4, 12, 7, 4, 0, 4, 1, 3, 5, 5, 3, 27, 21, 44, 47, 186, 374, 1500, 1501},
+  {45572, 5697, 2849, 1425, 357, 45, 23, 6, 10, 7, 2, 2, 3, 0, 4, 6, 7, 88, 179, 713, 11392, 45573, 45574, 45575},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021},
+  {2511, 5016, 5018, 5017, 312, 79, 38, 36, 30, 14, 6, 0, 2, 1, 3, 5, 8, 31, 37, 157, 626, 5019, 5020, 5021}
+};
+
+
+static int bitcount_table_category0[196] = {
+  1, 4, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, 11, 11, 4, 5, 6, 7, 7, 8, 8,
+  9, 9, 9, 9, 10, 11, 11, 5, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11,
+  12, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 12, 13, 7, 7, 8, 9, 9,
+  9, 10, 10, 10, 10, 11, 11, 12, 13, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11,
+  11, 12, 13, 14, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 15, 8,
+  8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 14, 15, 9, 9, 9, 10, 10, 10,
+  11, 11, 12, 13, 12, 14, 15, 16, 9, 9, 10, 10, 10, 10, 11, 12, 12, 14,
+  14, 16, 16, 16, 9, 9, 10, 10, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16,
+  10, 10, 10, 11, 11, 12, 12, 13, 15, 15, 16, 14, 15, 15, 11, 11, 11, 12,
+  13, 13, 13, 15, 16, 16, 16, 16, 14, 15, 11, 11, 12, 13, 13, 14, 15, 16,
+  16, 16, 16, 16, 16, 14};
+
+static int code_table_category0[196] = {
+  1, 2, 1, 24, 14, 51, 9, 68, 110, 26, 218, 54, 154, 761, 3, 10, 22, 8, 58,
+  22, 71, 16, 30, 50, 213, 75, 94, 632, 15, 18, 52, 23, 107, 5, 54, 63, 239,
+  46, 276, 271, 851, 252, 28, 10, 12, 1, 22, 133, 191, 55, 105, 278, 317, 554,
+  310, 276, 32, 50, 94, 20, 187, 219, 13, 268, 473, 445, 145, 849, 1277, 623,
+  1, 14, 0, 55, 238, 121, 120, 269, 318, 530, 639, 1117, 509, 556, 24, 78, 51,
+  153, 62, 308, 16, 25, 68, 1058, 428, 277, 2233, 1114, 92, 108, 141, 223, 270,
+  381, 24, 212, 760, 35, 1063, 279, 1717, 3439, 7, 21, 152, 73, 309, 310, 95, 944,
+  1890, 2232, 1891, 5107, 10213, 4981, 61, 62, 9, 79, 474, 475, 848, 1059, 1056, 1716,
+  139, 4978, 4983, 4983, 140, 186, 76, 444, 144, 633, 1057, 838, 2237, 4472, 4473,
+  10212, 10212, 4983, 74, 78, 311, 213, 850, 1062, 1119, 508, 276, 277, 4982, 4473,
+  10212, 10212, 208, 70, 555, 418, 68, 510, 2552, 1115, 4980, 4979, 4982, 4982, 4473,
+  10212, 215, 71, 253, 511, 839, 1718, 2488, 6876, 6877, 4979, 4979, 4982, 4982, 4473};
+
+
+static int bitcount_table_category1[100] = {
+  1, 4, 5, 6, 7, 8, 8, 9, 10, 10, 4, 5, 6, 7, 7, 8, 8, 9, 9, 11, 5, 5, 6, 7, 8, 8, 9, 9,
+  10, 11, 6, 6, 7, 8, 8, 9, 9, 10, 11, 12, 7, 7, 8, 8, 9, 9, 10, 11, 11, 13, 8, 8, 8,
+  9, 9, 10, 10, 11, 12, 14, 8, 8, 8, 9, 10, 11, 11, 12, 13, 15, 9, 9, 9, 10, 11, 12,
+  12, 14, 14, 14, 9, 9, 9, 10, 11, 12, 14, 16, 14, 14, 10, 10, 11, 12, 13, 14, 16, 16,
+  16, 14};
+
+static int code_table_category1[100] = {
+  1, 2, 11, 27, 31, 9, 120, 31, 275, 310, 1, 0, 12, 5, 33, 54, 102, 111, 246, 448, 10, 14,
+  31, 39, 59, 100, 114, 202, 485, 969, 24, 26, 36, 52, 103, 30, 120, 242, 69, 1244, 35,
+  32, 14, 61, 113, 117, 233, 486, 487, 2491, 13, 12, 69, 110, 149, 35, 495, 449, 1978,
+  7751, 76, 75, 122, 136, 213, 68, 623, 930, 3959, 9961, 115, 16, 107, 225, 424, 850,
+  1936, 7916, 4981, 4981, 148, 154, 243, 407, 988, 851, 7750, 19920, 7916, 4981, 406, 274,
+  464, 931, 3874, 7917, 19921, 19920, 19920, 7916};
+
+
+static int bitcount_table_category2[64] = {
+  1, 4, 5, 7, 8, 9, 10, 3, 4, 5, 7, 8, 9, 10, 5, 5, 6, 7, 8, 10, 10, 7, 6, 7, 8, 9, 10, 12,
+  8, 8, 8, 9, 10, 12, 14, 8, 9, 9, 10, 11, 15, 16, 9, 10, 11, 12, 13, 16, 15, 1, 1, 1};
+
+static int code_table_category2[52] = {
+  1, 0, 10, 11, 28, 62, 363, 3, 2, 9, 8, 24, 53, 352, 7, 8, 13, 25, 89, 74, 355, 10, 23, 24,
+  29, 55, 354, 1449, 25, 19, 30, 52, 108, 438, 5793, 91, 36, 63, 353, 725, 11584, 23170, 180,
+  75, 218, 439, 2897, 23171, 11584};
+
+
+static int bitcount_table_category3[625] = {
+  2, 4, 6, 8, 10, 5, 5, 6, 8, 10, 7, 8, 8, 10, 12, 9, 9, 10, 12, 15, 10, 11, 13, 16, 16, 5, 6, 8,
+  10, 11, 5, 6, 8, 10, 12, 7, 7, 8, 10, 13, 9, 9, 10, 12, 15, 12, 11, 13, 16, 16, 7, 9, 10, 12,
+  15, 7, 8, 10, 12, 13, 9, 9, 11, 13, 16, 11, 11, 12, 14, 16, 12, 12, 14, 16, 14, 9, 11, 12, 16,
+  16, 9, 10, 13, 15, 16, 10, 11, 12, 16, 16, 13, 13, 16, 16, 16, 16, 16, 15, 16, 16, 11, 13, 16,
+  16, 15, 11, 13, 15, 16, 16, 13, 13, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4, 6, 8,
+  10, 13, 6, 6, 8, 10, 13, 9, 8, 10, 12, 16, 10, 10, 11, 15, 16, 13, 12, 14, 16, 16, 5, 6, 8, 11, 13,
+  6, 6, 8, 10, 13, 8, 8, 9, 11, 14, 10, 10, 12, 12, 16, 13, 12, 13, 15, 16, 7, 8, 9, 12, 16, 7, 8,
+  10, 12, 14, 9, 9, 10, 13, 16, 11, 10, 12, 15, 16, 13, 13, 16, 16, 15, 9, 11, 13, 16, 16, 9, 10,
+  12, 15, 16, 10, 11, 13, 16, 16, 13, 12, 16, 16, 16, 16, 16, 16, 16, 16, 11, 13, 16, 16, 16, 11,
+  13, 16, 16, 16, 12, 13, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 6, 8, 11, 13, 16, 8,
+  8, 10, 12, 16, 11, 10, 11, 13, 16, 12, 13, 13, 15, 16, 16, 16, 14, 16, 15, 6, 8, 10, 13, 16, 8,
+  8, 10, 12, 16, 10, 10, 11, 13, 16, 13, 12, 13, 16, 16, 14, 14, 14, 16, 16, 8, 9, 11, 13, 16, 8,
+  9, 11, 16, 14, 10, 10, 12, 15, 16, 12, 12, 13, 16, 16, 15, 16, 16, 16, 16, 10, 12, 15, 16, 16,
+  10, 12, 12, 14, 16, 12, 12, 13, 16, 16, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 12, 15, 15, 16,
+  16, 13, 13, 16, 16, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 15, 16, 16, 16, 8, 10, 13,
+  15, 16, 10, 11, 13, 16, 16, 13, 13, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 10,
+  11, 15, 16, 9, 10, 12, 16, 16, 12, 12, 15, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 9, 11,
+  14, 16, 16, 10, 11, 13, 16, 16, 14, 13, 14, 16, 16, 16, 15, 15, 16, 16, 16, 16, 16, 16, 16, 11, 13,
+  16, 16, 16, 11, 13, 15, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16,
+  16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 13,
+  16, 16, 16, 11, 13, 16, 16, 16, 14, 15, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 13,
+  15, 15, 16, 12, 13, 14, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 13,
+  15, 16, 16, 12, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 16, 16, 16, 16,
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  16, 16, 16, 16, 16, 15, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
+
+static int code_table_category3[625] = {
+  3, 8, 46, 145, 228, 4, 8, 47, 28, 455, 89, 2, 180, 5, 1335, 250, 12, 644, 1311, 139, 729, 251, 870,
+  2172, 2211, 5, 23, 112, 334, 1469, 21, 3, 5, 111, 2014, 88, 79, 152, 124, 2685, 297, 48, 110, 1310,
+  149, 501, 1231, 153, 2267, 2569, 57, 13, 653, 2587, 143, 75, 124, 118, 2611, 5242, 61, 50, 253, 3633,
+  2216, 476, 39, 57, 1926, 2236, 2586, 1329, 1920, 2566, 1926, 296, 233, 2590, 2240, 2217, 253, 613,
+  867, 144, 318, 614, 252, 2589, 2242, 2218, 872, 866, 2187, 2296, 2155, 2568, 2227, 150, 2567, 2296,
+  199, 2686, 2160, 2290, 19145, 232, 2680, 128, 2192, 2212, 2684, 793, 2281, 2223, 2242, 1934, 2165,
+  2146, 2291, 2296, 2222, 2189, 2187, 2296, 2296, 6, 4, 82, 725, 3632, 15, 21, 56, 599, 148, 3, 162,
+  42, 411, 2301, 735, 654, 930, 137, 2586, 869, 1334, 1931, 2300, 2213, 9, 22, 146, 1290, 5240, 5, 12,
+  53, 630, 875, 80, 9, 8, 86, 2002, 210, 117, 56, 2019, 2162, 146, 397, 868, 131, 2151, 77, 160, 365,
+  2610, 2252, 59, 54, 41, 2591, 1928, 226, 14, 121, 5792, 2295, 1197, 728, 408, 130, 2157, 3635, 155,
+  2573, 2587, 130, 314, 64, 144, 2173, 2176, 115, 30, 409, 153, 2590, 631, 26, 4787, 2221, 2174, 2683,
+  1863, 2572, 319, 2150, 2177, 2194, 2571, 2257, 319, 65, 145, 2251, 2156, 2161, 909, 864, 2193, 2197,
+  2246, 2588, 5797, 156, 2258, 2221, 2158, 2199, 2214, 2152, 319, 2188, 2264, 2572, 319, 319, 30, 117,
+  219, 865, 2263, 147, 127, 239, 410, 2247, 27, 324, 1468, 2681, 2180, 1328, 5241, 147, 142, 2237, 2241,
+  2245, 1921, 2262, 142, 41, 11, 505, 2682, 2591, 0, 26, 229, 2015, 2577, 464, 98, 87, 5243, 2166, 149,
+  2016, 5244, 2190, 2198, 9573, 11598, 11599, 2235, 2190, 144, 298, 1004, 5245, 2277, 156, 104, 254, 2560,
+  1922, 612, 325, 2017, 129, 2588, 2608, 1330, 871, 2144, 2145, 132, 2147, 2148, 2149, 2144, 119, 1331,
+  133, 2153, 2154, 211, 58, 2609, 1923, 2159, 510, 163, 5246, 2163, 2164, 1924, 134, 2167, 2168, 2168, 2169,
+  2170, 2171, 2168, 2168, 1332, 135, 136, 2175, 2153, 150, 873, 2178, 2179, 1923, 1925, 2181, 2182, 2183,
+  2163, 2184, 2185, 2186, 2168, 2168, 1924, 134, 2167, 2168, 2168, 58, 326, 2687, 138, 2191, 31, 66, 874,
+  2195, 2196, 151, 152, 1927, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2205, 55,
+  103, 1230, 140, 2215, 118, 15, 1333, 2219, 2220, 2018, 511, 141, 2224, 2225, 2226, 1929, 2228, 2229, 2230,
+  2231, 2232, 2233, 2234, 2229, 366, 1005, 1930, 2238, 2239, 12, 1006, 5247, 2243, 2244, 1932, 3634, 1933,
+  2248, 2249, 2250, 145, 146, 2253, 2253, 2254, 2255, 2256, 2253, 2253, 1291, 5793, 2259, 2260, 2261, 477,
+  5794, 147, 2265, 2266, 5795, 2268, 2269, 2270, 2270, 2271, 2272, 2273, 2274, 2274, 2275, 2276, 2273, 2274,
+  2274, 148, 2278, 2279, 2280, 2260, 1935, 2282, 2283, 2284, 2265, 2285, 2286, 2287, 2270, 2270, 2288, 2289,
+  2273, 2274, 2274, 2271, 2272, 2273, 2274, 2274, 233, 5796, 2292, 2293, 2294, 1292, 3724, 2297, 2298, 2299,
+  2000, 151, 2302, 2303, 2200, 152, 2561, 2562, 2563, 2205, 2564, 2565, 2204, 2205, 2205, 363, 154, 154, 155,
+  2570, 59, 3725, 2001, 2574, 2575, 2576, 157, 2578, 2579, 2224, 2580, 2581, 2582, 2583, 2229, 2584, 2585, 2228,
+  2229, 2229, 654, 5798, 158, 2589, 2238, 2392, 2003, 2592, 2593, 2243, 2594, 2595, 2596, 2597, 2248, 2598, 2599,
+  2600, 2253, 2253, 2250, 145, 146, 2253, 2253, 2601, 2602, 2603, 2604, 2260, 2605, 2606, 2607, 6336, 2265, 6337,
+  6338, 6339, 2270, 2270, 6340, 6341, 2273, 2274, 2274, 2271, 2272, 2273, 2274, 2274, 6342, 6343, 2259, 2260,
+  2260, 38288, 38289, 147, 2265, 2265, 5795, 2268, 2269, 2270, 2270, 2271, 2272, 2273, 2274, 2274, 2271, 2272,
+  2273, 2274, 2274};
+
+
+static int bitcount_table_category4[256] = {
+  2, 4, 7, 10, 4, 5, 7, 10, 7, 8, 10, 14, 11, 11, 15, 15, 4, 5, 9,
+  12, 5, 5, 8, 12, 8, 7, 10, 15, 11, 11, 15, 15, 7, 9, 12, 15, 8, 8,
+  12, 15, 10, 10, 13, 15, 14, 14, 15, 13, 11, 13, 15, 15, 11, 13, 15,
+  15, 14, 15, 15, 13, 15, 15, 13, 13, 4, 5, 9, 13, 5, 6, 9, 13, 9, 9,
+  11, 15, 14, 13, 15, 15, 4, 6, 9, 12, 5, 6, 9, 13, 9, 8, 11, 15, 13,
+  12, 15, 15, 7, 9, 12, 15, 7, 8, 11, 15, 10, 10, 14, 15, 14, 15, 15,
+  14, 10, 12, 15, 15, 11, 13, 15, 15, 15, 15, 15, 14, 15, 15, 14, 14,
+  6, 9, 13, 14, 8, 9, 12, 15, 12, 12, 15, 15, 15, 15, 15, 15, 7, 9, 13,
+  15, 8, 9, 12, 15, 11, 12, 15, 15, 15, 15, 15, 15, 9, 11, 15, 15, 9,
+  11, 15, 15, 14, 14, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 14, 15,
+  15, 15, 15, 15, 15, 15, 14, 14, 15, 15, 9, 12, 15, 15, 12, 13, 15,
+  15, 15, 15, 15, 15, 15, 15, 15, 15, 10, 12, 15, 15, 12, 14, 15, 15,
+  15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+  15, 15, 15, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14,
+  15, 15, 14, 14, 15, 15};
+
+static int code_table_category4[256] = {
+  1, 2, 4, 572, 10, 0, 69, 712, 91, 10, 46, 9182, 1426, 1430, 30172, 30194,
+  9, 28, 22, 2258, 16, 25, 142, 2179, 15, 111, 719, 1521, 1131, 1437, 1520,
+  30196, 88, 283, 3803, 30193, 13, 236, 2856, 30166, 545, 951, 5709, 1522,
+  3241, 9180, 30179, 5709, 1088, 4356, 30410, 30175, 1146, 377, 30162, 30163,
+  8715, 30176, 30165, 5709, 30197, 30184, 5709, 5709, 1, 23, 28, 5710, 26, 14,
+  29, 7538, 102, 103, 1429, 1524, 3237, 7060, 30401, 30201, 15, 13, 470, 3768,
+  24, 15, 281, 5747, 24, 181, 1128, 30206, 5711, 3531, 30156, 30158, 116, 100,
+  2260, 30187, 119, 234, 1764, 30171, 716, 883, 9183, 30164, 3236, 1528, 30180,
+  9183, 885, 2870, 1532, 30160, 1431, 5708, 30192, 30205, 30402, 30168, 30173,
+  9183, 30157, 30161, 9183, 9183, 54, 25, 1621, 15211, 180, 287, 2261, 30198, 808,
+  811, 30411, 30413, 30414, 22986, 22987, 30411, 24, 273, 376, 30159, 137, 280,
+  2871, 1523, 1768, 2259, 1525, 30167, 1526, 30169, 30170, 1525, 443, 1434, 1527,
+  30174, 474, 1769, 30177, 30178, 3238, 3239, 30181, 30181, 30182, 30183, 30181,
+  30181, 3240, 30185, 30186, 1527, 9181, 30188, 30189, 30177, 30190, 30191, 30181,
+  30181, 3238, 3239, 30181, 30181, 440, 2857, 1529, 30195, 2294, 7061, 1530, 30199,
+  30200, 1531, 30202, 30411, 30203, 30204, 30411, 30411, 203, 2872, 30207, 30400,
+  189, 11492, 30403, 30404, 30405, 30406, 30407, 1525, 30408, 30409, 1525, 1525,
+  8714, 1533, 30412, 1527, 1534, 1535, 30415, 30177, 30416, 30417, 30181, 30181,
+  3238, 3239, 30181, 30181, 30418, 30419, 1527, 1527, 30420, 30421, 30177, 30177,
+  3238, 3239, 30181, 30181, 3238, 3239, 30181, 30181};
+
+
+static int bitcount_table_category5[256] = {
+  2, 4, 8, 4, 5, 9, 9, 10, 14, 4, 6, 11, 5, 6, 12,10, 11, 15, 9, 11, 15, 10, 13, 15,
+  14, 15, 6, 4, 6, 12, 6, 7, 12, 12, 12, 15, 5, 7, 13, 6, 7, 13, 12, 13, 15, 10, 12,
+  15, 11, 13, 15, 15, 15, 7, 8, 13, 15, 11, 12, 15, 15, 15, 7, 10, 13, 15, 12, 15, 15,
+  15, 15, 7, 15, 15, 7, 15, 15, 7, 6, 7, 7, 4, 5, 11, 5, 7, 12, 11, 12, 15, 6, 7, 13, 7,
+  8, 14, 12, 14, 15, 11, 13, 15, 12, 13, 15, 15, 15, 8, 5, 6, 13, 7, 8, 15, 12, 14, 15,
+  6, 8, 14, 7, 8, 15, 14, 15, 15, 12, 12, 15, 12, 13, 15, 15, 15, 8, 9, 13, 15, 12, 13,
+  15, 15, 15, 8, 11, 13, 15, 13, 13, 15, 15, 15, 8, 14, 15, 8, 15, 15, 8, 7, 8, 8, 8, 10,
+  15, 11, 12, 15, 15, 15, 7, 10, 12, 15, 12, 13, 15, 15, 15, 8, 14, 15, 7, 15, 15, 8, 7,
+  8, 8, 8, 12, 15, 12, 13, 15, 15, 15, 8, 11, 13, 15, 13, 15, 15, 15, 15, 8, 15, 15, 8,
+  15, 15, 8, 7, 8, 8, 14, 15, 6, 15, 15, 8, 7, 8, 8, 15, 15, 8, 15, 15, 8, 7, 8, 8, 6,
+  8, 8, 7, 8, 8, 7, 8, 8};
+
+static int code_table_category5[243] = {
+  0, 5, 220, 10, 16, 443, 390, 391, 14333, 11, 26, 1566, 26, 54, 3135, 508, 1558, 28581,
+  255, 1782, 28599, 885, 6208, 28578, 14335, 28579, 54, 9, 35, 3129, 27, 68, 3537, 1562,
+  3568, 28610, 25, 62, 4078, 58, 118, 7763, 3107, 7758, 28563, 778, 3131, 28598, 780, 7123,
+  28630, 28593, 28586, 118, 243, 6210, 28614, 1018, 3567, 28601, 28611, 28570, 68, 388, 6256,
+  28619, 1559, 28562, 28606, 28565, 28591, 118, 28594, 28571, 62, 28618, 28590, 118, 58,
+  118, 118, 4, 28, 1781, 31, 60, 3134, 1938, 3882, 28574, 25, 96, 7757, 49, 126, 14244,
+  3883, 14334, 28613, 1769, 4077, 28602, 3106, 7756, 28582, 28621, 28566, 126, 14, 61, 4079,
+  61, 138, 28491, 3536, 8153, 28573, 49, 96, 12442, 119, 240, 28490, 12443, 28560, 28561, 3111,
+  3580, 28564, 3130, 7759, 28567, 28568, 28569, 240, 444, 6209, 28572, 3569, 6211, 28575, 28576,
+  28577, 138, 778, 7760, 28580, 7761, 7762, 28583, 28584, 28585, 240, 14319, 28587, 96, 28588, 28589,
+  240, 119, 240, 240, 139, 968, 28592, 1554, 3581, 28595, 28596, 28597, 60, 971, 3560, 28600,3582,
+  7132, 28603, 28604, 28605, 126, 14332, 28607, 96, 28608, 28609, 126, 49, 126, 126, 241, 1558, 28612,
+  1563, 6257, 28615, 28616, 28617, 138, 1559, 7133, 28620, 6220, 28622, 28623, 28624, 28625, 240, 28626,
+  28627, 96, 28628, 28629, 240, 119, 240, 240, 8152, 28631, 61, 28632, 28633, 138, 61, 138, 138, 28634,
+  28635, 96, 28636, 28637, 240, 119, 240, 240, 49, 96, 96, 119, 240, 240, 119, 240, 240};
+
+
+static int bitcount_table_category6[32] = {1, 4, 4, 6, 4, 6, 6, 8, 4, 6, 6, 8, 6, 9, 8, 10, 4, 6, 7, 8, 6, 9, 8, 11, 6, 9, 8, 10, 8, 10, 9, 11};
+
+static int code_table_category6[32] = {1, 2, 4, 2, 5, 29, 24, 101, 3, 31, 28, 105, 3, 5, 102, 424, 1, 30, 0, 107, 27, 200, 103, 806, 1, 4, 104, 402, 3, 425, 213, 807};
+
+
+
+static int *bitcount_tables[7] = {
+  bitcount_table_category0,
+  bitcount_table_category1,
+  bitcount_table_category2,
+  bitcount_table_category3,
+  bitcount_table_category4,
+  bitcount_table_category5,
+  bitcount_table_category6};
+
+static int *code_tables[7] = {
+  code_table_category0,
+  code_table_category1,
+  code_table_category2,
+  code_table_category3,
+  code_table_category4,
+  code_table_category5,
+  code_table_category6};
+
+
+
+
+static int differential_decoder_tree[27][24][2] = {
+  {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, -12}, {-11, -10}, {-8, -9}, {-7, -6}, {-13, 12}, {-5, -4}, {0, 13}, {-3, -14}, {-2, 14}, {-1, 15}, {-15, 16}, {-16, 17}, {-17, 18}, {19, 20}, {21, 22}, {-18, -19}, {-20, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {-10, -9}, {-8, -11}, {-7, -6}, {9, -5}, {10, -12}, {-4, 11}, {-13, -3}, {12, -2}, {13, -14}, {-1, 14}, {15, -15}, {0, 16}, {-16, 17}, {-17, 18}, {-18, 19}, {20, 21},{22, -19}, {-20, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {-12, 11}, {-11, -13}, {-10, -9}, {12, -14}, {-8, -7}, {-15, -6}, {13, -5}, {-16, -4}, {14, -17}, {15, -3}, {16, -18}, {-2, 17}, {18, -19}, {-1, 19}, {-20, 20}, {0, 21}, {22, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {5, 6}, {-11, -10}, {7, -12}, {8, -9}, {9, -13}, {-14, 10}, {-8, -15}, {-16, 11}, {-7, 12}, {-17, -6}, {13, 14}, {-18, 15}, {-5, -4}, {16, 17}, {-3, -2}, {-19, 18}, {-1, 19}, {-20, 20}, {21, 22}, {0, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {5, 6}, {-12, -11}, {-13, 7}, {8, -14}, {-10, 9}, {10, -15}, {-9, 11}, {-8, 12}, {-16, 13}, {-7, -6}, {-17, 14}, {-5, -18}, {15, -4}, {16, -19}, {17, -3}, {-20, 18}, {-2, 19}, {-21, 20}, {0, 21}, {22, -1}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {5, 6}, {-11, 7}, {-12, -10}, {-13, -9}, {8, 9}, {-14, -8}, {10, -15}, {-7, 11}, {-16, 12}, {-6, -17}, {13, 14}, {-5, 15}, {-18, 16}, {-4, 17}, {-3, -19}, {18, -2}, {-20, 19}, {-1, 20}, {0, 21}, {22, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {5, -12}, {6, -11}, {-10, -13}, {-9, 7}, {8, -14}, {9, -8}, {-15, 10}, {-7, -16}, {11, -6}, {12, -17}, {13, -5}, {-18, 14}, {15, -4}, {-19, 16}, {17, -3}, {-20, 18}, {19, 20}, {21, 22}, {0, -2}, {-1, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {5, -12}, {6, -13}, {-11, -10}, {7, -14}, {8, -9}, {9, -15}, {-8, 10}, {-7, -16}, {11, 12}, {-6, -17}, {-5, 13}, {14, 15}, {-18, -4}, {-19, 16}, {-3, 17}, {18, -2}, {-20, 19}, {20, 21}, {22, 0}, {-1, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {5, 6}, {-11, -10}, {-12, -9}, {7, 8}, {-13, -8}, {9, -14}, {-7, 10}, {-6, -15}, {11, 12}, {-5, -16}, {13, 14}, {-17, 15}, {-4, 16}, {17, -18}, {18, -3}, {-2, 19}, {-1, 0}, {-19, 20}, {-20, 21}, {22, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {5, 6}, {-11, 7}, {-10, -12}, {-9, 8}, {-8, -13}, {9, -7}, {10, -14}, {-6, 11}, {-15, 12}, {-5, 13}, {-16, -4}, {14, 15}, {-17, -3}, {-18, 16}, {17, -19}, {-2, 18}, {-20, 19}, {-1, 20}, {21, 22}, {0, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {5, -12}, {6, -11}, {7, 8}, {-10, -13}, {-9, 9}, {-8, -14}, {10, -7}, {11, -15}, {-6, 12}, {-5, 13}, {-4, -16}, {14, 15}, {-3, -17}, {16, 17}, {-18, -2}, {18, -19}, {-1, 19}, {-20, 20}, {-21, 21}, {22, 0}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {5, -12}, {-13, 6}, {-11, 7}, {-14, 8}, {-10, 9}, {-15, -9}, {-8, 10}, {-7, -16}, {11, -6}, {12, -5}, {-17, 13}, {14, -18}, {15, -4}, {16, -19}, {17, -3}, {18, -2}, {19, -1}, {-20, 20}, {21, 22}, {0, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}},
+  {{1, 2}, {3, 4}, {-12, 5}, {-11, -13}, {6, -14}, {-10, 7}, {8, -15}, {-9, 9}, {-16, 10}, {-8, -17}, {11, 12}, {-7, -18}, {-6, 13}, {14, -5}, {15, -19}, {-4, 16}, {-20, 17}, {18, 19}, {20, 21}, {22, 0}, {-1, -3}, {-2, -21}, {-22, -23}, {-32, -32}}};
+
+
+
+static float mlt_quant[7][14] = {
+  {  0.0f, 0.392f, 0.761f, 1.120f, 1.477f, 1.832f, 2.183f, 2.541f, 2.893f, 3.245f, 3.598f, 3.942f, 4.288f, 4.724f},
+  {  0.0f, 0.544f, 1.060f, 1.563f, 2.068f, 2.571f, 3.072f, 3.562f, 4.070f, 4.620f,   0.0f,   0.0f,   0.0f,   0.0f},
+  {  0.0f, 0.746f, 1.464f, 2.180f, 2.882f, 3.584f, 4.316f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f},
+  {  0.0f, 1.006f, 2.000f, 2.993f, 3.985f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f},
+  {  0.0f, 1.321f, 2.703f, 3.983f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f},
+  {  0.0f, 1.657f, 3.491f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f},
+  {  0.0f, 1.964f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f,   0.0f}};
+
+
+static int decoder_tree0[360] = {
+  2,     1,    4,    6,    8,   10,   12,   14,   16,   18,   33,    3,   20,   22,   24,   26,   28,   30,
+  32,   34,   36,   38,   35,   40,   42,   44,   46,    5,   48,   65,   50,   52,   54,   56,   58,   60,
+  62,   64,   37,   66,   67,   68,   97,   70,   72,   74,    7,   76,   78,   80,   82,   84,   86,   88,
+  99,   90,   39,   92,   94,   96,  129,   98,    9,   100,  102,  104,  106,  108,  110,  112,   41,  161,
+  69,   114,  116,  118,  131,  120,  122,   11,  124,  126,  128,  193,  130,  132,   71,  134,   43,  136,
+  138,  140,  163,  101,   13,  142,  144,  146,  148,  150,  152,  154,  225,  156,  158,  195,  160,  162,
+  45,   164,   15,  166,   73,  168,  170,  133,   47,  172,  257,  174,  176,  178,   75,  103,  180,  165,
+  182,   17,  227,  184,  105,   49,  135,  186,  289,  188,  259,  190,  192,  194,  196,  198,  291,   77,
+  200,  202,  197,  107,  204,   19,   51,  229,  206,  167,  208,  210,  212,  214,   21,   79,   81,  109,
+  216,  218,  220,  222,   53,  137,  224,  199,  226,  323,  321,  169,  228,  111,  230,  232,  139,  261,
+  234,   83,  236,  201,  238,  240,  293,  242,  353,  231,  141,  244,  246,  113,   23,  355,   85,  248,
+  55,   115,  250,  263,  252,  254,  203,  171,  256,  258,  233,  235,  143,  357,  325,  260,  295,  262,
+  173,  145,  177,   87,  264,  327,  267,  266,  268,  175,  270,  272,  117,  297,  274,  265,  147,  179,
+  205,  276,  207,  237,  269,  278,   57,   59,  387,  209,  280,  282,  149,  329,  385,  284,   25,  286,
+  239,  119,  288,   27,  290,  292,  299,  294,  359,   89,  296,  298,  419,  181,  300,  331,  271,  417,
+  211,  361,  151,  389,  241,  302,  304,  303,  306,  308,  421,   91,  310,  312,  391,  314,  121,  316,
+  333,  318,  275,  213,  301,  243,  183,  335,  320,  363,  322,  215,  324,  393,  273,  337,  153,  326,
+  423,  365,  328,  367,  247,  395,  185,  123,  330,  425,  245,  155,  332,  334,  305,  397,  336,  277,
+  217,  338,  340,  339,  427,  342,  344,  346,  307,  399,  187,  348,  309,  341,  350,  369,  279,  311,
+  429,  249,  219,  352,  354,  356,  358,  431,  373,  401,  371,  313,  281,  433,  343,  403,  251,  283};
+
+
+static int decoder_tree1[188] = {
+  2,    1,    4,    6,    8,   10,   12,   14,   16,    3,   33,   18,   20,   22,   24,   26,   35,   28,   30,
+  32,   34,   36,    5,   65,   38,   40,   37,   42,   44,   46,   67,   48,   50,   52,   54,   56,   58,
+  60,    7,   62,   39,   97,   64,   69,   66,   99,   68,   70,   72,   74,   76,   78,   80,  129,   41,
+  131,   82,    9,   71,   84,   86,  101,   88,   90,   92,   94,   96,  161,   43,   11,   73,   98,  103,
+  100,  163,  102,  104,  106,  108,  133,  110,  105,  112,   75,  114,   45,   13,  116,  165,  118,  195,
+  135,  193,  120,   77,  122,   47,  124,  167,  225,  126,   79,  107,  227,  128,  137,  197,   15,  130,
+  169,  199,  132,  109,  134,   17,  139,   49,  136,  229,  138,  140,   81,  259,  142,  144,  171,  146,
+  141,  148,  111,  150,  201,  231,  152,   51,  257,  289,  154,   19,  113,  156,  261,  158,  203,  173,
+  263,  143,  160,  291,  235,   83,  162,  233,  265,  164,  205,  166,  293,  145,  168,  175,  177,  237,
+  115,  295,  170,  207,  172,  267,  174, 176,  297,  147,  178,  180,  269,  182,  271,  209,  299,  239,
+  179,  184,  301,  241,  211,    0,    0};
+
+static int decoder_tree2[96] = {
+  2,    1,    4,    6,    8,   10,   12,    3,   17,   14,   19,   16,   18,   20,   22,   24,   26,    5,   21,
+  35,   33,   28,   30,   32,   34,   36,   38,   37,   40,   23,   51,   42,    7,   49,   44,   46,   48,   50,
+  39,   53,   52,   54,   56,   25,   67,    9,   58,   60,   65,   55,   41,   62,   64,   69,   66,   11,   27,
+  68,   57,   83,   70,   71,   81,   43,   72,   74,   13,   76,   85,   29,   73,   78,   99,   59,   87,  101,
+  80,   97,   45,   82,   84,   75,   89,   61,   86,  103,   88,   77,   90,  105,   91,   92,  107,   93,    0,    0};
+
+static int decoder_tree3[1040] = {
+  2,    4,    6,    8,   10,    1,   12,   14,   16,   18,   20,   22,   24,   26,   28,   30,   32,   34,    3,   36,
+  1025,   38,   40,   42,   44,   46,   48,   50,  129,   17,   52,   54, 1153,   19,   56,   58,   60,   62,   64,
+  66,   68,  145,   70,   72,   74,   76,   78, 1169, 1027,  147,   80,   82, 1171,   84,   86,  131,   88, 1155,
+  1043, 1041,   90,   92,    5,   94,   96,   98,  100,  102,  104,   21,  106,  108, 2049, 2177,  110,  112,  114,
+  116,  118,  120,  122,  124,  126,  128,  130,  132,  134,  136,  138,  140,  142,   33,  144,  163,  146,  148,
+  150,  152,  154,  161,  156,   35,  158, 1297,  160,  162,  273,  257,  164,  166,  149,  168, 1281,  170,  172,
+  2193,  174,  176,  178, 1299,  180, 1045,  182,  184, 1173,  186, 3201,  188,  190,  192,  194, 2195, 1187,   23,
+  2179,  196,    7,  198,  275,  200, 2051,  202, 2065,  204,  206, 1029, 1185,  208,  210, 1157,   37, 3073, 2067,
+  133,  212,  214, 2321,  216,  165,  218, 1059,  220, 1283,  222, 2305,  224,  226,  228,  230,  259, 232,  234,
+  2323,  236, 1409, 1057, 1315,  238,  240,  242,  244,  246, 1425,  248, 1313,  250,  252,  254,  256,  258,  260,
+  289,  262,  264, 1189,  266,  268,  179,  151,  270,  272,  274,  276,  278,  291,  280,  282,    9,  385,  284,
+  286,  177,   49,  401, 1061,  288,  290,  292,   51,  294,  296,  298,  300,  302,  304,   25,  306, 2083,   39,
+  308,  310, 3329,  167,  312,  314, 1175,  316,  318, 1203,  135,  320,  322,  324,  326,  328, 2211, 2307,  330,
+  1301,  332,  334, 1047,  336,  338, 2449, 3217,  340, 1427, 2209,   53,  342, 2339, 3345,  344,  346,  348,  403,
+  181, 4097, 2197,  350, 2181, 1285, 1317, 1031,  352,  354,  356, 3089,  358,  360, 4225,  277,  362,  364,  366,
+  368, 2069,  370, 3203,  293, 1201,  305,  372, 3219,  307, 2433,  374,  376,  378,  380, 2081, 1411,  382,  384,
+  3075, 1443,  513,  386,  387,  388,  390, 1331,  261,  392,  394,  396,  398,  400, 1441, 1075,   67, 1159,  402,
+  404,  406,  408,  410,  412,  414, 3347, 2325,  416,   65,  418,  420,  422,  424,  426, 2053, 193, 1073,  428,
+  430,  432, 1537, 1329, 2337, 2213,  434,  417,  183,   41,  436,  438,  440,  442,  444,  446,  448,  450,  195,
+  2435,  452, 2085, 1063, 1191,  454,  456,  458,  460,  419, 2071, 1553, 3091,   55,  137,  462,  464,  466,  468,
+  470,  472,  474,  476,  478, 2309, 4113,  480,  482,  484,  486, 2451, 2465, 1205,  153,  488,  490,  492,  494,
+  496,  498,  500,  502,  504,  506,  508,  510,  512,  514,  516,  518,  520,  522,  524, 1333,  526, 1555, 2467,
+  2227, 3205, 3331,  528,  530,  532,  534,  536,  538,  540,  542,  544,  546,  548,  529,  309, 1303, 3473, 3457,
+  389, 1569, 1445, 1077,   69, 2199, 1539, 4353,  550,  552,  554,  556,  558,  560,  562, 1459, 4241, 3221, 1429,
+  2341,  279, 3475,  169,  564,  545, 3105,  323, 2353, 2097, 3235,  421, 2229, 3107, 3233,  566,  568,  570,  572,
+  574,  576,  578,  580,  582,  584,  586,  588,  590,  592,  594,  596, 2099, 1091,  531, 2437, 4227,  405,  197,
+  263, 1287, 2577, 1049, 1571,  598,  600,  602,  604,  606,  608,  610,  612,  614,  616, 618,  620,  622,  624,  626,
+  628,  630,  632,  634,  636,  638,  640,  642,  644,  646,  648,  650, 1345, 1219, 3077, 1457, 2225, 2579,  515, 2561,
+  2469,  433, 1221, 2183, 4243,  652,  654,  656,  658,  660,  662,  664,  666,  668,  670, 1217, 3333, 3093,  435,  321,
+  4369, 1089, 2055, 4099, 3361, 1319,  547, 1161, 1177,  672, 2355, 4115, 1413, 4257, 3349, 2453, 3109, 2357, 2215, 3363,
+  1079, 1207,  311, 1033, 1347, 1065,  674,  676,  678,  680,  682,  684,  686,  688,  690,  692,  694,  696,  698,  700,
+  702,  704,  706,  708,  710,  712,  714,  716,  718,  720,  722,  724,  726,  728,  730,  732,  734,  736,  738,  740,
+  742,  744,  746,  748,  750,  752,  754,  756,  758,  760,  762,  764,  766,  768,  770,  772,  774,  776,  778,  780,
+  782,  784,  786,  788,  790,  792,  794,  796,  798,  800,  802,  804,  806,  808,  810,  812,  814, 2593, 2565, 4261,
+  3253,  437,  325, 3489, 2311, 4259, 1431, 2087, 2563,  295, 2343,  449,  199,  265, 2201, 4371, 1193,  816,  533, 1557,
+  2581, 2241, 3365, 3491, 3603, 549, 2101, 1461, 1093, 2117, 3459, 3079, 4481, 3095, 2327, 3461, 4129, 3249, 1447, 2471,
+  2231,   71, 4497, 2609, 1289,  393, 3251, 2073, 3097, 2371, 1305, 2089,  818,  820,  822,  824,  826,  828,  830,  832,
+  834,  836,  838,  840,  842,  844,  846,  848,  850,  852,  854,  856,  858,  860,  862,  864,  866,  868,  870,  872,
+  874,  876,  878,  880,  882,  884,  886,  888,  890,  892,  894,  896,  898,  900,  902,  904,  906,  908,  910,  912,
+  914,  916,  918,  920,  922,  924,  926,  928,  930,  932,  934,  936,  938,  940,  942,  944,  946,  948,  950,  952,
+  954,  956,  958,  960,  962,  964,  966,  968,  970,  972,  974,  976,  978,  980,  982,  984,  986,  988,  990,  992,
+  994,  996,  998, 1000, 1002, 1004, 1006, 1008, 1010, 1012, 1014, 1016, 1018, 1020, 1022, 1024, 1026, 1028, 1030, 1032,
+  1034, 1036, 4161, 4273, 3507, 3493, 4517, 2497, 1573, 2597, 3621, 4531, 4627, 3523, 3125, 4149, 4529, 3139, 4515,  451,
+  4277, 2113, 4163, 4499, 3381, 4405, 1473, 4373, 2485, 3509,  565, 1589, 2613, 3585, 3123, 4403, 3141, 4147,  563, 2245,
+  3269, 4357, 1349, 2373, 3397,  453, 1477, 2501, 2481,  579, 1601, 3477, 4103, 3265, 2243, 1587, 3207, 4231, 3267, 4501,
+  1475, 3335, 4359,  391, 1415, 2439, 3463, 4487,  519, 1543, 2567, 3591, 4609, 4289, 4611, 2499, 4119, 4385, 4145, 4401,
+  3223, 4247, 3379,  577, 3393, 3351, 4375,  407, 1585, 2455, 3479, 4503,  535, 1559, 2583, 3607, 3605, 4513, 4485, 3111,
+  4135, 3121,  517, 3377, 3239, 4263, 1541, 4291, 4229, 3367, 4391,  423, 2115, 4131, 3495,  551, 1575, 2599, 3635, 3395,
+  2103, 3127, 4151, 3589, 4101, 1603, 3255, 4279, 3601, 1335, 2359, 3383,  439, 1463, 2487, 3511,  567, 1591, 4133, 1095,
+  2119, 3143, 2369, 1223, 2247, 3271,  327, 1351, 2375,  455, 1479, 3137, 3521, 2057, 3081, 4105, 4387, 3505, 2185, 3209,
+  4233, 3587, 4355, 2313, 3337, 3237, 1417, 2441, 3465,  521, 1545, 3617, 3633,  561, 4625, 4121, 2611, 2483, 2595, 3225,
+  4249,  281, 4245, 2329, 3353,  409, 1433, 2457, 3481,  537, 1561, 4483, 3619, 4389, 3113, 4275, 4117, 2217, 3241,  297,
+  1321, 2345, 3369,  425, 1449, 2473,   57, 1081, 2105, 3129,  185, 1209, 2233, 3257,  313, 1337, 2361,  441, 1465,   73,
+  1097,  201, 1225,    0,    0};
+
+
+static int decoder_tree4[416] = {
+  2,    4,    6,    1,    8,   10,   12,   14,   16,   18,   20,   22,   24,    3,  129,   26,   28,    9,   33,   30,   32,
+  34,   36,   11,  161,   38,   40,   42,   41,   44,   46,  131,   43,  169,   35,   48,  137,   50,   52,   54,   56,  139,
+  163,  171,   58,   60,   62,   64,    5,   66,   68,   70,  257,   72,   74,   76,   13,   78,   80,  289,   82,   84,   17,
+  86,   88,   65,   90,  201,   19,   92,   94,   51,  193,   96,   98,   49,  100,   73,  102,  104,  106,   45,  108,  110,
+  297,  112,  114,  116,   37,  203,  118,  120,  179,  122,  177,  124,  265,  126,   75,  133,  259,  291,  147,  128,   67,
+  195,  130,  141,  173,  299,  132,  145,  134,  165,  136,  138,  140,  142,    7,  144,  146,   21,  267,  148,   53,  150,
+  321,  152,  154,   15,  156,   81,  158,  160,  385,  162,  417,  164,  166,  168,   83,  170,  172,  329,  174,  211,  176,
+  27,  178,  180,  182,  209,  184,  186,  188,  190,   25,  192,  331,  194,  196,  105,   57,  198,   97,  200,  202,  323,
+  225,   59, 149,  204,  206,  233,  307,  208,   77,  181,  210,  212,  214,  216,  218,  220,  222,   47,  224,  226,   69,
+  228,  230,  197,  232,  425,  393,  205,  275,  293,   39,  234,  236,  238,  305,  135,  155,  301,  143,  240,  242,  235,
+  395,  244,  246,  248,  250,  252,  254,  256,  258,  260,  262,  273,  269,  185,  264,  266,  268,  270,  272,  274,  276,
+  261,  153,  278,  280,  282,  187,  337,  387,  107,  284,  427,  227,  167,  419,  286,  288,  290,  292,  294,  296,  298,
+  300,  302,  304,  306,  308,  310,  312,  314,  316,  318,  320,  322,  324,  326,  328,  330,  332,  334,  336,  338,  115,
+  99,   85,  213,   29,  113,   23,   89,  241,   61,  449,  339,  175,  340,  342,  344,  346,  348,  350,  352,  354,  356,
+  358,  360,  362,  364,  366,  368,  370,  372,  374,  376,  378,  380,  382,  384,  386,  388,  390,  392,  394,  396,  398,
+  400,  402,  404,  406,  408,  410,  412,  414,  389,  361,  457,  465,  429,  451,  333,  109,  277,  243,  263,  295,  199,
+  283,  151,   55,  183,  229,  357,  363,  123,  491,  397,  411,  251,  313,  441,  467,  345,  433,  461,  219,  237,  365,
+  435,  353,  347,  405,  409,  217,  309,  437,  369,  371,  341,  117,  245,  249,  157,  285,  403,  189,  317,   93,  221,
+  315,  401,  481,  391,  489,  121,  421,  423,   71,  483,  327,  103,  231,  443,  459,  271,  399,  355,   91,  303,  431,
+  79,  207,  335,  111,  239,  281,  325,  279,  453,  101,  311,   87,  215,   31,  159,   63,  191};
+
+static int decoder_tree5[384] = {
+  2,    4,    1,    6,    8,   10,   12,   14,   16,   18,   20,   22,    3,  513,   24,   26,   28,    9,  129,   33,   30,
+  32,   34,   36,   38,   40,   11,   42,  641,   44,   46,   41,  161,   48,  515,   50,   52,  131,   54,   35,  545,  137,
+  56,   58,   60,  521,   62,   43,  673,   64,  169,   66,   68,  523,   70,  163,  643,  139,  553,   72,  649,   74,  547,
+  76,   78,   80,  681,  171,   82,   84,  555,   86,  675,   88,  651,    5,   90,   92, 1025,   94,   96,   98,  683,   13,
+  100,   17,  102,  104,  106,   65,  108,  110,  257,  112,  114, 1153,   19,  116,  118,  120,  122,  124,   49,  126,  128,
+  769,  289,  130,  132,  134,   73,  136,  138,  140,  142,  193,  144,  146,  148,  150,  152,  154,  517,  156,  158,   37,
+  51,  160,  201,  162,  145,  164,  166,  168,  133,  170,  801,   45,  172,  174, 1057,  176,  178,   67,  180, 1027,  577,
+  182,  184,  186,  188,  190,  192,  194,  196,  198,  259,  200,  202,  204,  525,  177,  265,  141,  206,  208,  210,  212,
+  195,  297, 214,   75,  216, 1033,  203,  585, 1155, 1185,  267, 1161,  549,  218,  220,  657,  777,  147,  222,  224,  226,
+  228,  230,  232,  234,  236,  238,  240,  587,  645,  165,  242,  244,  246,  248,  250,  771,  291,  252,  579, 1065, 1035,
+  705,  531,  529,  659,  173,  254,  561,  653,  256,  713,  677,  557,  258,  260,  262,  264,  266,  268,  270,  272,  274,
+  276,  278,  280,  282,  284,  286,  288,  290,  292,  294,  296,  298,  300,  707, 1059,  809,  715,  563,  179,  691, 1193,
+  21,  779, 1067,  299, 1187,  302,  304,  306,  308,  310,  312,  314,  316,  318,  320,  322,  324,  326,  328,  330,  332,
+  334,  336,  338,  340,  342,  344,  346,  348,  350,  352,  354,  356,  358,  360,  362,  364,  366,  368,  370,  372,  374,
+  376,  378,  380,   83,   69, 1281,  803,  321, 1195, 1163,  811, 1323,  689, 1321, 1099,  305,  835, 1227,  331,  843,  785,
+  593, 1043, 1291, 1283, 1171,  275,  787, 1217,  833, 1075, 1313, 1219, 1203,  307,  819,  841,  595,  211,  723,  721,  817,
+  1029,  329,   81, 1157, 261,  773, 1097, 1089, 1061, 1169, 1091, 1189,  293,  805, 1201,  581,  197,  709, 1289,  273, 1037,
+  1315, 1041, 1165,  269,  781,  209, 1073, 1069,  323,  685, 1197,  301,  813,   77,  589,  205,  717, 1225,  533,  149,  661,
+  53,  565,  181,  693,    0,    0};
+
+
+static int decoder_tree6[62] = {
+  2,    1,    4,    6,    8,   10,   12,   14,   16,    3,
+  33,    5,  17,    9,   18,   20,   22,   24,   26,   28,
+  30,   32,   34,    7,  49,   13,   25,   36,   38,   11,
+  21,   41,   35,   37,   19,   40, 	42,   44,   46,   48,
+  50,   15,   52,   57,   29,   27,   23,   53, 	54,   51,
+  39,   45,   43,   56,   58,   31,   55,   60,   61,   47,
+  59,   63};
+
+static int *decoder_tables[7] = {
+  decoder_tree0,
+  decoder_tree1,
+  decoder_tree2,
+  decoder_tree3,
+  decoder_tree4,
+  decoder_tree5,
+  decoder_tree6,
+};
+
+static float noise_category5[20] = {0.70711f, 0.6179f, 0.5005f, 0.3220f,
+                                    0.17678f, 0.17678f, 0.17678f, 0.17678f,
+                                    0.17678f, 0.17678f, 0.17678f, 0.17678f,
+                                    0.17678f, 0.17678f, 0.17678f, 0.17678f,
+                                    0.17678f, 0.17678f, 0.17678f, 0.17678f};
+
+static float noise_category6[20] = {0.70711f, 0.5686f, 0.3563f, 0.25f,
+                                    0.25f, 0.25f, 0.25f, 0.25f,
+                                    0.25f, 0.25f, 0.25f, 0.25f,
+                                    0.25f, 0.25f, 0.25f, 0.25f,
+                                    0.25f, 0.25f, 0.25f, 0.25f};
+
+static float noise_category7 = 0.70711f;
+
+
+static int index_table[8] = {4, 4, 3, 3, 2, 2, 1, 0};
+
+#endif /* _HUFFMAN_CONSTS_H */
diff --git a/libavcodec/libsiren7/rmlt.c b/libavcodec/libsiren7/rmlt.c
new file mode 100644
index 0000000..0c1163c
--- /dev/null
+++ b/libavcodec/libsiren7/rmlt.c
@@ -0,0 +1,133 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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"
+
+
+static int rmlt_initialized = 0;
+static float rmlt_window_640[640];
+static float rmlt_window_320[320];
+
+#define PI_2     1.57079632679489661923
+
+void siren_rmlt_init(void) {
+  int i = 0;
+  float angle;
+
+  for (i = 0; i < 640; i++) {
+    angle = (float) (((i + 0.5) * PI_2) / 640);
+    rmlt_window_640[i] = (float) sin(angle);
+  }
+  for (i = 0; i < 320; i++) {
+    angle = (float) (((i + 0.5) * PI_2) / 320);
+    rmlt_window_320[i] = (float) sin(angle);
+  }
+
+  rmlt_initialized = 1;
+}
+
+int siren_rmlt_encode_samples(float *samples, float *old_samples, int dct_length, float *rmlt_coefs) {
+  int half_dct_length = dct_length / 2;
+  float *old_ptr = old_samples + half_dct_length;
+  float *coef_high = rmlt_coefs + half_dct_length;
+  float *coef_low = rmlt_coefs + half_dct_length;
+  float *samples_low = samples;
+  float *samples_high = samples + dct_length;
+  float *window_low = NULL;
+  float *window_high = NULL;
+  int i = 0;
+
+  if (rmlt_initialized == 0)
+    siren_rmlt_init();
+
+  if (dct_length == 320)
+    window_low = rmlt_window_320;
+  else if (dct_length == 640)
+    window_low = rmlt_window_640;
+  else
+    return 4;
+
+  window_high = window_low + dct_length;
+
+
+  for (i = 0; i < half_dct_length; i++) {
+    *--coef_low = *--old_ptr;
+    *coef_high++ = (*samples_low * *--window_high) - (*--samples_high * *window_low);
+    *old_ptr = (*samples_high * *window_high) + (*samples_low++ * *window_low++);
+  }
+  siren_dct4(rmlt_coefs, rmlt_coefs, dct_length);
+
+  return 0;
+}
+
+
+
+int siren_rmlt_decode_samples(float *coefs, float *old_coefs, int dct_length, float *samples)  {
+  int half_dct_length = dct_length / 2;
+  float *old_low = old_coefs;
+  float *old_high = old_coefs + half_dct_length;
+  float *samples_low = samples ;
+  float *samples_high = samples + dct_length;
+  float *samples_middle_low = samples + half_dct_length;
+  float *samples_middle_high = samples + half_dct_length;
+  float *window_low = NULL;
+  float *window_high = NULL;
+  float *window_middle_low = NULL;
+  float *window_middle_high = NULL;
+  float sample_low_val;
+  float sample_high_val;
+  float sample_middle_low_val;
+  float sample_middle_high_val;
+  int i = 0;
+
+  if (rmlt_initialized == 0)
+    siren_rmlt_init();
+
+  if (dct_length == 320)
+    window_low = rmlt_window_320;
+  else if (dct_length == 640)
+    window_low = rmlt_window_640;
+  else
+    return 4;
+
+
+  window_high = window_low + dct_length;
+  window_middle_low = window_low + half_dct_length;
+  window_middle_high = window_low + half_dct_length;
+
+  siren_dct4(coefs, samples, dct_length);
+
+  for (i = 0; i < half_dct_length; i+=2) {
+    sample_low_val = *samples_low;
+    sample_high_val = *--samples_high;
+    sample_middle_low_val = *--samples_middle_low;
+    sample_middle_high_val = *samples_middle_high;
+    *samples_low++ = (*old_low * *--window_high) + (sample_middle_low_val * *window_low);
+    *samples_high = (sample_middle_low_val * *window_high) - (*old_low * *window_low++);
+    *samples_middle_high++ = (sample_low_val * *window_middle_high) - (*--old_high * *--window_middle_low);
+    *samples_middle_low = (*old_high * *window_middle_high++) + (sample_low_val * *window_middle_low);
+    *old_low++ = sample_middle_high_val;
+    *old_high = sample_high_val;
+  }
+
+  return 0;
+}
diff --git a/libavcodec/libsiren7/rmlt.h b/libavcodec/libsiren7/rmlt.h
new file mode 100644
index 0000000..27257cf
--- /dev/null
+++ b/libavcodec/libsiren7/rmlt.h
@@ -0,0 +1,30 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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.
+ */
+
+
+#ifndef _SIREN7_RMLT_H_
+#define _SIREN7_RMLT_H_
+
+extern void siren_rmlt_init(void);
+extern int siren_rmlt_encode_samples(float *samples, float *old_samples, int dct_length, float *rmlt_coefs);
+extern int siren_rmlt_decode_samples(float *coefs, float *old_coefs, int dct_length, float *samples);
+
+#endif /* _SIREN7_RMLT_H_ */
diff --git a/libavcodec/libsiren7/siren7.h b/libavcodec/libsiren7/siren7.h
new file mode 100644
index 0000000..9a89811
--- /dev/null
+++ b/libavcodec/libsiren7/siren7.h
@@ -0,0 +1,30 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ *   @author: Youness Alaoui <kakaroto at 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.
+ */
+
+
+#ifndef _SIREN7_H
+#define _SIREN7_H
+
+#include "encoder.h"
+#include "decoder.h"
+
+
+#endif /* _SIREN7_H */
diff --git a/libavcodec/libsiren7dec.c b/libavcodec/libsiren7dec.c
new file mode 100644
index 0000000..4dad00a
--- /dev/null
+++ b/libavcodec/libsiren7dec.c
@@ -0,0 +1,95 @@
+/*
+ * Siren7 decoder using aMSN libsiren
+ * Copyright (c) 2010 Peter Ross (pross at xvid.org)
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Siren7 decoder using aMSN libsiren
+ */
+
+#include "avcodec.h"
+#include "libsiren7/decoder.h"
+
+#define BYTES_PER_FRAME   40
+#define SAMPLES_PER_FRAME 320
+
+typedef struct {
+    AVFrame frame;
+    SirenDecoder decoder;
+} Siren7DecContext;
+
+static av_cold int decode_init(AVCodecContext *avctx)
+{
+    Siren7DecContext * s = avctx->priv_data;
+
+    s->decoder = Siren7_NewDecoder(avctx->sample_rate);
+    if (!s->decoder)
+        return AVERROR(EINVAL);
+
+    avctx->sample_fmt  = AV_SAMPLE_FMT_S16;
+
+    avcodec_get_frame_defaults(&s->frame);
+    avctx->coded_frame = &s->frame;
+
+    return 0;
+}
+
+static av_cold int decode_close(AVCodecContext *avctx)
+{
+    Siren7DecContext * s = avctx->priv_data;
+    Siren7_CloseDecoder(s->decoder);
+    return 0;
+}
+
+static int decode_frame(AVCodecContext *avctx, void *data,
+                        int *got_frame_ptr, AVPacket *avpkt)
+{
+    Siren7DecContext * s       = avctx->priv_data;
+    int ret;
+
+    s->frame.nb_samples = SAMPLES_PER_FRAME;
+    if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+        return ret;
+    }
+
+    if (avpkt->size < BYTES_PER_FRAME) {
+        av_log(avctx, AV_LOG_WARNING, "skipping short frame (decoder)\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    Siren7_DecodeFrame(s->decoder, avpkt->data, s->frame.data[0]);
+
+    *(AVFrame *)data = s->frame;
+    *got_frame_ptr = 1;
+    return BYTES_PER_FRAME;
+}
+
+AVCodec ff_libsiren7_decoder = {
+    .name           = "libsiren7",
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = CODEC_ID_SIREN7,
+    .priv_data_size = sizeof(Siren7DecContext),
+    .init           = decode_init,
+    .close          = decode_close,
+    .decode         = decode_frame,
+    .capabilities   = CODEC_CAP_DR1,
+    .long_name      = NULL_IF_CONFIG_SMALL("Siren7 (aMSN library)"),
+};
diff --git a/libavcodec/libsiren7enc.c b/libavcodec/libsiren7enc.c
new file mode 100644
index 0000000..25f42c0
--- /dev/null
+++ b/libavcodec/libsiren7enc.c
@@ -0,0 +1,94 @@
+/*
+ * Siren7 encoder using aMSN libsiren
+ * Copyright (c) 2010 Peter Ross (pross at xvid.org)
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Siren7 encoder using aMSN libsiren
+ */
+
+#include "avcodec.h"
+#include "internal.h"
+#include "libsiren7/encoder.h"
+
+#define BYTES_PER_FRAME   40
+#define SAMPLES_PER_FRAME 320
+
+typedef struct {
+    AVFrame frame;
+    SirenEncoder encoder;
+} Siren7EncContext;
+
+static av_cold int encode_init(AVCodecContext *avctx)
+{
+    Siren7EncContext * s = avctx->priv_data;
+
+    if (avctx->sample_fmt != AV_SAMPLE_FMT_S16 ||
+        avctx->channels != 1)
+        return AVERROR(EINVAL);
+
+    s->encoder = Siren7_NewEncoder(avctx->sample_rate);
+    if (!s->encoder)
+        return AVERROR(EINVAL);
+
+    avctx->frame_size = SAMPLES_PER_FRAME;
+    return 0;
+}
+
+static av_cold int encode_close(AVCodecContext *avctx)
+{
+    Siren7EncContext * s = avctx->priv_data;
+    Siren7_CloseEncoder(s->encoder);
+    return 0;
+}
+
+static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+                        const AVFrame *frame, int *got_packet_ptr)
+{
+    Siren7EncContext * s = avctx->priv_data;
+    int ret;
+
+    if (frame->nb_samples < SAMPLES_PER_FRAME) {
+        av_log(avctx, AV_LOG_WARNING, "skipping short frame (encoder)\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    if ((ret = ff_alloc_packet2(avctx, avpkt, BYTES_PER_FRAME)))
+        return ret;
+
+    Siren7_EncodeFrame(s->encoder, frame->data[0], avpkt->data);
+
+    avpkt->size     = BYTES_PER_FRAME;
+    *got_packet_ptr = 1;
+    return 0;
+}
+
+AVCodec ff_libsiren7_encoder = {
+    .name            = "libsiren7",
+    .type            = AVMEDIA_TYPE_AUDIO,
+    .id              = CODEC_ID_SIREN7,
+    .priv_data_size  = sizeof(Siren7EncContext),
+    .init            = encode_init,
+    .encode2         = encode_frame,
+    .close           = encode_close,
+    .sample_fmts     = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
+                                                      AV_SAMPLE_FMT_NONE },
+    .long_name       = NULL_IF_CONFIG_SMALL("Siren7 (aMSN library)"),
+};
diff --git a/libavformat/riff.c b/libavformat/riff.c
index 4f21d2c..08c8d4c 100644
--- a/libavformat/riff.c
+++ b/libavformat/riff.c
@@ -351,6 +351,7 @@ const AVCodecTag ff_codec_wav_tags[] = {
     { CODEC_ID_WMALOSSLESS,     0x0163 },
     { CODEC_ID_ADPCM_CT,        0x0200 },
     { CODEC_ID_ATRAC3,          0x0270 },
+    { CODEC_ID_SIREN7,          0x028E },
     { CODEC_ID_ADPCM_G722,      0x028F },
     { CODEC_ID_IMC,             0x0401 },
     { CODEC_ID_IAC,             0x0402 },
-- 
1.7.10.4

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20120717/0514f215/attachment.asc>


More information about the ffmpeg-devel mailing list