diff options
author | Alex Converse <alex.converse@gmail.com> | 2009-07-08 20:01:31 +0000 |
---|---|---|
committer | Alex Converse <alex.converse@gmail.com> | 2009-07-08 20:01:31 +0000 |
commit | 78e65cd7726942a1615ead039abe0bfa79341212 (patch) | |
tree | 7003e32f0234d3fb6d7959e9f193e2ec733df5c6 /libavcodec/psymodel.c | |
parent | 5e039e1b4c0fe25c76faa7ea107db60264edb757 (diff) | |
download | ffmpeg-78e65cd7726942a1615ead039abe0bfa79341212.tar.gz |
Merge the AAC encoder from SoC svn. It is still considered experimental.
Originally committed as revision 19375 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/psymodel.c')
-rw-r--r-- | libavcodec/psymodel.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/libavcodec/psymodel.c b/libavcodec/psymodel.c new file mode 100644 index 0000000000..623254e531 --- /dev/null +++ b/libavcodec/psymodel.c @@ -0,0 +1,130 @@ +/* + * audio encoder psychoacoustic model + * Copyright (C) 2008 Konstantin Shishkov + * + * 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 "avcodec.h" +#include "psymodel.h" +#include "iirfilter.h" + +extern const FFPsyModel ff_aac_psy_model; + +av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, + int num_lens, + const uint8_t **bands, const int* num_bands) +{ + ctx->avctx = avctx; + ctx->psy_bands = av_mallocz(sizeof(FFPsyBand) * PSY_MAX_BANDS * avctx->channels); + ctx->bands = av_malloc (sizeof(ctx->bands[0]) * num_lens); + ctx->num_bands = av_malloc (sizeof(ctx->num_bands[0]) * num_lens); + memcpy(ctx->bands, bands, sizeof(ctx->bands[0]) * num_lens); + memcpy(ctx->num_bands, num_bands, sizeof(ctx->num_bands[0]) * num_lens); + switch(ctx->avctx->codec_id){ + case CODEC_ID_AAC: + ctx->model = &ff_aac_psy_model; + break; + } + if(ctx->model->init) + return ctx->model->init(ctx); + return 0; +} + +FFPsyWindowInfo ff_psy_suggest_window(FFPsyContext *ctx, + const int16_t *audio, const int16_t *la, + int channel, int prev_type) +{ + return ctx->model->window(ctx, audio, la, channel, prev_type); +} + +void ff_psy_set_band_info(FFPsyContext *ctx, int channel, + const float *coeffs, FFPsyWindowInfo *wi) +{ + ctx->model->analyze(ctx, channel, coeffs, wi); +} + +av_cold void ff_psy_end(FFPsyContext *ctx) +{ + if(ctx->model->end) + ctx->model->end(ctx); + av_freep(&ctx->bands); + av_freep(&ctx->num_bands); + av_freep(&ctx->psy_bands); +} + +typedef struct FFPsyPreprocessContext{ + AVCodecContext *avctx; + float stereo_att; + struct FFIIRFilterCoeffs *fcoeffs; + struct FFIIRFilterState **fstate; +}FFPsyPreprocessContext; + +#define FILT_ORDER 4 + +av_cold struct FFPsyPreprocessContext* ff_psy_preprocess_init(AVCodecContext *avctx) +{ + FFPsyPreprocessContext *ctx; + int i; + float cutoff_coeff; + ctx = av_mallocz(sizeof(FFPsyPreprocessContext)); + ctx->avctx = avctx; + + if(avctx->flags & CODEC_FLAG_QSCALE) + cutoff_coeff = 1.0f / av_clip(1 + avctx->global_quality / FF_QUALITY_SCALE, 1, 8); + else + cutoff_coeff = avctx->bit_rate / (4.0f * avctx->sample_rate * avctx->channels); + + ctx->fcoeffs = ff_iir_filter_init_coeffs(FF_FILTER_TYPE_BUTTERWORTH, FF_FILTER_MODE_LOWPASS, + FILT_ORDER, cutoff_coeff, 0.0, 0.0); + if(ctx->fcoeffs){ + ctx->fstate = av_mallocz(sizeof(ctx->fstate[0]) * avctx->channels); + for(i = 0; i < avctx->channels; i++) + ctx->fstate[i] = ff_iir_filter_init_state(FILT_ORDER); + } + return ctx; +} + +void ff_psy_preprocess(struct FFPsyPreprocessContext *ctx, + const int16_t *audio, int16_t *dest, + int tag, int channels) +{ + int ch, i; + if(ctx->fstate){ + for(ch = 0; ch < channels; ch++){ + ff_iir_filter(ctx->fcoeffs, ctx->fstate[tag+ch], ctx->avctx->frame_size, + audio + ch, ctx->avctx->channels, + dest + ch, ctx->avctx->channels); + } + }else{ + for(ch = 0; ch < channels; ch++){ + for(i = 0; i < ctx->avctx->frame_size; i++) + dest[i*ctx->avctx->channels + ch] = audio[i*ctx->avctx->channels + ch]; + } + } +} + +av_cold void ff_psy_preprocess_end(struct FFPsyPreprocessContext *ctx) +{ + int i; + ff_iir_filter_free_coeffs(ctx->fcoeffs); + if (ctx->fstate) + for (i = 0; i < ctx->avctx->channels; i++) + ff_iir_filter_free_state(ctx->fstate[i]); + av_freep(&ctx->fstate); +} + |