mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-15 12:56:33 +00:00
433 lines
12 KiB
C
433 lines
12 KiB
C
/*
|
|
* Siren Encoder/Decoder library
|
|
*
|
|
* @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
|
|
#include "siren7.h"
|
|
#include "huffman_consts.h"
|
|
|
|
|
|
static short current_word = 0;
|
|
static int bit_idx = 0;
|
|
static int *bitstream_ptr = NULL;
|
|
|
|
int
|
|
next_bit (void)
|
|
{
|
|
if (bitstream_ptr == NULL)
|
|
return -1;
|
|
|
|
if (bit_idx == 0) {
|
|
current_word = *bitstream_ptr++;
|
|
bit_idx = 16;
|
|
}
|
|
|
|
return (current_word >> --bit_idx) & 1;
|
|
}
|
|
|
|
void
|
|
set_bitstream (int *stream)
|
|
{
|
|
bitstream_ptr = stream;
|
|
current_word = *bitstream_ptr;
|
|
bit_idx = 0;
|
|
}
|
|
|
|
|
|
int
|
|
compute_region_powers (int number_of_regions, float *coefs, int *drp_num_bits,
|
|
int *drp_code_bits, int *absolute_region_power_index, int esf_adjustment)
|
|
{
|
|
float region_power = 0;
|
|
int num_bits;
|
|
int idx;
|
|
int max_idx, min_idx;
|
|
int region, i;
|
|
|
|
for (region = 0; region < number_of_regions; region++) {
|
|
region_power = 0.0f;
|
|
for (i = 0; i < region_size; i++) {
|
|
region_power +=
|
|
coefs[(region * region_size) + i] * coefs[(region * region_size) + i];
|
|
}
|
|
region_power *= region_size_inverse;
|
|
|
|
min_idx = 0;
|
|
max_idx = 64;
|
|
for (i = 0; i < 6; i++) {
|
|
idx = (min_idx + max_idx) / 2;
|
|
if (region_power_table_boundary[idx - 1] <= region_power) {
|
|
min_idx = idx;
|
|
} else {
|
|
max_idx = idx;
|
|
}
|
|
}
|
|
absolute_region_power_index[region] = min_idx - 24;
|
|
|
|
}
|
|
|
|
for (region = number_of_regions - 2; region >= 0; region--) {
|
|
if (absolute_region_power_index[region] <
|
|
absolute_region_power_index[region + 1] - 11)
|
|
absolute_region_power_index[region] =
|
|
absolute_region_power_index[region + 1] - 11;
|
|
}
|
|
|
|
if (absolute_region_power_index[0] < (1 - esf_adjustment))
|
|
absolute_region_power_index[0] = (1 - esf_adjustment);
|
|
|
|
if (absolute_region_power_index[0] > (31 - esf_adjustment))
|
|
absolute_region_power_index[0] = (31 - esf_adjustment);
|
|
|
|
drp_num_bits[0] = 5;
|
|
drp_code_bits[0] = absolute_region_power_index[0] + esf_adjustment;
|
|
|
|
|
|
for (region = 1; region < number_of_regions; region++) {
|
|
if (absolute_region_power_index[region] < (-8 - esf_adjustment))
|
|
absolute_region_power_index[region] = (-8 - esf_adjustment);
|
|
if (absolute_region_power_index[region] > (31 - esf_adjustment))
|
|
absolute_region_power_index[region] = (31 - esf_adjustment);
|
|
}
|
|
|
|
num_bits = 5;
|
|
|
|
for (region = 0; region < number_of_regions - 1; region++) {
|
|
idx =
|
|
absolute_region_power_index[region + 1] -
|
|
absolute_region_power_index[region] + 12;
|
|
if (idx < 0)
|
|
idx = 0;
|
|
|
|
absolute_region_power_index[region + 1] =
|
|
absolute_region_power_index[region] + idx - 12;
|
|
drp_num_bits[region + 1] = differential_region_power_bits[region][idx];
|
|
drp_code_bits[region + 1] = differential_region_power_codes[region][idx];
|
|
num_bits += drp_num_bits[region + 1];
|
|
}
|
|
|
|
return num_bits;
|
|
}
|
|
|
|
|
|
int
|
|
decode_envelope (int number_of_regions, float *decoder_standard_deviation,
|
|
int *absolute_region_power_index, int esf_adjustment)
|
|
{
|
|
int index;
|
|
int i;
|
|
int envelope_bits = 0;
|
|
|
|
index = 0;
|
|
for (i = 0; i < 5; i++)
|
|
index = (index << 1) | next_bit ();
|
|
envelope_bits = 5;
|
|
|
|
absolute_region_power_index[0] = index - esf_adjustment;
|
|
decoder_standard_deviation[0] =
|
|
standard_deviation[absolute_region_power_index[0] + 24];
|
|
|
|
for (i = 1; i < number_of_regions; i++) {
|
|
index = 0;
|
|
do {
|
|
index = differential_decoder_tree[i - 1][index][next_bit ()];
|
|
envelope_bits++;
|
|
} while (index > 0);
|
|
|
|
absolute_region_power_index[i] =
|
|
absolute_region_power_index[i - 1] - index - 12;
|
|
if (absolute_region_power_index[i] < -24)
|
|
absolute_region_power_index[i] = -24;
|
|
else if (absolute_region_power_index[i] > 39)
|
|
absolute_region_power_index[i] = 39;
|
|
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;
|
|
}
|