* TwinVQ decoder
* Copyright (c) 2009 Vitor Sessak
*
- * This file is part of FFmpeg.
+ * This file is part of Libav.
*
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav 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,
+ * Libav 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
+ * License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/channel_layout.h"
+#include "libavutil/float_dsp.h"
#include "avcodec.h"
#include "get_bits.h"
-#include "dsputil.h"
+#include "fft.h"
+#include "internal.h"
+#include "lsp.h"
+#include "sinewin.h"
#include <math.h>
#include <stdint.h>
typedef struct TwinContext {
AVCodecContext *avctx;
- DSPContext dsp;
- MDCTContext mdct_ctx[3];
+ AVFloatDSPContext fdsp;
+ FFTContext mdct_ctx[3];
const ModeTab *mtab;
float *curr_frame; ///< non-interleaved output
float *prev_frame; ///< non-interleaved previous frame
int last_block_pos[2];
+ int discarded_packets;
float *cos_tabs[3];
} TwinContext;
#define PPC_SHAPE_CB_SIZE 64
+#define PPC_SHAPE_LEN_MAX 60
#define SUB_AMP_MAX 4500.0
#define MULAW_MU 100.0
#define GAIN_BITS 8
#define SUB_GAIN_BITS 5
#define WINDOW_TYPE_BITS 4
#define PGAIN_MU 200
+#define LSP_COEFS_MAX 20
+#define LSP_SPLIT_MAX 4
+#define CHANNELS_MAX 2
+#define SUBBLOCKS_MAX 16
+#define BARK_N_COEF_MAX 4
/** @note not speed critical, hence not optimized */
static void memset_float(float *buf, float val, int size)
* be a multiple of four.
* @return the LPC value
*
- * @todo reuse code from vorbis_dec.c: vorbis_floor0_decode
+ * @todo reuse code from Vorbis decoder: vorbis_floor0_decode
*/
static float eval_lpc_spectrum(const float *lsp, float cos_val, int order)
{
float q = 0.5f;
float two_cos_w = 2.0f*cos_val;
- for (j=0; j + 1 < order; j += 2*2) {
+ for (j = 0; j + 1 < order; j += 2*2) {
// Unroll the loop once since order is a multiple of four
q *= lsp[j ] - two_cos_w;
p *= lsp[j+1] - two_cos_w;
}
/**
- * Evaluates the LPC amplitude spectrum envelope from the line spectrum pairs.
+ * Evaluate the LPC amplitude spectrum envelope from the line spectrum pairs.
*/
static void eval_lpcenv(TwinContext *tctx, const float *cos_vals, float *lpc)
{
const ModeTab *mtab = tctx->mtab;
int size_s = mtab->size / mtab->fmode[FT_SHORT].sub;
- for (i=0; i < size_s/2; i++) {
+ for (i = 0; i < size_s/2; i++) {
float cos_i = tctx->cos_tabs[0][i];
lpc[i] = eval_lpc_spectrum(cos_vals, cos_i, mtab->n_lsp);
lpc[size_s-i-1] = eval_lpc_spectrum(cos_vals, -cos_i, mtab->n_lsp);
int i;
float step = (v1 - v2)/(size + 1);
- for (i=0; i < size; i++) {
+ for (i = 0; i < size; i++) {
v2 += step;
out[i] = v2;
}
}
/**
- * Evaluates the LPC amplitude spectrum envelope from the line spectrum pairs.
+ * Evaluate the LPC amplitude spectrum envelope from the line spectrum pairs.
* Probably for speed reasons, the coefficients are evaluated as
* siiiibiiiisiiiibiiiisiiiibiiiisiiiibiiiis ...
* where s is an evaluated value, i is a value interpolated from the others
const float *cos_tab = tctx->cos_tabs[ftype];
// Fill the 's'
- for (i=0; i < size; i += step)
+ for (i = 0; i < size; i += step)
out[i] =
eval_lpc_spectrum(in,
get_cos(i, part, cos_tab, size),
mtab->n_lsp);
// Fill the 'iiiibiiii'
- for (i=step; i <= size - 2*step; i += step) {
+ for (i = step; i <= size - 2*step; i += step) {
if (out[i + step] + out[i - step] > 1.95*out[i] ||
out[i + step] >= out[i - step]) {
interpolate(out + i - step + 1, out[i], out[i-step], step - 1);
int pos = 0;
int i, j;
- for (i=0; i < tctx->n_div[ftype]; i++) {
+ for (i = 0; i < tctx->n_div[ftype]; i++) {
int tmp0, tmp1;
int sign0 = 1;
int sign1 = 1;
tab0 = cb0 + tmp0*cb_len;
tab1 = cb1 + tmp1*cb_len;
- for (j=0; j < length; j++)
+ for (j = 0; j < length; j++)
out[tctx->permut[ftype][pos+j]] = sign0*tab0[j] + sign1*tab1[j];
pos += length;
* a*b == 200 and the nearest integer is ill-defined, use a table to emulate
* the following broken float-based implementation used by the binary decoder:
*
- * \code
+ * @code
* static int very_broken_op(int a, int b)
* {
* static float test; // Ugh, force gcc to do the division first...
* test = a/400.;
* return b * test + 0.5;
* }
- * \endcode
+ * @endcode
*
* @note if this function is replaced by just ROUNDED_DIV(a*b,400.), the stddev
* between the original file (before encoding with Yamaha encoder) and the
int center;
// First peak centered around zero
- for (i=0; i < width/2; i++)
+ for (i = 0; i < width/2; i++)
speech[i] += ppc_gain * *shape++;
- for (i=1; i < ROUNDED_DIV(len,width) ; i++) {
+ for (i = 1; i < ROUNDED_DIV(len,width) ; i++) {
center = very_broken_op(period, i);
- for (j=-width/2; j < (width+1)/2; j++)
+ for (j = -width/2; j < (width+1)/2; j++)
speech[j+center] += ppc_gain * *shape++;
}
// For the last block, be careful not to go beyond the end of the buffer
center = very_broken_op(period, i);
- for (j=-width/2; j < (width + 1)/2 && shape < shape_end; j++)
+ for (j = -width/2; j < (width + 1)/2 && shape < shape_end; j++)
speech[j+center] += ppc_gain * *shape++;
}
float sub_step = SUB_AMP_MAX / ((1 << SUB_GAIN_BITS) - 1);
if (ftype == FT_LONG) {
- for (i=0; i < tctx->avctx->channels; i++)
+ for (i = 0; i < tctx->avctx->channels; i++)
out[i] = (1./(1<<13)) *
mulawinv(step * 0.5 + step * get_bits(gb, GAIN_BITS),
AMP_MAX, MULAW_MU);
} else {
- for (i=0; i < tctx->avctx->channels; i++) {
+ for (i = 0; i < tctx->avctx->channels; i++) {
float val = (1./(1<<23)) *
mulawinv(step * 0.5 + step * get_bits(gb, GAIN_BITS),
AMP_MAX, MULAW_MU);
- for (j=0; j < sub; j++) {
+ for (j = 0; j < sub; j++) {
out[i*sub + j] =
val*mulawinv(sub_step* 0.5 +
sub_step* get_bits(gb, SUB_GAIN_BITS),
{
int i;
float min_dist2 = min_dist * 0.5;
- for (i=1; i < order; i++)
+ for (i = 1; i < order; i++)
if (lsp[i] - lsp[i-1] < min_dist) {
float avg = (lsp[i] + lsp[i-1]) * 0.5;
}
}
-static void bubblesort(float *lsp, int lp_order)
-{
- int i,j;
-
- /* sort lsp in ascending order. float bubble agorithm,
- O(n) if data already sorted, O(n^2) - otherwise */
- for (i=0; i < lp_order - 1; i++)
- for (j=i; j >= 0 && lsp[j] > lsp[j+1]; j--)
- FFSWAP(float, lsp[j], lsp[j+1]);
-}
-
static void decode_lsp(TwinContext *tctx, int lpc_idx1, uint8_t *lpc_idx2,
int lpc_hist_idx, float *lsp, float *hist)
{
0
};
- j=0;
- for (i=0; i < mtab->lsp_split; i++) {
+ j = 0;
+ for (i = 0; i < mtab->lsp_split; i++) {
int chunk_end = ((i + 1)*mtab->n_lsp + funny_rounding[i])/mtab->lsp_split;
for (; j < chunk_end; j++)
lsp[j] = cb [lpc_idx1 * mtab->n_lsp + j] +
rearrange_lsp(mtab->n_lsp, lsp, 0.0001);
- for (i=0; i < mtab->n_lsp; i++) {
+ for (i = 0; i < mtab->n_lsp; i++) {
float tmp1 = 1. - cb3[lpc_hist_idx*mtab->n_lsp + i];
float tmp2 = hist[i] * cb3[lpc_hist_idx*mtab->n_lsp + i];
hist[i] = lsp[i];
rearrange_lsp(mtab->n_lsp, lsp, 0.0001);
rearrange_lsp(mtab->n_lsp, lsp, 0.000095);
- bubblesort(lsp, mtab->n_lsp);
+ ff_sort_nearly_sorted_floats(lsp, mtab->n_lsp);
}
static void dec_lpc_spectrum_inv(TwinContext *tctx, float *lsp,
int i;
int size = tctx->mtab->size / tctx->mtab->fmode[ftype].sub;
- for (i=0; i < tctx->mtab->n_lsp; i++)
+ for (i = 0; i < tctx->mtab->n_lsp; i++)
lsp[i] = 2*cos(lsp[i]);
switch (ftype) {
static void imdct_and_window(TwinContext *tctx, enum FrameType ftype, int wtype,
float *in, float *prev, int ch)
{
+ FFTContext *mdct = &tctx->mdct_ctx[ftype];
const ModeTab *mtab = tctx->mtab;
int bsize = mtab->size / mtab->fmode[ftype].sub;
int size = mtab->size;
first_wsize = wsize;
prev_buf = prev + (size - bsize)/2;
- for (j=0; j < mtab->fmode[ftype].sub; j++) {
+ for (j = 0; j < mtab->fmode[ftype].sub; j++) {
int sub_wtype = ftype == FT_MEDIUM ? 8 : wtype;
if (!j && wtype == 4)
wsize = types_sizes[wtype_to_wsize[sub_wtype]];
- ff_imdct_half(&tctx->mdct_ctx[ftype], buf1 + bsize*j, in + bsize*j);
+ mdct->imdct_half(mdct, buf1 + bsize*j, in + bsize*j);
- tctx->dsp.vector_fmul_window(out2,
- prev_buf + (bsize-wsize)/2,
- buf1 + bsize*j,
- ff_sine_windows[av_log2(wsize) - 7],
- 0.0,
- wsize/2);
+ tctx->fdsp.vector_fmul_window(out2, prev_buf + (bsize-wsize) / 2,
+ buf1 + bsize * j,
+ ff_sine_windows[av_log2(wsize)],
+ wsize / 2);
out2 += wsize;
memcpy(out2, buf1 + bsize*j + wsize/2, (bsize - wsize/2)*sizeof(float));
}
static void imdct_output(TwinContext *tctx, enum FrameType ftype, int wtype,
- float *out)
+ float **out)
{
const ModeTab *mtab = tctx->mtab;
+ int size1, size2;
float *prev_buf = tctx->prev_frame + tctx->last_block_pos[0];
- int i, j;
+ int i;
- for (i=0; i < tctx->avctx->channels; i++) {
+ for (i = 0; i < tctx->avctx->channels; i++) {
imdct_and_window(tctx, ftype, wtype,
tctx->spectrum + i*mtab->size,
prev_buf + 2*i*mtab->size,
i);
}
- if (tctx->avctx->channels == 2) {
- for (i=0; i < mtab->size - tctx->last_block_pos[0]; i++) {
- float f1 = prev_buf[ i];
- float f2 = prev_buf[2*mtab->size + i];
- out[2*i ] = f1 + f2;
- out[2*i + 1] = f1 - f2;
- }
- for (j=0; i < mtab->size; j++,i++) {
- float f1 = tctx->curr_frame[ j];
- float f2 = tctx->curr_frame[2*mtab->size + j];
- out[2*i ] = f1 + f2;
- out[2*i + 1] = f1 - f2;
- }
- } else {
- memcpy(out, prev_buf,
- (mtab->size - tctx->last_block_pos[0]) * sizeof(*out));
+ if (!out)
+ return;
- out += mtab->size - tctx->last_block_pos[0];
+ size2 = tctx->last_block_pos[0];
+ size1 = mtab->size - size2;
- memcpy(out, tctx->curr_frame,
- (tctx->last_block_pos[0]) * sizeof(*out));
- }
+ memcpy(&out[0][0 ], prev_buf, size1 * sizeof(out[0][0]));
+ memcpy(&out[0][size1], tctx->curr_frame, size2 * sizeof(out[0][0]));
+ if (tctx->avctx->channels == 2) {
+ memcpy(&out[1][0], &prev_buf[2*mtab->size], size1 * sizeof(out[1][0]));
+ memcpy(&out[1][size1], &tctx->curr_frame[2*mtab->size], size2 * sizeof(out[1][0]));
+ tctx->fdsp.butterflies_float(out[0], out[1], mtab->size);
+ }
}
static void dec_bark_env(TwinContext *tctx, const uint8_t *in, int use_hist,
int fw_cb_len = mtab->fmode[ftype].bark_env_size / bark_n_coef;
int idx = 0;
- for (i=0; i < fw_cb_len; i++)
- for (j=0; j < bark_n_coef; j++, idx++) {
+ for (i = 0; i < fw_cb_len; i++)
+ for (j = 0; j < bark_n_coef; j++, idx++) {
float tmp2 =
mtab->fmode[ftype].bark_cb[fw_cb_len*in[j] + i] * (1./4096);
float st = use_hist ?
int channels = tctx->avctx->channels;
int sub = mtab->fmode[ftype].sub;
int block_size = mtab->size / sub;
- float gain[channels*sub];
- float ppc_shape[mtab->ppc_shape_len * channels * 4];
- uint8_t bark1[channels][sub][mtab->fmode[ftype].bark_n_coef];
- uint8_t bark_use_hist[channels][sub];
+ float gain[CHANNELS_MAX*SUBBLOCKS_MAX];
+ float ppc_shape[PPC_SHAPE_LEN_MAX * CHANNELS_MAX * 4];
+ uint8_t bark1[CHANNELS_MAX][SUBBLOCKS_MAX][BARK_N_COEF_MAX];
+ uint8_t bark_use_hist[CHANNELS_MAX][SUBBLOCKS_MAX];
- uint8_t lpc_idx1[channels];
- uint8_t lpc_idx2[channels][tctx->mtab->lsp_split];
- uint8_t lpc_hist_idx[channels];
+ uint8_t lpc_idx1[CHANNELS_MAX];
+ uint8_t lpc_idx2[CHANNELS_MAX][LSP_SPLIT_MAX];
+ uint8_t lpc_hist_idx[CHANNELS_MAX];
int i, j, k;
mtab->fmode[ftype].cb0, mtab->fmode[ftype].cb1,
mtab->fmode[ftype].cb_len_read);
- for (i=0; i < channels; i++)
- for (j=0; j < sub; j++)
- for (k=0; k < mtab->fmode[ftype].bark_n_coef; k++)
+ for (i = 0; i < channels; i++)
+ for (j = 0; j < sub; j++)
+ for (k = 0; k < mtab->fmode[ftype].bark_n_coef; k++)
bark1[i][j][k] =
get_bits(gb, mtab->fmode[ftype].bark_n_bit);
- for (i=0; i < channels; i++)
- for (j=0; j < sub; j++)
+ for (i = 0; i < channels; i++)
+ for (j = 0; j < sub; j++)
bark_use_hist[i][j] = get_bits1(gb);
dec_gain(tctx, gb, ftype, gain);
- for (i=0; i < channels; i++) {
+ for (i = 0; i < channels; i++) {
lpc_hist_idx[i] = get_bits(gb, tctx->mtab->lsp_bit0);
lpc_idx1 [i] = get_bits(gb, tctx->mtab->lsp_bit1);
- for (j=0; j < tctx->mtab->lsp_split; j++)
+ for (j = 0; j < tctx->mtab->lsp_split; j++)
lpc_idx2[i][j] = get_bits(gb, tctx->mtab->lsp_bit2);
}
mtab->ppc_shape_cb + cb_len_p*PPC_SHAPE_CB_SIZE, cb_len_p);
}
- for (i=0; i < channels; i++) {
+ for (i = 0; i < channels; i++) {
float *chunk = out + mtab->size * i;
- float lsp[tctx->mtab->n_lsp];
+ float lsp[LSP_COEFS_MAX];
- for (j=0; j < sub; j++) {
+ for (j = 0; j < sub; j++) {
dec_bark_env(tctx, bark1[i][j], bark_use_hist[i][j], i,
tctx->tmp_buf, gain[sub*i+j], ftype);
- tctx->dsp.vector_fmul(chunk + block_size*j, tctx->tmp_buf,
- block_size);
+ tctx->fdsp.vector_fmul(chunk + block_size*j, chunk + block_size*j,
+ tctx->tmp_buf, block_size);
}
dec_lpc_spectrum_inv(tctx, lsp, ftype, tctx->tmp_buf);
- for (j=0; j < mtab->fmode[ftype].sub; j++) {
- tctx->dsp.vector_fmul(chunk, tctx->tmp_buf, block_size);
+ for (j = 0; j < mtab->fmode[ftype].sub; j++) {
+ tctx->fdsp.vector_fmul(chunk, chunk, tctx->tmp_buf, block_size);
chunk += block_size;
}
}
}
static int twin_decode_frame(AVCodecContext * avctx, void *data,
- int *data_size, AVPacket *avpkt)
+ int *got_frame_ptr, AVPacket *avpkt)
{
+ AVFrame *frame = data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
TwinContext *tctx = avctx->priv_data;
GetBitContext gb;
const ModeTab *mtab = tctx->mtab;
- float *out = data;
+ float **out = NULL;
enum FrameType ftype;
- int window_type;
+ int window_type, ret;
static const enum FrameType wtype_to_ftype_table[] = {
FT_LONG, FT_LONG, FT_SHORT, FT_LONG,
FT_MEDIUM, FT_LONG, FT_LONG, FT_MEDIUM, FT_MEDIUM
if (buf_size*8 < avctx->bit_rate*mtab->size/avctx->sample_rate + 8) {
av_log(avctx, AV_LOG_ERROR,
"Frame too small (%d bytes). Truncated file?\n", buf_size);
- *data_size = 0;
- return buf_size;
+ return AVERROR(EINVAL);
+ }
+
+ /* get output buffer */
+ if (tctx->discarded_packets >= 2) {
+ frame->nb_samples = mtab->size;
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return ret;
+ }
+ out = (float **)frame->extended_data;
}
init_get_bits(&gb, buf, buf_size * 8);
FFSWAP(float*, tctx->curr_frame, tctx->prev_frame);
- if (tctx->avctx->frame_number < 2) {
- *data_size=0;
+ if (tctx->discarded_packets < 2) {
+ tctx->discarded_packets++;
+ *got_frame_ptr = 0;
return buf_size;
}
- tctx->dsp.vector_clipf(out, out, -32700./(1<<15), 32700./(1<<15),
- mtab->size);
-
- *data_size = mtab->size*avctx->channels*4;
+ *got_frame_ptr = 1;
return buf_size;
}
/**
* Init IMDCT and windowing tables
*/
-static av_cold void init_mdct_win(TwinContext *tctx)
+static av_cold int init_mdct_win(TwinContext *tctx)
{
- int i,j;
+ int i, j, ret;
const ModeTab *mtab = tctx->mtab;
int size_s = mtab->size / mtab->fmode[FT_SHORT].sub;
int size_m = mtab->size / mtab->fmode[FT_MEDIUM].sub;
int channels = tctx->avctx->channels;
float norm = channels == 1 ? 2. : 1.;
- for (i=0; i < 3; i++) {
+ for (i = 0; i < 3; i++) {
int bsize = tctx->mtab->size/tctx->mtab->fmode[i].sub;
- ff_mdct_init(&tctx->mdct_ctx[i], av_log2(bsize) + 1, 1,
- -sqrt(norm/bsize) / (1<<15));
+ if ((ret = ff_mdct_init(&tctx->mdct_ctx[i], av_log2(bsize) + 1, 1,
+ -sqrt(norm/bsize) / (1<<15))))
+ return ret;
}
- tctx->tmp_buf = av_malloc(mtab->size * sizeof(*tctx->tmp_buf));
+ FF_ALLOC_OR_GOTO(tctx->avctx, tctx->tmp_buf,
+ mtab->size * sizeof(*tctx->tmp_buf), alloc_fail);
- tctx->spectrum = av_malloc(2*mtab->size*channels*sizeof(float));
- tctx->curr_frame = av_malloc(2*mtab->size*channels*sizeof(float));
- tctx->prev_frame = av_malloc(2*mtab->size*channels*sizeof(float));
+ FF_ALLOC_OR_GOTO(tctx->avctx, tctx->spectrum,
+ 2 * mtab->size * channels * sizeof(*tctx->spectrum),
+ alloc_fail);
+ FF_ALLOC_OR_GOTO(tctx->avctx, tctx->curr_frame,
+ 2 * mtab->size * channels * sizeof(*tctx->curr_frame),
+ alloc_fail);
+ FF_ALLOC_OR_GOTO(tctx->avctx, tctx->prev_frame,
+ 2 * mtab->size * channels * sizeof(*tctx->prev_frame),
+ alloc_fail);
- for(i=0; i < 3; i++) {
+ for (i = 0; i < 3; i++) {
int m = 4*mtab->size/mtab->fmode[i].sub;
double freq = 2*M_PI/m;
- tctx->cos_tabs[i] = av_malloc((m/4)*sizeof(*tctx->cos_tabs));
+ FF_ALLOC_OR_GOTO(tctx->avctx, tctx->cos_tabs[i],
+ (m / 4) * sizeof(*tctx->cos_tabs[i]), alloc_fail);
- for (j=0; j <= m/8; j++)
+ for (j = 0; j <= m/8; j++)
tctx->cos_tabs[i][j] = cos((2*j + 1)*freq);
- for (j=1; j < m/8; j++)
+ for (j = 1; j < m/8; j++)
tctx->cos_tabs[i][m/4-j] = tctx->cos_tabs[i][j];
}
- ff_sine_window_init(ff_sine_windows[av_log2(size_m) - 7], size_m );
- ff_sine_window_init(ff_sine_windows[av_log2(size_s/2) - 7], size_s/2);
- ff_sine_window_init(ff_sine_windows[av_log2(mtab->size) - 7], mtab->size);
+ ff_init_ff_sine_windows(av_log2(size_m));
+ ff_init_ff_sine_windows(av_log2(size_s/2));
+ ff_init_ff_sine_windows(av_log2(mtab->size));
+
+ return 0;
+alloc_fail:
+ return AVERROR(ENOMEM);
}
/**
{
int i,j;
- for (i=0; i < line_len[0]; i++) {
+ for (i = 0; i < line_len[0]; i++) {
int shift;
if (num_blocks == 1 ||
} else
shift = i*i;
- for (j=0; j < num_vect && (j+num_vect*i < block_size*num_blocks); j++)
+ for (j = 0; j < num_vect && (j+num_vect*i < block_size*num_blocks); j++)
tab[i*num_vect+j] = i*num_vect + (j + shift) % num_vect;
}
}
/**
* Interpret the input data as in the following table:
*
- * \verbatim
+ * @verbatim
*
* abcdefgh
* ijklmnop
* qrstuvw
* x123456
*
- * \endverbatim
+ * @endverbatim
*
* and transpose it, giving the output
* aiqxbjr1cks2dlt3emu4fvn5gow6hp
{
int i,j;
int cont= 0;
- for (i=0; i < num_vect; i++)
- for (j=0; j < line_len[i >= length_div]; j++)
+ for (i = 0; i < num_vect; i++)
+ for (j = 0; j < line_len[i >= length_div]; j++)
out[cont++] = in[j*num_vect + i];
}
int block_size = size/n_blocks;
int i;
- for (i=0; i < size; i++)
+ for (i = 0; i < size; i++)
out[i] = block_size * (in[i] % n_blocks) + in[i] / n_blocks;
}
{
int block_size;
const ModeTab *mtab = tctx->mtab;
- int size = tctx->avctx->channels*mtab->fmode[ftype].sub;
+ int size;
int16_t *tmp_perm = (int16_t *) tctx->tmp_buf;
if (ftype == FT_PPC) {
size = tctx->avctx->channels;
block_size = mtab->ppc_shape_len;
- } else
+ } else {
+ size = tctx->avctx->channels * mtab->fmode[ftype].sub;
block_size = mtab->size / mtab->fmode[ftype].sub;
+ }
permutate_in_line(tmp_perm, tctx->n_div[ftype], size,
block_size, tctx->length[ftype],
int bsize_no_main_cb[3];
int bse_bits[3];
int i;
+ enum FrameType frametype;
- for (i=0; i < 3; i++)
+ for (i = 0; i < 3; i++)
// +1 for history usage switch
bse_bits[i] = n_ch *
(mtab->fmode[i].bark_n_coef * mtab->fmode[i].bark_n_bit + 1);
bsize_no_main_cb[2] = bse_bits[2] + lsp_bits_per_block + ppc_bits +
WINDOW_TYPE_BITS + n_ch*GAIN_BITS;
- for (i=0; i < 2; i++)
+ for (i = 0; i < 2; i++)
bsize_no_main_cb[i] =
lsp_bits_per_block + n_ch*GAIN_BITS + WINDOW_TYPE_BITS +
mtab->fmode[i].sub*(bse_bits[i] + n_ch*SUB_GAIN_BITS);
// The remaining bits are all used for the main spectrum coefficients
- for (i=0; i < 4; i++) {
+ for (i = 0; i < 4; i++) {
int bit_size;
int vect_size;
int rounded_up, rounded_down, num_rounded_down, num_rounded_up;
tctx->length_change[i] = num_rounded_up;
}
- for (i=0; i < 4; i++)
- construct_perm_table(tctx, i);
+ for (frametype = FT_SHORT; frametype <= FT_PPC; frametype++)
+ construct_perm_table(tctx, frametype);
+}
+
+static av_cold int twin_decode_close(AVCodecContext *avctx)
+{
+ TwinContext *tctx = avctx->priv_data;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ ff_mdct_end(&tctx->mdct_ctx[i]);
+ av_free(tctx->cos_tabs[i]);
+ }
+
+
+ av_free(tctx->curr_frame);
+ av_free(tctx->spectrum);
+ av_free(tctx->prev_frame);
+ av_free(tctx->tmp_buf);
+
+ return 0;
}
static av_cold int twin_decode_init(AVCodecContext *avctx)
{
+ int ret;
TwinContext *tctx = avctx->priv_data;
- int isampf = avctx->sample_rate/1000;
- int ibps = avctx->bit_rate/(1000 * avctx->channels);
+ int isampf, ibps;
tctx->avctx = avctx;
- avctx->sample_fmt = SAMPLE_FMT_FLT;
+ avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
- if (avctx->channels > 2) {
+ if (!avctx->extradata || avctx->extradata_size < 12) {
+ av_log(avctx, AV_LOG_ERROR, "Missing or incomplete extradata\n");
+ return AVERROR_INVALIDDATA;
+ }
+ avctx->channels = AV_RB32(avctx->extradata ) + 1;
+ avctx->bit_rate = AV_RB32(avctx->extradata + 4) * 1000;
+ isampf = AV_RB32(avctx->extradata + 8);
+
+ if (isampf < 8 || isampf > 44) {
+ av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate\n");
+ return AVERROR_INVALIDDATA;
+ }
+ switch (isampf) {
+ case 44: avctx->sample_rate = 44100; break;
+ case 22: avctx->sample_rate = 22050; break;
+ case 11: avctx->sample_rate = 11025; break;
+ default: avctx->sample_rate = isampf * 1000; break;
+ }
+
+ if (avctx->channels <= 0 || avctx->channels > CHANNELS_MAX) {
av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %i\n",
avctx->channels);
return -1;
}
+ avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO :
+ AV_CH_LAYOUT_STEREO;
+
+ ibps = avctx->bit_rate / (1000 * avctx->channels);
switch ((isampf << 8) + ibps) {
case (8 <<8) + 8: tctx->mtab = &mode_08_08; break;
return -1;
}
- dsputil_init(&tctx->dsp, avctx);
- init_mdct_win(tctx);
+ avpriv_float_dsp_init(&tctx->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+ if ((ret = init_mdct_win(tctx))) {
+ av_log(avctx, AV_LOG_ERROR, "Error initializing MDCT\n");
+ twin_decode_close(avctx);
+ return ret;
+ }
init_bitstream_params(tctx);
memset_float(tctx->bark_hist[0][0], 0.1, FF_ARRAY_ELEMS(tctx->bark_hist));
return 0;
}
-static av_cold int twin_decode_close(AVCodecContext *avctx)
-{
- TwinContext *tctx = avctx->priv_data;
- int i;
-
- for (i=0; i < 3; i++) {
- ff_mdct_end(&tctx->mdct_ctx[i]);
- av_free(tctx->cos_tabs[i]);
- }
-
-
- av_free(tctx->curr_frame);
- av_free(tctx->spectrum);
- av_free(tctx->prev_frame);
- av_free(tctx->tmp_buf);
-
- return 0;
-}
-
-AVCodec twinvq_decoder =
-{
- "twinvq",
- CODEC_TYPE_AUDIO,
- CODEC_ID_TWINVQ,
- sizeof(TwinContext),
- twin_decode_init,
- NULL,
- twin_decode_close,
- twin_decode_frame,
- .long_name = NULL_IF_CONFIG_SMALL("VQF TwinVQ"),
+AVCodec ff_twinvq_decoder = {
+ .name = "twinvq",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .id = AV_CODEC_ID_TWINVQ,
+ .priv_data_size = sizeof(TwinContext),
+ .init = twin_decode_init,
+ .close = twin_decode_close,
+ .decode = twin_decode_frame,
+ .capabilities = CODEC_CAP_DR1,
+ .long_name = NULL_IF_CONFIG_SMALL("VQF TwinVQ"),
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
+ AV_SAMPLE_FMT_NONE },
};