From f40bfc9267b13b54e6379dfe7539447662879d24 Mon Sep 17 00:00:00 2001 From: Sean Bartell Date: Sat, 25 Jun 2011 21:32:25 -0400 Subject: Add codecs to librbcodec. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id7f4717d51ed02d67cb9f9cb3c0ada4a81843f97 Reviewed-on: http://gerrit.rockbox.org/137 Reviewed-by: Nils Wallménius Tested-by: Nils Wallménius --- lib/rbcodec/codecs/libwmapro/wma.c | 164 +++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 lib/rbcodec/codecs/libwmapro/wma.c (limited to 'lib/rbcodec/codecs/libwmapro/wma.c') diff --git a/lib/rbcodec/codecs/libwmapro/wma.c b/lib/rbcodec/codecs/libwmapro/wma.c new file mode 100644 index 0000000000..83cec89a4c --- /dev/null +++ b/lib/rbcodec/codecs/libwmapro/wma.c @@ -0,0 +1,164 @@ +/* + * WMA compatible codec + * Copyright (c) 2002-2007 The FFmpeg Project + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "wma.h" +#include "codeclib.h" /* needed for av_log2() */ + +/** + *@brief Get the samples per frame for this stream. + *@param sample_rate output sample_rate + *@param version wma version + *@param decode_flags codec compression features + *@return log2 of the number of output samples per frame + */ +int ff_wma_get_frame_len_bits(int sample_rate, int version, + unsigned int decode_flags) +{ + + int frame_len_bits; + + if (sample_rate <= 16000) { + frame_len_bits = 9; + } else if (sample_rate <= 22050 || + (sample_rate <= 32000 && version == 1)) { + frame_len_bits = 10; + } else if (sample_rate <= 48000) { + frame_len_bits = 11; + } else if (sample_rate <= 96000) { + frame_len_bits = 12; + } else { + frame_len_bits = 13; + } + + if (version == 3) { + int tmp = decode_flags & 0x6; + if (tmp == 0x2) { + ++frame_len_bits; + } else if (tmp == 0x4) { + --frame_len_bits; + } else if (tmp == 0x6) { + frame_len_bits -= 2; + } + } + + return frame_len_bits; +} + +/** + * Decode an uncompressed coefficient. + * @param s codec context + * @return the decoded coefficient + */ +unsigned int ff_wma_get_large_val(GetBitContext* gb) +{ + /** consumes up to 34 bits */ + int n_bits = 8; + /** decode length */ + if (get_bits1(gb)) { + n_bits += 8; + if (get_bits1(gb)) { + n_bits += 8; + if (get_bits1(gb)) { + n_bits += 7; + } + } + } + return get_bits_long(gb, n_bits); +} + +/** + * Decode run level compressed coefficients. + * @param avctx codec context + * @param gb bitstream reader context + * @param vlc vlc table for get_vlc2 + * @param level_table level codes + * @param run_table run codes + * @param version 0 for wma1,2 1 for wmapro + * @param ptr output buffer + * @param offset offset in the output buffer + * @param num_coefs number of input coefficents + * @param block_len input buffer length (2^n) + * @param frame_len_bits number of bits for escaped run codes + * @param coef_nb_bits number of bits for escaped level codes + * @return 0 on success, -1 otherwise + */ +#define av_log(...) +int ff_wma_run_level_decode(GetBitContext* gb, + VLC *vlc, + const int32_t *level_table, const uint16_t *run_table, + int version, int32_t *ptr, int offset, + int num_coefs, int block_len, int frame_len_bits, + int coef_nb_bits) +{ + int32_t code, level, sign; + const unsigned int coef_mask = block_len - 1; + /* Rockbox: To be able to use rockbox' optimized mdct we need to pre-shift + * the values by >>(nbits-3). */ + const int nbits = av_log2(block_len)+1; + const int shift = WMAPRO_FRACT-(nbits-3); + for (; offset < num_coefs; offset++) { + code = get_vlc2(gb, vlc->table, VLCBITS, VLCMAX); + if (code > 1) { + /** normal code */ + offset += run_table[code]; + sign = !get_bits1(gb); + /* Rockbox: To be able to use rockbox' optimized mdct we need + * invert the sign. */ + ptr[offset & coef_mask] = sign ? level_table[code] : -level_table[code]; + ptr[offset & coef_mask] <<= shift; + } else if (code == 1) { + /** EOB */ + break; + } else { + /** escape */ + if (!version) { + level = get_bits(gb, coef_nb_bits); + /** NOTE: this is rather suboptimal. reading + block_len_bits would be better */ + offset += get_bits(gb, frame_len_bits); + } else { + level = ff_wma_get_large_val(gb); + /** escape decode */ + if (get_bits1(gb)) { + if (get_bits1(gb)) { + if (get_bits1(gb)) { + av_log(avctx,AV_LOG_ERROR, + "broken escape sequence\n"); + return -1; + } else + offset += get_bits(gb, frame_len_bits) + 4; + } else + offset += get_bits(gb, 2) + 1; + } + } + sign = !get_bits1(gb); + ptr[offset & coef_mask] = sign ? level : -level; + ptr[offset & coef_mask] <<= shift; + } + } + /** NOTE: EOB can be omitted */ + if (offset > num_coefs) { + av_log(avctx, AV_LOG_ERROR, "overflow in spectral RLE, ignoring\n"); + return -1; + } + + return 0; +} -- cgit v1.2.3