* 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 "avcodec.h"
#include "get_bits.h"
#include "dsputil.h"
+#include "fft.h"
+#include "lsp.h"
+#include "sinewin.h"
#include <math.h>
#include <stdint.h>
typedef struct TwinContext {
AVCodecContext *avctx;
DSPContext dsp;
- MDCTContext mdct_ctx[3];
+ FFTContext mdct_ctx[3];
const ModeTab *mtab;
} 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)
{
}
/**
- * 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)
{
}
/**
- * 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
* 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
}
}
-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)
{
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,
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;
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,
+ ff_sine_windows[av_log2(wsize)],
wsize/2);
out2 += wsize;
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;
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++) {
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,
+ tctx->dsp.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);
+ tctx->dsp.vector_fmul(chunk, chunk, tctx->tmp_buf, block_size);
chunk += block_size;
}
}
const ModeTab *mtab = tctx->mtab;
float *out = data;
enum FrameType ftype;
- int window_type;
+ int window_type, out_size;
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);
+ }
+
+ out_size = mtab->size * avctx->channels *
+ av_get_bytes_per_sample(avctx->sample_fmt);
+ if (*data_size < out_size) {
+ av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n");
+ return AVERROR(EINVAL);
}
init_get_bits(&gb, buf, buf_size * 8);
return buf_size;
}
- tctx->dsp.vector_clipf(out, out, -32700./(1<<15), 32700./(1<<15),
- avctx->channels * mtab->size);
-
- *data_size = mtab->size*avctx->channels*4;
+ *data_size = out_size;
return buf_size;
}
}
- 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));
}
/**
/**
* 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 bsize_no_main_cb[3];
int bse_bits[3];
int i;
+ enum FrameType frametype;
for (i = 0; i < 3; i++)
// +1 for history usage switch
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_init(AVCodecContext *avctx)
int ibps = avctx->bit_rate/(1000 * avctx->channels);
tctx->avctx = avctx;
- avctx->sample_fmt = SAMPLE_FMT_FLT;
+ avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
- if (avctx->channels > 2) {
+ if (avctx->channels > CHANNELS_MAX) {
av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %i\n",
avctx->channels);
return -1;
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 = CODEC_ID_TWINVQ,
+ .priv_data_size = sizeof(TwinContext),
+ .init = twin_decode_init,
+ .close = twin_decode_close,
+ .decode = twin_decode_frame,
+ .long_name = NULL_IF_CONFIG_SMALL("VQF TwinVQ"),
};