Chat-O-Matic/libs/libmsn/libsiren/decoder.cpp

235 lines
7.1 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., 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;
}