diff options
author | Youness Alaoui <youness.alaoui@collabora.co.uk> | 2008-04-10 07:01:16 +0000 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2009-02-17 19:29:39 +0100 |
commit | b9ea3bbe4f4948d667599c79f6cc2fcf414e47a6 (patch) | |
tree | b7b165e3e1ee7fdca884b3b3aa38fb7f5d3e1b12 /gst/siren/encoder.c | |
parent | 79ebcb8fe5f4c856e87b51d7eaef9e59a53f763c (diff) | |
download | gst-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/siren/encoder.c')
-rw-r--r-- | gst/siren/encoder.c | 234 |
1 files changed, 234 insertions, 0 deletions
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; +} + |