summaryrefslogtreecommitdiffstats
path: root/gst
diff options
context:
space:
mode:
authorYouness Alaoui <youness.alaoui@collabora.co.uk>2008-04-10 07:01:16 +0000
committerEdward Hervey <bilboed@bilboed.com>2009-02-17 19:29:39 +0100
commitb9ea3bbe4f4948d667599c79f6cc2fcf414e47a6 (patch)
treeb7b165e3e1ee7fdca884b3b3aa38fb7f5d3e1b12 /gst
parent79ebcb8fe5f4c856e87b51d7eaef9e59a53f763c (diff)
downloadgst-plugins-bad-b9ea3bbe4f4948d667599c79f6cc2fcf414e47a6.tar.gz
gst-plugins-bad-b9ea3bbe4f4948d667599c79f6cc2fcf414e47a6.tar.bz2
gst-plugins-bad-b9ea3bbe4f4948d667599c79f6cc2fcf414e47a6.zip
[MOVED FROM GST-P-FARSIGHT] Added Siren encoder/decoder/payloader/depayloader
20080410070116-4f0f6-72ffbdbb262f07bfabd1e469973a01b3359bee45.gz
Diffstat (limited to 'gst')
-rw-r--r--gst/siren/.git-darcs-dir0
-rw-r--r--gst/siren/Makefile.am16
-rw-r--r--gst/siren/common.c505
-rw-r--r--gst/siren/common.h146
-rw-r--r--gst/siren/dct4.c184
-rw-r--r--gst/siren/dct4.h30
-rw-r--r--gst/siren/decoder.c234
-rw-r--r--gst/siren/decoder.h52
-rw-r--r--gst/siren/encoder.c234
-rw-r--r--gst/siren/encoder.h47
-rw-r--r--gst/siren/gstrtpsirendepay.c142
-rw-r--r--gst/siren/gstrtpsirendepay.h60
-rw-r--r--gst/siren/gstrtpsirenpay.c163
-rw-r--r--gst/siren/gstrtpsirenpay.h58
-rw-r--r--gst/siren/gstsiren.c55
-rw-r--r--gst/siren/gstsiren.h69
-rw-r--r--gst/siren/gstsirendec.c341
-rw-r--r--gst/siren/gstsirendec.h79
-rw-r--r--gst/siren/gstsirenenc.c330
-rw-r--r--gst/siren/gstsirenenc.h79
-rw-r--r--gst/siren/huffman.c382
-rw-r--r--gst/siren/huffman.h35
-rw-r--r--gst/siren/huffman_consts.h528
-rw-r--r--gst/siren/rmlt.c133
-rw-r--r--gst/siren/rmlt.h30
-rw-r--r--gst/siren/siren7.h30
26 files changed, 3962 insertions, 0 deletions
diff --git a/gst/siren/.git-darcs-dir b/gst/siren/.git-darcs-dir
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/gst/siren/.git-darcs-dir
diff --git a/gst/siren/Makefile.am b/gst/siren/Makefile.am
new file mode 100644
index 00000000..9ecefd02
--- /dev/null
+++ b/gst/siren/Makefile.am
@@ -0,0 +1,16 @@
+plugin_LTLIBRARIES = libgstsiren.la
+
+libgstsiren_la_SOURCES = gstsiren.c \
+ gstsirendec.c gstsirendec.h \
+ gstsirenenc.c gstsirenenc.h \
+ gstrtpsirenpay.c gstrtpsirenpay.h \
+ gstrtpsirendepay.c gstrtpsirendepay.h \
+ common.c dct4.c decoder.c encoder.c huffman.c \
+ huffman.h rmlt.h common.h dct4.h decoder.h \
+ encoder.h huffman_consts.h rmlt.c siren7.h
+
+
+libgstsiren_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(ERROR_CFLAGS)
+libgstsiren_la_LIBADD = $(GST_LIBS_LIBS) $(GST_BASE_LIBS) \
+ -lgstrtp-@GST_MAJORMINOR@
+libgstsiren_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS)
diff --git a/gst/siren/common.c b/gst/siren/common.c
new file mode 100644
index 00000000..a85e6726
--- /dev/null
+++ b/gst/siren/common.c
@@ -0,0 +1,505 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "siren7.h"
+
+int region_size;
+float region_size_inverse;
+
+float standard_deviation[64];
+float deviation_inverse[64];
+float region_power_table_boundary[63];
+
+int expected_bits_table[8] = {52, 47, 43, 37, 29, 22, 16, 0};
+int vector_dimension[8] = {2, 2, 2, 4, 4, 5, 5, 1};
+int number_of_vectors[8] = {10, 10, 10, 5, 5, 4, 4, 20};
+float dead_zone[8] = {0.3f, 0.33f, 0.36f, 0.39f, 0.42f, 0.45f, 0.5f, 0.5f};
+
+int max_bin[8] = {
+ 13,
+ 9,
+ 6,
+ 4,
+ 3,
+ 2,
+ 1,
+ 1};
+
+float step_size[8] = {
+ 0.3536f,
+ 0.5f,
+ 0.70709997f,
+ 1.0f,
+ 1.4141999f,
+ 2.0f,
+ 2.8283999f,
+ 2.8283999f};
+
+float step_size_inverse[8];
+
+static int siren_initialized = 0;
+
+/*
+ STEPSIZE = 2.0 * log(sqrt(2));
+*/
+#define STEPSIZE 0.3010299957
+
+void siren_init() {
+ int i;
+ float region_power;
+
+ if (siren_initialized == 1)
+ return;
+
+ region_size = 20;
+ region_size_inverse = 1.0f/region_size;
+
+ for (i = 0; i < 64; i++) {
+ region_power = (float) pow(10, (i-24) * STEPSIZE);
+ standard_deviation[i] = (float) sqrt(region_power);
+ deviation_inverse[i] = (float) 1.0 / standard_deviation[i];
+ }
+
+ for (i = 0; i < 63; i++)
+ region_power_table_boundary[i] = (float) pow(10, (i-24 + 0.5) * STEPSIZE);
+
+ for (i = 0; i < 8; i++)
+ step_size_inverse[i] = (float) 1.0 / step_size[i];
+
+ siren_dct4_init();
+ siren_rmlt_init();
+
+ siren_initialized = 1;
+}
+
+
+int categorize_regions(int number_of_regions, int number_of_available_bits, int *absolute_region_power_index, int *power_categories, int *category_balance) {
+ int region, delta, i, temp;
+ int expected_number_of_code_bits;
+ int min, max;
+ int offset,
+ num_rate_control_possibilities,
+ raw_value,
+ raw_max_idx = 0,
+ raw_min_idx = 0;
+ int max_rate_categories[28];
+ int min_rate_categories[28];
+ int temp_category_balances[64];
+ int *min_rate_ptr = NULL;
+ int *max_rate_ptr = NULL;
+
+ if (number_of_regions == 14) {
+ num_rate_control_possibilities = 16;
+ if ( number_of_available_bits > 320)
+ number_of_available_bits = ((number_of_available_bits - 320) * 5/8) + 320;
+ } else {
+ num_rate_control_possibilities = 32;
+ if (number_of_regions == 28 && number_of_available_bits > 640)
+ number_of_available_bits = ((number_of_available_bits - 640) * 5/8) + 640;
+ }
+
+ offset = -32;
+ for (delta = 32; number_of_regions > 0 && delta > 0; delta /= 2) {
+ expected_number_of_code_bits = 0;
+ for (region = 0; region < number_of_regions; region++) {
+ i = (delta + offset - absolute_region_power_index[region]) >> 1;
+ if (i > 7)
+ i = 7;
+ else if (i < 0)
+ i = 0;
+
+ power_categories[region] = i;
+ expected_number_of_code_bits += expected_bits_table[i];
+
+ }
+ if (expected_number_of_code_bits >= number_of_available_bits-32)
+ offset += delta;
+ }
+
+ expected_number_of_code_bits = 0;
+ for (region = 0; region < number_of_regions; region++) {
+ i = (offset - absolute_region_power_index[region]) >> 1;
+ if (i > 7)
+ i = 7;
+ else if (i < 0)
+ i = 0;
+ max_rate_categories[region] = min_rate_categories[region] = power_categories[region] = i;
+ expected_number_of_code_bits += expected_bits_table[i];
+ }
+
+
+ min = max = expected_number_of_code_bits;
+ min_rate_ptr = max_rate_ptr = temp_category_balances + num_rate_control_possibilities;
+ for (i = 0; i < num_rate_control_possibilities -1; i++) {
+ if (min + max > number_of_available_bits * 2) {
+ raw_value = -99;
+ for (region = number_of_regions-1; region >= 0; region--) {
+ if (min_rate_categories[region] < 7) {
+ temp = offset - absolute_region_power_index[region] - 2*min_rate_categories[region];
+ if (temp > raw_value) {
+ raw_value = temp;
+ raw_min_idx = region;
+ }
+ }
+ }
+ *min_rate_ptr++ = raw_min_idx;
+ min += expected_bits_table[min_rate_categories[raw_min_idx] + 1] - expected_bits_table[min_rate_categories[raw_min_idx]];
+ min_rate_categories[raw_min_idx]++;
+ } else {
+ raw_value = 99;
+ for (region = 0; region < number_of_regions; region++) {
+ if (max_rate_categories[region] > 0 ) {
+ temp = offset - absolute_region_power_index[region] - 2*max_rate_categories[region];
+ if (temp < raw_value) {
+ raw_value = temp;
+ raw_max_idx = region;
+ }
+ }
+ }
+
+ *--max_rate_ptr = raw_max_idx;
+ max += expected_bits_table[max_rate_categories[raw_max_idx] - 1] - expected_bits_table[max_rate_categories[raw_max_idx]];
+ max_rate_categories[raw_max_idx]--;
+ }
+ }
+
+ for (region = 0; region < number_of_regions; region++)
+ power_categories[region] = max_rate_categories[region];
+
+ for (i = 0; i < num_rate_control_possibilities-1; i++)
+ category_balance[i] = *max_rate_ptr++;
+
+
+ return 0;
+}
+
+
+
+/*
+ Looks like the flag means what kind of encoding is used
+ for now, it looks like :
+ 0 : the sample rate is not encoded in the frame
+ 1 - 2 : the sample rate is fixed in the frame
+ 3 : sample rate is variable and there is one for each frame
+*/
+
+int GetSirenCodecInfo(int flag, int sample_rate, int *number_of_coefs, int *sample_rate_bits, int *rate_control_bits, int *rate_control_possibilities, int *checksum_bits, int *esf_adjustment, int *scale_factor, int *number_of_regions, int *sample_rate_code, int *bits_per_frame ) {
+ switch (flag) {
+ case 0:
+ *number_of_coefs = 320;
+ *sample_rate_bits = 0;
+ *rate_control_bits = 4;
+ *rate_control_possibilities = 16;
+ *checksum_bits = 0;
+ *esf_adjustment = 7;
+ *number_of_regions = 14;
+ *sample_rate_code = 0;
+ *scale_factor = 22;
+ break;
+ case 1:
+ *number_of_coefs = 320;
+ *sample_rate_bits = 2;
+ *rate_control_bits = 4;
+ *rate_control_possibilities = 16;
+ *checksum_bits = 4;
+ *esf_adjustment = -2;
+ *number_of_regions = 14;
+ *scale_factor = 1;
+ if (sample_rate == 16000)
+ *sample_rate_code = 1;
+ else if (sample_rate == 24000)
+ *sample_rate_code = 2;
+ else if (sample_rate == 32000)
+ *sample_rate_code = 3;
+ else
+ return 3;
+ break;
+ case 2:
+ *number_of_coefs = 640;
+ *sample_rate_bits = 2;
+ *rate_control_bits = 5;
+ *rate_control_possibilities = 32;
+ *checksum_bits = 4;
+ *esf_adjustment = 7;
+ *number_of_regions = 28;
+ *scale_factor = 33;
+
+ if (sample_rate == 24000)
+ *sample_rate_code = 1;
+ else if (sample_rate == 24000)
+ *sample_rate_code = 2;
+ else if (sample_rate == 48000)
+ *sample_rate_code = 3;
+ else
+ return 3;
+
+ break;
+ case 3:
+ *number_of_coefs = 640;
+ *sample_rate_bits = 6;
+ *rate_control_bits = 5;
+ *rate_control_possibilities = 32;
+ *checksum_bits = 4;
+ *esf_adjustment = 7;
+ *scale_factor = 33;
+
+ switch (sample_rate) {
+ case 8800:
+ *number_of_regions = 12;
+ *sample_rate_code = 59;
+ break;
+ case 9600:
+ *number_of_regions = 12;
+ *sample_rate_code = 1;
+ break;
+ case 10400:
+ *number_of_regions = 12;
+ *sample_rate_code = 13;
+ break;
+ case 10800:
+ *number_of_regions = 12;
+ *sample_rate_code = 14;
+ break;
+ case 11200:
+ *number_of_regions = 12;
+ *sample_rate_code = 15;
+ break;
+ case 11600:
+ *number_of_regions = 12;
+ *sample_rate_code = 16;
+ break;
+ case 12000:
+ *number_of_regions = 12;
+ *sample_rate_code = 2;
+ break;
+ case 12400:
+ *number_of_regions = 12;
+ *sample_rate_code = 17;
+ break;
+ case 12800:
+ *number_of_regions = 12;
+ *sample_rate_code = 18;
+ break;
+ case 13200:
+ *number_of_regions = 12;
+ *sample_rate_code = 19;
+ break;
+ case 13600:
+ *number_of_regions = 12;
+ *sample_rate_code = 20;
+ break;
+ case 14000:
+ *number_of_regions = 12;
+ *sample_rate_code = 21;
+ break;
+ case 14400:
+ *number_of_regions = 16;
+ *sample_rate_code = 3;
+ break;
+ case 14800:
+ *number_of_regions = 16;
+ *sample_rate_code = 22;
+ break;
+ case 15200:
+ *number_of_regions = 16;
+ *sample_rate_code = 23;
+ break;
+ case 15600:
+ *number_of_regions = 16;
+ *sample_rate_code = 24;
+ break;
+ case 16000:
+ *number_of_regions = 16;
+ *sample_rate_code = 25;
+ break;
+ case 16400:
+ *number_of_regions = 16;
+ *sample_rate_code = 26;
+ break;
+ case 16800:
+ *number_of_regions = 18;
+ *sample_rate_code = 4;
+ break;
+ case 17200:
+ *number_of_regions = 18;
+ *sample_rate_code = 27;
+ break;
+ case 17600:
+ *number_of_regions = 18;
+ *sample_rate_code = 28;
+ break;
+ case 18000:
+ *number_of_regions = 18;
+ *sample_rate_code = 29;
+ break;
+ case 18400:
+ *number_of_regions = 18;
+ *sample_rate_code = 30;
+ break;
+ case 18800:
+ *number_of_regions = 18;
+ *sample_rate_code = 31;
+ break;
+ case 19200:
+ *number_of_regions = 20;
+ *sample_rate_code = 5;
+ break;
+ case 19600:
+ *number_of_regions = 20;
+ *sample_rate_code = 32;
+ break;
+ case 20000:
+ *number_of_regions = 20;
+ *sample_rate_code = 33;
+ break;
+ case 20400:
+ *number_of_regions = 20;
+ *sample_rate_code = 34;
+ break;
+ case 20800:
+ *number_of_regions = 20;
+ *sample_rate_code = 35;
+ break;
+ case 21200:
+ *number_of_regions = 20;
+ *sample_rate_code = 36;
+ break;
+ case 21600:
+ *number_of_regions = 22;
+ *sample_rate_code = 6;
+ break;
+ case 22000:
+ *number_of_regions = 22;
+ *sample_rate_code = 37;
+ break;
+ case 22400:
+ *number_of_regions = 22;
+ *sample_rate_code = 38;
+ break;
+ case 22800:
+ *number_of_regions = 22;
+ *sample_rate_code = 39;
+ break;
+ case 23200:
+ *number_of_regions = 22;
+ *sample_rate_code = 40;
+ break;
+ case 23600:
+ *number_of_regions = 22;
+ *sample_rate_code = 41;
+ break;
+ case 24000:
+ *number_of_regions = 24;
+ *sample_rate_code = 7;
+ break;
+ case 24400:
+ *number_of_regions = 24;
+ *sample_rate_code = 42;
+ break;
+ case 24800:
+ *number_of_regions = 24;
+ *sample_rate_code = 43;
+ break;
+ case 25200:
+ *number_of_regions = 24;
+ *sample_rate_code = 44;
+ break;
+ case 25600:
+ *number_of_regions = 24;
+ *sample_rate_code = 45;
+ break;
+ case 26000:
+ *number_of_regions = 24;
+ *sample_rate_code = 46;
+ break;
+ case 26400:
+ *number_of_regions = 26;
+ *sample_rate_code = 8;
+ break;
+ case 26800:
+ *number_of_regions = 26;
+ *sample_rate_code = 47;
+ break;
+ case 27200:
+ *number_of_regions = 26;
+ *sample_rate_code = 48;
+ break;
+ case 27600:
+ *number_of_regions = 26;
+ *sample_rate_code = 49;
+ break;
+ case 28000:
+ *number_of_regions = 26;
+ *sample_rate_code = 50;
+ break;
+ case 28400:
+ *number_of_regions = 26;
+ *sample_rate_code = 51;
+ break;
+ case 28800:
+ *number_of_regions = 28;
+ *sample_rate_code = 9;
+ break;
+ case 29200:
+ *number_of_regions = 28;
+ *sample_rate_code = 52;
+ break;
+ case 29600:
+ *number_of_regions = 28;
+ *sample_rate_code = 53;
+ break;
+ case 30000:
+ *number_of_regions = 28;
+ *sample_rate_code = 54;
+ break;
+ case 30400:
+ *number_of_regions = 28;
+ *sample_rate_code = 55;
+ break;
+ case 30800:
+ *number_of_regions = 28;
+ *sample_rate_code = 56;
+ break;
+ case 31200:
+ *number_of_regions = 28;
+ *sample_rate_code = 10;
+ break;
+ case 31600:
+ *number_of_regions = 28;
+ *sample_rate_code = 57;
+ break;
+ case 32000:
+ *number_of_regions = 28;
+ *sample_rate_code = 58;
+ break;
+ default:
+ return 3;
+ break;
+ }
+ break;
+ default:
+ return 6;
+ }
+
+ *bits_per_frame = sample_rate / 50;
+ return 0;
+}
+
diff --git a/gst/siren/common.h b/gst/siren/common.h
new file mode 100644
index 00000000..1ed342ce
--- /dev/null
+++ b/gst/siren/common.h
@@ -0,0 +1,146 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#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();
+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_LE16(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/gst/siren/dct4.c b/gst/siren/dct4.c
new file mode 100644
index 00000000..2fee4880
--- /dev/null
+++ b/gst/siren/dct4.c
@@ -0,0 +1,184 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "siren7.h"
+
+
+#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() {
+ 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/gst/siren/dct4.h b/gst/siren/dct4.h
new file mode 100644
index 00000000..6394b131
--- /dev/null
+++ b/gst/siren/dct4.h
@@ -0,0 +1,30 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _SIREN7_DCT4_H_
+#define _SIREN7_DCT4_H_
+
+extern void siren_dct4_init();
+extern void siren_dct4(float *Source, float *Destination, int dct_length);
+
+
+#endif /* _SIREN7_DCT4_H_ */
diff --git a/gst/siren/decoder.c b/gst/siren/decoder.c
new file mode 100644
index 00000000..c5067f7b
--- /dev/null
+++ b/gst/siren/decoder.c
@@ -0,0 +1,234 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "siren7.h"
+
+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/gst/siren/decoder.h b/gst/siren/decoder.h
new file mode 100644
index 00000000..58c1406b
--- /dev/null
+++ b/gst/siren/decoder.h
@@ -0,0 +1,52 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _SIREN_DECODER_H
+#define _SIREN_DECODER_H
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "dct4.h"
+#include "rmlt.h"
+#include "huffman.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;
+
+
+/* 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/gst/siren/encoder.c b/gst/siren/encoder.c
new file mode 100644
index 00000000..9d89eb51
--- /dev/null
+++ b/gst/siren/encoder.c
@@ -0,0 +1,234 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+
+#include "siren7.h"
+
+
+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/gst/siren/encoder.h b/gst/siren/encoder.h
new file mode 100644
index 00000000..a53185ca
--- /dev/null
+++ b/gst/siren/encoder.h
@@ -0,0 +1,47 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#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/gst/siren/gstrtpsirendepay.c b/gst/siren/gstrtpsirendepay.c
new file mode 100644
index 00000000..9e6c5345
--- /dev/null
+++ b/gst/siren/gstrtpsirendepay.c
@@ -0,0 +1,142 @@
+/*
+ * Siren Depayloader Gst Element
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <gst/rtp/gstrtpbuffer.h>
+#include "gstrtpsirendepay.h"
+
+/* elementfactory information */
+static const GstElementDetails gst_rtp_siren_depay_details =
+GST_ELEMENT_DETAILS ("RTP Siren packet depayloader",
+ "Codec/Depayloader/Network",
+ "Extracts Siren audio from RTP packets",
+ "Philippe Kalaf <philippe.kalaf@collabora.co.uk>");
+
+
+static GstStaticPadTemplate gst_rtp_siren_depay_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("application/x-rtp, "
+ "media = (string) \"audio\", "
+ "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
+ "clock-rate = (int) 16000, "
+ "encoding-name = (string) \"SIREN\", "
+ "dct-length = (int) 320")
+ );
+
+static GstStaticPadTemplate gst_rtp_siren_depay_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-siren, " "dct-length = (int) 320")
+ );
+
+static GstBuffer *gst_rtp_siren_depay_process (GstBaseRTPDepayload * depayload,
+ GstBuffer * buf);
+static gboolean gst_rtp_siren_depay_setcaps (GstBaseRTPDepayload * depayload,
+ GstCaps * caps);
+
+GST_BOILERPLATE (GstRTPSirenDepay, gst_rtp_siren_depay, GstBaseRTPDepayload,
+ GST_TYPE_BASE_RTP_DEPAYLOAD);
+
+static void
+gst_rtp_siren_depay_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_rtp_siren_depay_src_template));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_rtp_siren_depay_sink_template));
+ gst_element_class_set_details (element_class, &gst_rtp_siren_depay_details);
+}
+
+static void
+gst_rtp_siren_depay_class_init (GstRTPSirenDepayClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseRTPDepayloadClass *gstbasertpdepayload_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass;
+
+ gstbasertpdepayload_class->process = gst_rtp_siren_depay_process;
+ gstbasertpdepayload_class->set_caps = gst_rtp_siren_depay_setcaps;
+}
+
+static void
+gst_rtp_siren_depay_init (GstRTPSirenDepay * rtpsirendepay,
+ GstRTPSirenDepayClass * klass)
+{
+
+}
+
+static gboolean
+gst_rtp_siren_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
+{
+ GstCaps *srccaps;
+ gboolean ret;
+
+ srccaps = gst_caps_new_simple ("audio/x-siren",
+ "dct-length", G_TYPE_INT, 320, NULL);
+ ret = gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), srccaps);
+
+ GST_DEBUG ("set caps on source: %" GST_PTR_FORMAT " (ret=%d)", srccaps, ret);
+ gst_caps_unref (srccaps);
+
+ /* always fixed clock rate of 16000 */
+ depayload->clock_rate = 16000;
+
+ return ret;
+}
+
+static GstBuffer *
+gst_rtp_siren_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
+{
+ GstBuffer *outbuf;
+
+ g_print ("process : got %d bytes, mark %d ts %u seqn %d, header len %d, payload len %d\n",
+ GST_BUFFER_SIZE (buf),
+ gst_rtp_buffer_get_marker (buf),
+ gst_rtp_buffer_get_timestamp (buf),
+ gst_rtp_buffer_get_seq (buf),
+ gst_rtp_buffer_get_header_len (buf),
+ gst_rtp_buffer_get_payload_len (buf));
+
+ outbuf = gst_rtp_buffer_get_payload_buffer (buf);
+
+ return outbuf;
+}
+
+gboolean
+gst_rtp_siren_depay_plugin_init (GstPlugin * plugin)
+{
+ return gst_element_register (plugin, "rtpsirendepay",
+ GST_RANK_MARGINAL, GST_TYPE_RTP_SIREN_DEPAY);
+}
diff --git a/gst/siren/gstrtpsirendepay.h b/gst/siren/gstrtpsirendepay.h
new file mode 100644
index 00000000..0ef6dd02
--- /dev/null
+++ b/gst/siren/gstrtpsirendepay.h
@@ -0,0 +1,60 @@
+/*
+ * Siren Depayloader Gst Element
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_RTP_SIREN_DEPAY_H__
+#define __GST_RTP_SIREN_DEPAY_H__
+
+#include <gst/gst.h>
+#include <gst/rtp/gstbasertpdepayload.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstRTPSirenDepay GstRTPSirenDepay;
+typedef struct _GstRTPSirenDepayClass GstRTPSirenDepayClass;
+
+#define GST_TYPE_RTP_SIREN_DEPAY \
+ (gst_rtp_siren_depay_get_type())
+#define GST_RTP_SIREN_DEPAY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_SIREN_DEPAY,GstRTPSirenDepay))
+#define GST_RTP_SIREN_DEPAY_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_SIREN_DEPAY,GstRTPSirenDepayClass))
+#define GST_IS_RTP_SIREN_DEPAY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_SIREN_DEPAY))
+#define GST_IS_RTP_SIREN_DEPAY_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_SIREN_DEPAY))
+
+
+struct _GstRTPSirenDepay
+{
+ GstBaseRTPDepayload depayload;
+
+};
+
+struct _GstRTPSirenDepayClass
+{
+ GstBaseRTPDepayloadClass parent_class;
+};
+
+gboolean gst_rtp_siren_depay_plugin_init (GstPlugin * plugin);
+
+G_END_DECLS
+
+#endif /* __GST_RTP_SIREN_DEPAY_H__ */
diff --git a/gst/siren/gstrtpsirenpay.c b/gst/siren/gstrtpsirenpay.c
new file mode 100644
index 00000000..dff8ae7b
--- /dev/null
+++ b/gst/siren/gstrtpsirenpay.c
@@ -0,0 +1,163 @@
+/*
+ * Siren Payloader Gst Element
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstrtpsirenpay.h"
+#include <gst/rtp/gstrtpbuffer.h>
+
+/* elementfactory information */
+static GstElementDetails gst_rtpsirenpay_details = {
+ "RTP Payloader for Siren Audio",
+ "Codec/Payloader/Network",
+ "Packetize Siren audio streams into RTP packets",
+ "Youness Alaoui <kakaroto@kakaroto.homelinux.net>"
+};
+
+GST_DEBUG_CATEGORY_STATIC (rtpsirenpay_debug);
+#define GST_CAT_DEFAULT (rtpsirenpay_debug)
+
+static GstStaticPadTemplate gst_rtpsirenpay_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-siren, " "dct-length = (int) 320")
+ );
+
+static GstStaticPadTemplate gst_rtpsirenpay_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("application/x-rtp, "
+ "media = (string) \"audio\", "
+ "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
+ "clock-rate = (int) 16000, "
+ "encoding-name = (string) \"SIREN\", "
+ "dct-length = (int) 320")
+ );
+
+static gboolean gst_rtpsirenpay_setcaps (GstBaseRTPPayload * payload,
+ GstCaps * caps);
+
+GST_BOILERPLATE (GstRTPSirenPay, gst_rtpsirenpay, GstBaseRTPAudioPayload,
+ GST_TYPE_BASE_RTP_AUDIO_PAYLOAD);
+
+static void
+gst_rtpsirenpay_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_rtpsirenpay_sink_template));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_rtpsirenpay_src_template));
+ gst_element_class_set_details (element_class, &gst_rtpsirenpay_details);
+}
+
+static void
+gst_rtpsirenpay_class_init (GstRTPSirenPayClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseRTPPayloadClass *gstbasertppayload_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
+
+ parent_class = g_type_class_ref (GST_TYPE_BASE_RTP_PAYLOAD);
+
+ gstbasertppayload_class->set_caps = gst_rtpsirenpay_setcaps;
+
+ GST_DEBUG_CATEGORY_INIT (rtpsirenpay_debug, "rtpsirenpay", 0,
+ "siren audio RTP payloader");
+}
+
+static void
+gst_rtpsirenpay_init (GstRTPSirenPay * rtpsirenpay, GstRTPSirenPayClass * klass)
+{
+ GstBaseRTPPayload *basertppayload;
+ GstBaseRTPAudioPayload *basertpaudiopayload;
+
+ basertppayload = GST_BASE_RTP_PAYLOAD (rtpsirenpay);
+ basertpaudiopayload = GST_BASE_RTP_AUDIO_PAYLOAD (rtpsirenpay);
+
+ /* we don't set the payload type, it should be set by the application using
+ * the pt property or the default 96 will be used */
+ basertppayload->clock_rate = 16000;
+
+ /* tell basertpaudiopayload that this is a frame based codec */
+ gst_base_rtp_audio_payload_set_frame_based (basertpaudiopayload);
+}
+
+static gboolean
+gst_rtpsirenpay_setcaps (GstBaseRTPPayload * basertppayload, GstCaps * caps)
+{
+ GstRTPSirenPay *rtpsirenpay;
+ GstBaseRTPAudioPayload *basertpaudiopayload;
+ gboolean ret;
+ gint dct_length;
+ GstStructure *structure;
+ const char *payload_name;
+
+ rtpsirenpay = GST_RTP_SIREN_PAY (basertppayload);
+ basertpaudiopayload = GST_BASE_RTP_AUDIO_PAYLOAD (basertppayload);
+
+ structure = gst_caps_get_structure (caps, 0);
+
+ gst_structure_get_int (structure, "dct-length", &dct_length);
+ if (dct_length != 320)
+ goto wrong_dct;
+
+ payload_name = gst_structure_get_name (structure);
+ if (g_strcasecmp ("audio/x-siren", payload_name))
+ goto wrong_caps;
+
+ gst_basertppayload_set_options (basertppayload, "audio", TRUE, "SIREN", 16000);
+ /* set options for this frame based audio codec */
+ gst_base_rtp_audio_payload_set_frame_options (basertpaudiopayload, 20, 40);
+
+ ret = gst_basertppayload_set_outcaps (basertppayload, NULL);
+
+ return TRUE;
+
+ /* ERRORS */
+wrong_dct:
+ {
+ GST_ERROR_OBJECT (rtpsirenpay, "dct-length must be 320, received %d", dct_length);
+ return FALSE;
+ }
+wrong_caps:
+ {
+ GST_ERROR_OBJECT (rtpsirenpay, "expected audio/x-siren, received %s",
+ payload_name);
+ return FALSE;
+ }
+}
+
+gboolean
+gst_rtp_siren_pay_plugin_init (GstPlugin * plugin)
+{
+ return gst_element_register (plugin, "rtpsirenpay",
+ GST_RANK_NONE, GST_TYPE_RTP_SIREN_PAY);
+}
diff --git a/gst/siren/gstrtpsirenpay.h b/gst/siren/gstrtpsirenpay.h
new file mode 100644
index 00000000..9adeae76
--- /dev/null
+++ b/gst/siren/gstrtpsirenpay.h
@@ -0,0 +1,58 @@
+/*
+ * Siren Payloader Gst Element
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_RTP_SIREN_PAY_H__
+#define __GST_RTP_SIREN_PAY_H__
+
+#include <gst/gst.h>
+#include <gst/rtp/gstbasertpaudiopayload.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_RTP_SIREN_PAY \
+ (gst_rtpsirenpay_get_type())
+#define GST_RTP_SIREN_PAY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_SIREN_PAY,GstRTPSirenPay))
+#define GST_RTP_SIREN_PAY_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_SIREN_PAY,GstRTPSirenPayClass))
+#define GST_IS_RTP_SIREN_PAY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_SIREN_PAY))
+#define GST_IS_RTP_SIREN_PAY_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_SIREN_PAY))
+
+typedef struct _GstRTPSirenPay GstRTPSirenPay;
+typedef struct _GstRTPSirenPayClass GstRTPSirenPayClass;
+
+struct _GstRTPSirenPay
+{
+ GstBaseRTPAudioPayload audiopayload;
+};
+
+struct _GstRTPSirenPayClass
+{
+ GstBaseRTPAudioPayloadClass parent_class;
+};
+
+gboolean gst_rtp_siren_pay_plugin_init (GstPlugin * plugin);
+
+G_END_DECLS
+
+#endif /* __GST_RTP_SIREN_PAY_H__ */
diff --git a/gst/siren/gstsiren.c b/gst/siren/gstsiren.c
new file mode 100644
index 00000000..299887f3
--- /dev/null
+++ b/gst/siren/gstsiren.c
@@ -0,0 +1,55 @@
+/*
+ * Siren encoding/Decoder Gst plugin
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstsirendec.h"
+#include "gstsirenenc.h"
+#include "gstrtpsirenpay.h"
+#include "gstrtpsirendepay.h"
+
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ if (!gst_siren_dec_plugin_init (plugin))
+ return FALSE;
+
+ if (!gst_siren_enc_plugin_init (plugin))
+ return FALSE;
+
+ if (!gst_rtp_siren_pay_plugin_init (plugin))
+ return FALSE;
+
+ if (!gst_rtp_siren_depay_plugin_init (plugin))
+ return FALSE;
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "gstsiren",
+ "Siren encoder/decoder/payloader/depayloader plugins",
+ plugin_init, "0.1" , "LGPL", "Siren", "");
diff --git a/gst/siren/gstsiren.h b/gst/siren/gstsiren.h
new file mode 100644
index 00000000..92b662ba
--- /dev/null
+++ b/gst/siren/gstsiren.h
@@ -0,0 +1,69 @@
+/*
+ * Siren encoding/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GST_SIREN_H__
+#define __GST_SIREN_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+
+G_BEGIN_DECLS
+
+/* #define's don't like whitespacey bits */
+#define GST_TYPE_SIREN \
+ (gst_siren_get_type())
+#define GST_SIREN(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ GST_TYPE_SIREN,GstSiren))
+#define GST_SIREN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), \
+ GST_TYPE_SIREN,GstSirenClass))
+#define GST_IS_SIREN(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SIREN))
+#define GST_IS_SIREN_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SIREN))
+
+typedef struct _GstSiren GstSiren;
+typedef struct _GstSirenClass GstSirenClass;
+typedef struct _GstSirenPrivate GstSirenPrivate;
+
+struct _GstSiren
+{
+ GstBaseTransform parent;
+
+ /*< private > */
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+struct _GstSirenClass
+{
+ GstBaseTransformClass parent_class;
+
+ /*< private > */
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+GType gst_siren_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_SIREN_H__ */
diff --git a/gst/siren/gstsirendec.c b/gst/siren/gstsirendec.c
new file mode 100644
index 00000000..97061b82
--- /dev/null
+++ b/gst/siren/gstsirendec.c
@@ -0,0 +1,341 @@
+/*
+ * Siren Decoder Gst Element
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstsirendec.h"
+
+#include <string.h>
+
+GST_DEBUG_CATEGORY (sirendec_debug);
+#define GST_CAT_DEFAULT (sirendec_debug)
+
+/* elementfactory information */
+static const GstElementDetails gst_siren_dec_details =
+GST_ELEMENT_DETAILS (
+ "Siren Decoder element",
+ "Codec/Decoder/Audio ",
+ "Decode streams encoded with the Siren7 codec into 16bit PCM",
+ "Youness Alaoui <kakaroto@kakaroto.homelinux.net>");
+
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-siren, "
+ "dct-length = (int) 320"));
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "width = (int) 16, "
+ "depth = (int) 16, "
+ "endianness = (int) 1234, "
+ "signed = (boolean) true, "
+ "rate = (int) 16000, "
+ "channels = (int) 1"));
+
+/* signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ ARG_0,
+};
+
+
+
+static void gst_siren_dec_dispose (GObject *object);
+
+static GstFlowReturn gst_siren_dec_transform (GstBaseTransform *trans,
+ GstBuffer *inbuf, GstBuffer *outbuf);
+static gboolean gst_siren_dec_transform_size (GstBaseTransform *trans,
+ GstPadDirection direction, GstCaps *caps, guint size,
+ GstCaps *othercaps, guint *othersize);
+static GstCaps * gst_siren_dec_transform_caps (GstBaseTransform * base,
+ GstPadDirection direction, GstCaps * caps);
+static gboolean gst_siren_dec_start (GstBaseTransform *trans);
+static gboolean gst_siren_dec_stop (GstBaseTransform *trans);
+
+
+static void
+_do_init (GType type)
+{
+ GST_DEBUG_CATEGORY_INIT
+ (sirendec_debug, "sirendec", 0, "sirendec");
+}
+
+GST_BOILERPLATE_FULL (GstSirenDec, gst_siren_dec, GstBaseTransform,
+ GST_TYPE_BASE_TRANSFORM, _do_init);
+
+static void
+gst_siren_dec_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&srctemplate));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&sinktemplate));
+
+ gst_element_class_set_details (element_class, &gst_siren_dec_details);
+}
+
+static void
+gst_siren_dec_class_init (GstSirenDecClass *klass)
+{
+ GObjectClass *gobject_class;
+ GstBaseTransformClass *gstbasetransform_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstbasetransform_class = (GstBaseTransformClass *) klass;
+
+ GST_DEBUG ("Initializing Class");
+
+ gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_siren_dec_dispose);
+
+ gstbasetransform_class->transform =
+ GST_DEBUG_FUNCPTR (gst_siren_dec_transform);
+ gstbasetransform_class->transform_caps =
+ GST_DEBUG_FUNCPTR (gst_siren_dec_transform_caps);
+ gstbasetransform_class->transform_size =
+ GST_DEBUG_FUNCPTR (gst_siren_dec_transform_size);
+ gstbasetransform_class->start =
+ GST_DEBUG_FUNCPTR (gst_siren_dec_start);
+ gstbasetransform_class->stop =
+ GST_DEBUG_FUNCPTR (gst_siren_dec_stop);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ GST_DEBUG ("Class Init done");
+}
+
+static void
+gst_siren_dec_init (GstSirenDec *dec, GstSirenDecClass *klass)
+{
+
+ GST_DEBUG ("Initializing");
+ dec->decoder = NULL;
+ dec->adapter = gst_adapter_new ();
+
+ GST_DEBUG ("Init done");
+}
+
+static void
+gst_siren_dec_dispose (GObject *object)
+{
+ GstSirenDec *dec = GST_SIREN_DEC (object);
+
+ GST_DEBUG ("Disposing");
+
+ if (dec->decoder) {
+ Siren7_CloseDecoder (dec->decoder);
+ dec->decoder = NULL;
+ }
+ if (dec->adapter) {
+ g_object_unref (dec->adapter);
+ dec->adapter = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+
+ GST_DEBUG ("Dispose done");
+
+}
+
+static gboolean
+gst_siren_dec_start (GstBaseTransform *trans)
+{
+ GstSirenDec *dec = GST_SIREN_DEC (trans);
+
+ GST_DEBUG ("Start");
+
+ if (dec->decoder) {
+ Siren7_CloseDecoder (dec->decoder);
+ dec->decoder = NULL;
+ }
+ dec->decoder = Siren7_NewDecoder (16000);
+ gst_adapter_clear (dec->adapter);
+
+ return dec->decoder != NULL;
+}
+
+
+
+static gboolean
+gst_siren_dec_stop (GstBaseTransform *trans)
+{
+ GstSirenDec *dec = GST_SIREN_DEC (trans);
+
+ GST_DEBUG ("Stop");
+
+ if (dec->decoder) {
+ Siren7_CloseDecoder (dec->decoder);
+ dec->decoder = NULL;
+ }
+ gst_adapter_clear (dec->adapter);
+ return TRUE;
+}
+
+
+static gboolean gst_siren_dec_transform_size (GstBaseTransform *trans,
+ GstPadDirection direction, GstCaps *caps, guint size,
+ GstCaps *othercaps, guint *othersize)
+{
+ GstSirenDec *dec = GST_SIREN_DEC (trans);
+ GstStructure *structure = NULL;
+ const gchar *in_name = NULL;
+ const gchar *out_name = NULL;
+ gboolean decoding;
+
+ if (caps != NULL && othercaps != NULL) {
+ structure = gst_caps_get_structure (caps, 0);
+ in_name = gst_structure_get_name (structure);
+ structure = gst_caps_get_structure (othercaps, 0);
+ out_name = gst_structure_get_name (structure);
+ }
+
+ GST_DEBUG ("Transform size from caps '%s' to '%s'", in_name, out_name);
+
+ if (in_name == NULL || out_name == NULL) {
+ if (direction == GST_PAD_SINK)
+ decoding = TRUE;
+ else
+ decoding = FALSE;
+ } else if (strcmp (in_name, "audio/x-raw-int") == 0 &&
+ strcmp (out_name, "audio/x-siren") == 0 ) {
+ decoding = FALSE;
+ } else if (strcmp (in_name, "audio/x-siren") == 0 &&
+ strcmp (out_name, "audio/x-raw-int") == 0 ) {
+ decoding = TRUE;
+ } else {
+ GST_DEBUG ("Unknown in/out caps");
+ return FALSE;
+ }
+
+ if (decoding) {
+ size += gst_adapter_available (dec->adapter);
+ *othersize = size * 16;
+ *othersize -= *othersize % 640;
+ if ((size * 16) % 640 > 0)
+ *othersize+= 640;
+ } else {
+ *othersize = size / 16;
+ *othersize -= *othersize % 40;
+ if ((size / 16) % 40 > 0)
+ *othersize+= 40;
+ }
+ GST_DEBUG ("Transform size %d to %d", size, *othersize);
+
+ return TRUE;
+}
+
+static GstCaps * gst_siren_dec_transform_caps (GstBaseTransform * base,
+ GstPadDirection direction, GstCaps * caps)
+{
+ GstCaps *othercaps = NULL;
+ GST_DEBUG ("Transforming caps");
+
+ if (direction == GST_PAD_SINK) {
+ return gst_static_pad_template_get_caps (&srctemplate);
+ } else if (direction == GST_PAD_SRC) {
+ return gst_static_pad_template_get_caps (&sinktemplate);
+ }
+
+ GST_DEBUG ("Transform caps");
+
+ return othercaps;
+}
+
+static GstFlowReturn
+gst_siren_dec_transform (GstBaseTransform *trans, GstBuffer *inbuf,
+ GstBuffer *outbuf)
+{
+
+ GstSirenDec *dec = GST_SIREN_DEC (trans);
+ GstFlowReturn ret = GST_FLOW_OK;
+ guint8 *data = NULL;
+ gint offset = 0;
+ gint decode_ret = 0;
+
+ GST_DEBUG ("Transform");
+
+ if (dec->decoder == NULL) {
+ GST_DEBUG ("Siren decoder not set");
+ return GST_FLOW_WRONG_STATE;
+ }
+ if (dec->adapter == NULL) {
+ GST_DEBUG ("Adapter not set");
+ return GST_FLOW_UNEXPECTED;
+ }
+
+ gst_buffer_ref (inbuf);
+ gst_adapter_push (dec->adapter, inbuf);
+
+ GST_DEBUG ("Received buffer of size %d with adapter of size : %d",
+ GST_BUFFER_SIZE (inbuf), gst_adapter_available (dec->adapter));
+
+ data = GST_BUFFER_DATA (outbuf);
+ offset = 0;
+ while((gst_adapter_available (dec->adapter) >= 40) &&
+ (offset + 640 <= GST_BUFFER_SIZE (outbuf)) &&
+ ret == GST_FLOW_OK) {
+
+ GST_DEBUG ("Decoding frame");
+
+ decode_ret = Siren7_DecodeFrame (dec->decoder,
+ (guint8 *) gst_adapter_peek (dec->adapter, 40),
+ data + offset);
+ if (decode_ret != 0) {
+ GST_DEBUG ("Siren7_DecodeFrame returned %d", decode_ret);
+ ret = GST_FLOW_ERROR;
+ }
+
+ gst_adapter_flush (dec->adapter, 40);
+ offset += 640;
+ }
+
+ GST_DEBUG ("Finished decoding : %d", offset);
+ if (offset != GST_BUFFER_SIZE (outbuf)) {
+ GST_DEBUG ("didn't decode enough : offfset (%d) != BUFFER_SIZE (%d)",
+ offset, GST_BUFFER_SIZE (outbuf));
+ return GST_FLOW_ERROR;
+ }
+
+ return ret;
+}
+
+
+
+gboolean
+gst_siren_dec_plugin_init (GstPlugin *plugin)
+{
+ return gst_element_register (plugin, "sirendec",
+ GST_RANK_MARGINAL, GST_TYPE_SIREN_DEC);
+}
diff --git a/gst/siren/gstsirendec.h b/gst/siren/gstsirendec.h
new file mode 100644
index 00000000..256f3d10
--- /dev/null
+++ b/gst/siren/gstsirendec.h
@@ -0,0 +1,79 @@
+/*
+ * Siren Decoder Gst Element
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GST_SIREN_DEC_H__
+#define __GST_SIREN_DEC_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/base/gstadapter.h>
+
+#include "siren7.h"
+
+G_BEGIN_DECLS
+
+/* #define's don't like whitespacey bits */
+#define GST_TYPE_SIREN_DEC \
+ (gst_siren_dec_get_type())
+#define GST_SIREN_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ GST_TYPE_SIREN_DEC,GstSirenDec))
+#define GST_SIREN_DEC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), \
+ GST_TYPE_SIREN_DEC,GstSirenDecClass))
+#define GST_IS_SIREN_DEC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SIREN_DEC))
+#define GST_IS_SIREN_DEC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SIREN_DEC))
+
+typedef struct _GstSirenDec GstSirenDec;
+typedef struct _GstSirenDecClass GstSirenDecClass;
+typedef struct _GstSirenDecPrivate GstSirenDecPrivate;
+
+struct _GstSirenDec
+{
+ GstBaseTransform parent;
+
+ SirenDecoder decoder;
+ GstAdapter *adapter;
+
+ /*< private > */
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+struct _GstSirenDecClass
+{
+ GstBaseTransformClass parent_class;
+
+
+ /*< private > */
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+GType gst_siren_dec_get_type (void);
+
+gboolean
+gst_siren_dec_plugin_init (GstPlugin *plugin);
+
+G_END_DECLS
+
+#endif /* __GST_SIREN_DEC_H__ */
diff --git a/gst/siren/gstsirenenc.c b/gst/siren/gstsirenenc.c
new file mode 100644
index 00000000..5ffb6641
--- /dev/null
+++ b/gst/siren/gstsirenenc.c
@@ -0,0 +1,330 @@
+/*
+ * Siren Encoder Gst Element
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstsirenenc.h"
+
+#include <string.h>
+
+GST_DEBUG_CATEGORY (sirenenc_debug);
+#define GST_CAT_DEFAULT (sirenenc_debug)
+
+/* elementfactory information */
+static const GstElementDetails gst_siren_enc_details =
+GST_ELEMENT_DETAILS (
+ "Siren Encoder element",
+ "Codec/Encoder/Audio ",
+ "Encode 16bit PCM streams into the Siren7 codec",
+ "Youness Alaoui <kakaroto@kakaroto.homelinux.net>");
+
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-siren, "
+ "dct-length = (int) 320"));
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "width = (int) 16, "
+ "depth = (int) 16, "
+ "endianness = (int) 1234, "
+ "signed = (boolean) true, "
+ "rate = (int) 16000, "
+ "channels = (int) 1"));
+
+/* signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ ARG_0,
+};
+
+
+
+static void gst_siren_enc_dispose (GObject *object);
+
+static GstFlowReturn gst_siren_enc_transform (GstBaseTransform *trans,
+ GstBuffer *inbuf, GstBuffer *outbuf);
+static gboolean gst_siren_enc_transform_size (GstBaseTransform *trans,
+ GstPadDirection direction, GstCaps *caps, guint size,
+ GstCaps *othercaps, guint *othersize);
+static GstCaps * gst_siren_enc_transform_caps (GstBaseTransform * base,
+ GstPadDirection direction, GstCaps * caps);
+static gboolean gst_siren_enc_start (GstBaseTransform *trans);
+static gboolean gst_siren_enc_stop (GstBaseTransform *trans);
+
+
+static void
+_do_init (GType type)
+{
+ GST_DEBUG_CATEGORY_INIT
+ (sirenenc_debug, "sirenenc", 0, "sirenenc");
+}
+
+GST_BOILERPLATE_FULL (GstSirenEnc, gst_siren_enc, GstBaseTransform,
+ GST_TYPE_BASE_TRANSFORM, _do_init);
+
+static void
+gst_siren_enc_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&srctemplate));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&sinktemplate));
+
+ gst_element_class_set_details (element_class, &gst_siren_enc_details);
+}
+
+static void
+gst_siren_enc_class_init (GstSirenEncClass *klass)
+{
+ GObjectClass *gobject_class;
+ GstBaseTransformClass *gstbasetransform_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstbasetransform_class = (GstBaseTransformClass *) klass;
+
+ GST_DEBUG ("Initializing Class");
+
+ gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_siren_enc_dispose);
+
+ gstbasetransform_class->transform =
+ GST_DEBUG_FUNCPTR (gst_siren_enc_transform);
+ gstbasetransform_class->transform_caps =
+ GST_DEBUG_FUNCPTR (gst_siren_enc_transform_caps);
+ gstbasetransform_class->transform_size =
+ GST_DEBUG_FUNCPTR (gst_siren_enc_transform_size);
+ gstbasetransform_class->start =
+ GST_DEBUG_FUNCPTR (gst_siren_enc_start);
+ gstbasetransform_class->stop =
+ GST_DEBUG_FUNCPTR (gst_siren_enc_stop);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ GST_DEBUG ("Class Init done");
+}
+
+static void
+gst_siren_enc_init (GstSirenEnc *enc, GstSirenEncClass *klass)
+{
+
+ GST_DEBUG ("Initializing");
+ enc->encoder = NULL;
+ enc->adapter = gst_adapter_new ();
+
+ GST_DEBUG ("Init done");
+}
+
+static void
+gst_siren_enc_dispose (GObject *object)
+{
+ GstSirenEnc *enc = GST_SIREN_ENC (object);
+
+ GST_DEBUG ("Disposing");
+
+ if (enc->encoder) {
+ Siren7_CloseEncoder (enc->encoder);
+ enc->encoder = NULL;
+ }
+ if (enc->adapter) {
+ g_object_unref (enc->adapter);
+ enc->adapter = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+
+ GST_DEBUG ("Dispose done");
+
+}
+
+static gboolean
+gst_siren_enc_start (GstBaseTransform *trans)
+{
+ GstSirenEnc *enc = GST_SIREN_ENC (trans);
+
+ GST_DEBUG ("Start");
+
+ if (enc->encoder) {
+ Siren7_CloseEncoder (enc->encoder);
+ enc->encoder = NULL;
+ }
+ enc->encoder = Siren7_NewEncoder (16000);
+ gst_adapter_clear (enc->adapter);
+
+ return enc->encoder != NULL;
+}
+
+
+
+static gboolean
+gst_siren_enc_stop (GstBaseTransform *trans)
+{
+ GstSirenEnc *enc = GST_SIREN_ENC (trans);
+
+ GST_DEBUG ("Stop");
+
+ if (enc->encoder) {
+ Siren7_CloseEncoder (enc->encoder);
+ enc->encoder = NULL;
+ }
+ gst_adapter_clear (enc->adapter);
+ return TRUE;
+}
+
+
+static gboolean gst_siren_enc_transform_size (GstBaseTransform *trans,
+ GstPadDirection direction, GstCaps *caps, guint size,
+ GstCaps *othercaps, guint *othersize)
+{
+ GstSirenEnc *enc = GST_SIREN_ENC (trans);
+ GstStructure *structure;
+ const gchar *in_name;
+ const gchar *out_name;
+
+ if (caps == NULL || othercaps == NULL) {
+ GST_WARNING ("caps NULL");
+ return FALSE;
+ }
+
+ structure = gst_caps_get_structure (caps, 0);
+ in_name = gst_structure_get_name (structure);
+ structure = gst_caps_get_structure (othercaps, 0);
+ out_name = gst_structure_get_name (structure);
+
+ GST_DEBUG ("Transform size from caps '%s' to '%s'", in_name, out_name);
+
+ if (in_name == NULL || out_name == NULL) {
+ return FALSE;
+ } else if (strcmp (in_name, "audio/x-raw-int") == 0 &&
+ strcmp (out_name, "audio/x-siren") == 0 ) {
+ size += gst_adapter_available (enc->adapter);
+ *othersize = size / 16;
+ *othersize -= *othersize % 40;
+ if ((size / 16) % 40 > 0)
+ *othersize+=40;
+ } else if (strcmp (in_name, "audio/x-siren") == 0 &&
+ strcmp (out_name, "audio/x-raw-int") == 0 ) {
+ *othersize = size * 16;
+ *othersize -= *othersize % 640;
+ if ((size * 16) % 640 > 0)
+ *othersize+= 640;
+ } else {
+ GST_DEBUG ("Unknown in/out caps");
+ return FALSE;
+ }
+
+ GST_DEBUG ("Transform size %d to %d", size, *othersize);
+
+ return TRUE;
+}
+
+static GstCaps * gst_siren_enc_transform_caps (GstBaseTransform * base,
+ GstPadDirection direction, GstCaps * caps)
+{
+ GST_DEBUG ("Transforming caps");
+
+ if (direction == GST_PAD_SRC) {
+ return gst_static_pad_template_get_caps (&sinktemplate);
+ } else if (direction == GST_PAD_SINK) {
+ return gst_static_pad_template_get_caps (&srctemplate);
+ }
+
+ /* Make gcc happy */
+ return NULL;
+}
+
+static GstFlowReturn
+gst_siren_enc_transform (GstBaseTransform *trans, GstBuffer *inbuf,
+ GstBuffer *outbuf)
+{
+
+ GstSirenEnc *enc = GST_SIREN_ENC (trans);
+ GstFlowReturn ret = GST_FLOW_OK;
+ guint8 *data = NULL;
+ gint offset = 0;
+ gint encode_ret = 0;
+
+ GST_DEBUG ("Transform");
+
+ if (enc->encoder == NULL) {
+ GST_DEBUG ("Siren encoder not set");
+ return GST_FLOW_WRONG_STATE;
+ }
+ if (enc->adapter == NULL) {
+ GST_DEBUG ("Adapter not set");
+ return GST_FLOW_UNEXPECTED;
+ }
+
+ gst_buffer_ref (inbuf);
+ gst_adapter_push (enc->adapter, inbuf);
+
+ GST_DEBUG ("Received buffer of size %d with adapter of size : %d",
+ GST_BUFFER_SIZE (inbuf), gst_adapter_available (enc->adapter));
+
+ data = GST_BUFFER_DATA (outbuf);
+ offset = 0;
+ while(gst_adapter_available (enc->adapter) >= 640 &&
+ offset + 40 <= GST_BUFFER_SIZE (outbuf) &&
+ ret == GST_FLOW_OK) {
+
+ GST_DEBUG ("Encoding frame");
+
+ encode_ret = Siren7_EncodeFrame (enc->encoder,
+ (guint8 *)gst_adapter_peek (enc->adapter, 640),
+ data + offset);
+ if (encode_ret != 0) {
+ GST_DEBUG ("Siren7_EncodeFrame returned %d", encode_ret);
+ ret = GST_FLOW_ERROR;
+ }
+
+ gst_adapter_flush (enc->adapter, 640);
+ offset += 40;
+ }
+
+ GST_DEBUG ("Finished encoding : %d", offset);
+
+ GST_BUFFER_SIZE (outbuf) = offset;
+
+ return ret;
+}
+
+
+
+gboolean
+gst_siren_enc_plugin_init (GstPlugin *plugin)
+{
+ return gst_element_register (plugin, "sirenenc",
+ GST_RANK_MARGINAL, GST_TYPE_SIREN_ENC);
+}
diff --git a/gst/siren/gstsirenenc.h b/gst/siren/gstsirenenc.h
new file mode 100644
index 00000000..1b3937d3
--- /dev/null
+++ b/gst/siren/gstsirenenc.h
@@ -0,0 +1,79 @@
+/*
+ * Siren Encoder Gst Element
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GST_SIREN_ENC_H__
+#define __GST_SIREN_ENC_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/base/gstadapter.h>
+
+#include "siren7.h"
+
+G_BEGIN_DECLS
+
+/* #define's don't like whitespacey bits */
+#define GST_TYPE_SIREN_ENC \
+ (gst_siren_enc_get_type())
+#define GST_SIREN_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ GST_TYPE_SIREN_ENC,GstSirenEnc))
+#define GST_SIREN_ENC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), \
+ GST_TYPE_SIREN_ENC,GstSirenEncClass))
+#define GST_IS_SIREN_ENC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SIREN_ENC))
+#define GST_IS_SIREN_ENC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SIREN_ENC))
+
+typedef struct _GstSirenEnc GstSirenEnc;
+typedef struct _GstSirenEncClass GstSirenEncClass;
+typedef struct _GstSirenEncPrivate GstSirenEncPrivate;
+
+struct _GstSirenEnc
+{
+ GstBaseTransform parent;
+
+ SirenEncoder encoder;
+ GstAdapter *adapter;
+
+ /*< private > */
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+struct _GstSirenEncClass
+{
+ GstBaseTransformClass parent_class;
+
+
+ /*< private > */
+ gpointer _gst_reserved[GST_PADDING];
+};
+
+GType gst_siren_enc_get_type (void);
+
+gboolean
+gst_siren_enc_plugin_init (GstPlugin *plugin);
+
+G_END_DECLS
+
+#endif /* __GST_SIREN_ENC_H__ */
diff --git a/gst/siren/huffman.c b/gst/siren/huffman.c
new file mode 100644
index 00000000..35a4ae05
--- /dev/null
+++ b/gst/siren/huffman.c
@@ -0,0 +1,382 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "siren7.h"
+#include "huffman_consts.h"
+
+
+static short current_word = 0;
+static int bit_idx = 0;
+static int *bitstream_ptr = NULL;
+
+int next_bit() {
+ 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/gst/siren/huffman.h b/gst/siren/huffman.h
new file mode 100644
index 00000000..196932da
--- /dev/null
+++ b/gst/siren/huffman.h
@@ -0,0 +1,35 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#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();
+
+#endif /* _SIREN7_HUFFMAN_H_ */
diff --git a/gst/siren/huffman_consts.h b/gst/siren/huffman_consts.h
new file mode 100644
index 00000000..0a38c0bf
--- /dev/null
+++ b/gst/siren/huffman_consts.h
@@ -0,0 +1,528 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#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/gst/siren/rmlt.c b/gst/siren/rmlt.c
new file mode 100644
index 00000000..229b9106
--- /dev/null
+++ b/gst/siren/rmlt.c
@@ -0,0 +1,133 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "siren7.h"
+
+
+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() {
+ 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/gst/siren/rmlt.h b/gst/siren/rmlt.h
new file mode 100644
index 00000000..a855dd04
--- /dev/null
+++ b/gst/siren/rmlt.h
@@ -0,0 +1,30 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _SIREN7_RMLT_H_
+#define _SIREN7_RMLT_H_
+
+extern void siren_rmlt_init();
+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/gst/siren/siren7.h b/gst/siren/siren7.h
new file mode 100644
index 00000000..9a89811d
--- /dev/null
+++ b/gst/siren/siren7.h
@@ -0,0 +1,30 @@
+/*
+ * Siren Encoder/Decoder library
+ *
+ * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef _SIREN7_H
+#define _SIREN7_H
+
+#include "encoder.h"
+#include "decoder.h"
+
+
+#endif /* _SIREN7_H */