* Copyright (c) 2006 Benjamin Larsson
* Copyright (c) 2006 Konstantin Shishkov
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * 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.
*
- * Libav is distributed in the hope that it will be useful,
+ * 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 Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
typedef struct {
AVFrame frame;
- IMCChannel chctx[1];
+ IMCChannel chctx[2];
/** MDCT tables */
//@{
FFTContext fft;
DECLARE_ALIGNED(32, FFTComplex, samples)[COEFFS / 2];
float *out_samples;
+
+ int8_t cyclTab[32], cyclTab2[32];
+ float weights1[31], weights2[31];
} IMCContext;
static VLC huffman_vlc[4][4];
static VLC_TYPE vlc_tables[VLC_TABLES_SIZE][2];
+static inline double freq2bark(double freq)
+{
+ return 3.5 * atan((freq / 7500.0) * (freq / 7500.0)) + 13.0 * atan(freq * 0.00076);
+}
+
+static av_cold void iac_generate_tabs(IMCContext *q, int sampling_rate)
+{
+ double freqmin[32], freqmid[32], freqmax[32];
+ double scale = sampling_rate / (256.0 * 2.0 * 2.0);
+ double nyquist_freq = sampling_rate * 0.5;
+ double freq, bark, prev_bark = 0, tf, tb;
+ int i, j;
+
+ for (i = 0; i < 32; i++) {
+ freq = (band_tab[i] + band_tab[i + 1] - 1) * scale;
+ bark = freq2bark(freq);
+
+ if (i > 0) {
+ tb = bark - prev_bark;
+ q->weights1[i - 1] = pow(10.0, -1.0 * tb);
+ q->weights2[i - 1] = pow(10.0, -2.7 * tb);
+ }
+ prev_bark = bark;
+
+ freqmid[i] = freq;
+
+ tf = freq;
+ while (tf < nyquist_freq) {
+ tf += 0.5;
+ tb = freq2bark(tf);
+ if (tb > bark + 0.5)
+ break;
+ }
+ freqmax[i] = tf;
+
+ tf = freq;
+ while (tf > 0.0) {
+ tf -= 0.5;
+ tb = freq2bark(tf);
+ if (tb <= bark - 0.5)
+ break;
+ }
+ freqmin[i] = tf;
+ }
+
+ for (i = 0; i < 32; i++) {
+ freq = freqmax[i];
+ for (j = 31; j > 0 && freq <= freqmid[j]; j--);
+ q->cyclTab[i] = j + 1;
+
+ freq = freqmin[i];
+ for (j = 0; j < 32 && freq >= freqmid[j]; j++);
+ q->cyclTab2[i] = j - 1;
+ }
+}
+
static av_cold int imc_decode_init(AVCodecContext *avctx)
{
int i, j, ret;
IMCContext *q = avctx->priv_data;
double r1, r2;
- if (avctx->channels != 1) {
+ if ((avctx->codec_id == CODEC_ID_IMC && avctx->channels != 1)
+ || (avctx->codec_id == CODEC_ID_IAC && avctx->channels > 2)) {
av_log_ask_for_sample(avctx, "Number of channels is not supported\n");
return AVERROR_PATCHWELCOME;
}
}
q->one_div_log2 = 1 / log(2);
+ if (avctx->codec_id == CODEC_ID_IAC) {
+ }
+
+ if (avctx->codec_id == CODEC_ID_IAC) {
+ iac_generate_tabs(q, avctx->sample_rate);
+ } else {
+ memcpy(q->cyclTab, cyclTab, sizeof(cyclTab));
+ memcpy(q->cyclTab2, cyclTab2, sizeof(cyclTab2));
+ memcpy(q->weights1, imc_weights1, sizeof(imc_weights1));
+ memcpy(q->weights2, imc_weights2, sizeof(imc_weights2));
+ }
+
if ((ret = ff_fft_init(&q->fft, 7, 1))) {
av_log(avctx, AV_LOG_INFO, "FFT init failed\n");
return ret;
}
for (i = 0; i < BANDS; i++) {
- for (cnt2 = i; cnt2 < cyclTab[i]; cnt2++)
+ for (cnt2 = i; cnt2 < q->cyclTab[i]; cnt2++)
flcoeffs5[cnt2] = flcoeffs5[cnt2] + workT3[i];
workT2[cnt2 - 1] = workT2[cnt2 - 1] + workT3[i];
}
for (i = 1; i < BANDS; i++) {
- accum = (workT2[i - 1] + accum) * imc_weights1[i - 1];
+ accum = (workT2[i - 1] + accum) * q->weights1[i - 1];
flcoeffs5[i] += accum;
}
workT2[i] = 0.0;
for (i = 0; i < BANDS; i++) {
- for (cnt2 = i - 1; cnt2 > cyclTab2[i]; cnt2--)
+ for (cnt2 = i - 1; cnt2 > q->cyclTab2[i]; cnt2--)
flcoeffs5[cnt2] += workT3[i];
workT2[cnt2+1] += workT3[i];
}
accum = 0.0;
for (i = BANDS-2; i >= 0; i--) {
- accum = (workT2[i+1] + accum) * imc_weights2[i];
+ accum = (workT2[i+1] + accum) * q->weights2[i];
flcoeffs5[i] += accum;
// there is missing code here, but it seems to never be triggered
}
/* Check the frame header */
imc_hdr = get_bits(&q->gb, 9);
- if (imc_hdr != IMC_FRAME_ID) {
- av_log(avctx, AV_LOG_ERROR, "imc frame header check failed!\n");
- av_log(avctx, AV_LOG_ERROR, "got %x instead of 0x21.\n", imc_hdr);
+ if (imc_hdr & 0x18) {
+ av_log(avctx, AV_LOG_ERROR, "frame header check failed!\n");
+ av_log(avctx, AV_LOG_ERROR, "got %X.\n", imc_hdr);
return AVERROR_INVALIDDATA;
}
stream_format_code = get_bits(&q->gb, 3);
if (stream_format_code & 1) {
- av_log(avctx, AV_LOG_ERROR, "Stream code format %X is not supported\n", stream_format_code);
- return AVERROR_INVALIDDATA;
+ av_log_ask_for_sample(avctx, "Stream format %X is not supported\n",
+ stream_format_code);
+ return AVERROR_PATCHWELCOME;
}
// av_log(avctx, AV_LOG_DEBUG, "stream_format_code = %d\n", stream_format_code);
}
}
}
+ if (avctx->codec_id == CODEC_ID_IAC) {
+ bitscount += !!chctx->bandWidthT[BANDS - 1];
+ if (!(stream_format_code & 0x2))
+ bitscount += 16;
+ }
if ((ret = bit_allocation(q, chctx, stream_format_code,
512 - bitscount - get_bits_count(&q->gb),
LOCAL_ALIGNED_16(uint16_t, buf16, [IMC_BLOCK_SIZE / 2]);
- if (buf_size < IMC_BLOCK_SIZE) {
- av_log(avctx, AV_LOG_ERROR, "imc frame too small!\n");
+ if (buf_size < IMC_BLOCK_SIZE * avctx->channels) {
+ av_log(avctx, AV_LOG_ERROR, "frame too small!\n");
return AVERROR_INVALIDDATA;
}
return ret;
}
+ if (avctx->channels == 2) {
+ float *src = (float*)q->frame.data[0], t1, t2;
+
+ for (i = 0; i < COEFFS; i++) {
+ t1 = src[0];
+ t2 = src[1];
+ src[0] = t1 + t2;
+ src[1] = t1 - t2;
+ src += 2;
+ }
+ }
+
*got_frame_ptr = 1;
*(AVFrame *)data = q->frame;
return 0;
}
-
+#if CONFIG_IMC_DECODER
AVCodec ff_imc_decoder = {
.name = "imc",
.type = AVMEDIA_TYPE_AUDIO,
.capabilities = CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("IMC (Intel Music Coder)"),
};
+#endif
+#if CONFIG_IAC_DECODER
+AVCodec ff_iac_decoder = {
+ .name = "iac",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .id = CODEC_ID_IAC,
+ .priv_data_size = sizeof(IMCContext),
+ .init = imc_decode_init,
+ .close = imc_decode_close,
+ .decode = imc_decode_frame,
+ .capabilities = CODEC_CAP_DR1,
+ .long_name = NULL_IF_CONFIG_SMALL("IAC (Indeo Audio Coder)"),
+};
+#endif