mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-14 05:12:09 +00:00
257 lines
7.9 KiB
C
257 lines
7.9 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"
|
|
|
|
|
|
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;
|
|
}
|