MSN Audio support

This is essentially a MS GSM decoder extension that supports more
sampling rates and lower bitrates.

Signed-off-by: Anton Khirnov <anton@khirnov.net>
pull/49/head
Kostya Shishkov 11 years ago committed by Anton Khirnov
parent 56d061ce9d
commit a16577d985
  1. 18
      libavcodec/gsm.h
  2. 3
      libavcodec/gsm_parser.c
  3. 19
      libavcodec/gsmdec.c
  4. 26
      libavcodec/gsmdec_data.c
  5. 2
      libavcodec/gsmdec_data.h
  6. 21
      libavcodec/gsmdec_template.c
  7. 6
      libavcodec/msgsmdec.c
  8. 2
      libavcodec/msgsmdec.h
  9. 1
      libavformat/riff.c

@ -22,10 +22,24 @@
#define AVCODEC_GSM_H #define AVCODEC_GSM_H
/* bytes per block */ /* bytes per block */
#define GSM_BLOCK_SIZE 33 #define GSM_BLOCK_SIZE 33
#define GSM_MS_BLOCK_SIZE 65 #define GSM_MS_BLOCK_SIZE 65
#define MSN_MIN_BLOCK_SIZE 41
/* samples per block */ /* samples per block */
#define GSM_FRAME_SIZE 160 #define GSM_FRAME_SIZE 160
enum GSMModes {
GSM_13000 = 0,
MSN_12400,
MSN_11800,
MSN_11200,
MSN_10600,
MSN_10000,
MSN_9400,
MSN_8800,
MSN_8200,
NUM_GSM_MODES
};
#endif /* AVCODEC_GSM_H */ #endif /* AVCODEC_GSM_H */

@ -50,7 +50,8 @@ static int gsm_parse(AVCodecParserContext *s1, AVCodecContext *avctx,
s->duration = GSM_FRAME_SIZE; s->duration = GSM_FRAME_SIZE;
break; break;
case AV_CODEC_ID_GSM_MS: case AV_CODEC_ID_GSM_MS:
s->block_size = GSM_MS_BLOCK_SIZE; s->block_size = avctx->block_align ? avctx->block_align
: GSM_MS_BLOCK_SIZE;
s->duration = GSM_FRAME_SIZE * 2; s->duration = GSM_FRAME_SIZE * 2;
break; break;
default: default:

@ -36,7 +36,8 @@ static av_cold int gsm_init(AVCodecContext *avctx)
{ {
avctx->channels = 1; avctx->channels = 1;
avctx->channel_layout = AV_CH_LAYOUT_MONO; avctx->channel_layout = AV_CH_LAYOUT_MONO;
avctx->sample_rate = 8000; if (!avctx->sample_rate)
avctx->sample_rate = 8000;
avctx->sample_fmt = AV_SAMPLE_FMT_S16; avctx->sample_fmt = AV_SAMPLE_FMT_S16;
switch (avctx->codec_id) { switch (avctx->codec_id) {
@ -46,7 +47,16 @@ static av_cold int gsm_init(AVCodecContext *avctx)
break; break;
case AV_CODEC_ID_GSM_MS: case AV_CODEC_ID_GSM_MS:
avctx->frame_size = 2 * GSM_FRAME_SIZE; avctx->frame_size = 2 * GSM_FRAME_SIZE;
avctx->block_align = GSM_MS_BLOCK_SIZE; if (!avctx->block_align)
avctx->block_align = GSM_MS_BLOCK_SIZE;
else
if (avctx->block_align < MSN_MIN_BLOCK_SIZE ||
avctx->block_align > GSM_MS_BLOCK_SIZE ||
(avctx->block_align - MSN_MIN_BLOCK_SIZE) % 3) {
av_log(avctx, AV_LOG_ERROR, "Invalid block alignment %d\n",
avctx->block_align);
return AVERROR_INVALIDDATA;
}
} }
return 0; return 0;
@ -80,12 +90,13 @@ static int gsm_decode_frame(AVCodecContext *avctx, void *data,
init_get_bits(&gb, buf, buf_size * 8); init_get_bits(&gb, buf, buf_size * 8);
if (get_bits(&gb, 4) != 0xd) if (get_bits(&gb, 4) != 0xd)
av_log(avctx, AV_LOG_WARNING, "Missing GSM magic!\n"); av_log(avctx, AV_LOG_WARNING, "Missing GSM magic!\n");
res = gsm_decode_block(avctx, samples, &gb); res = gsm_decode_block(avctx, samples, &gb, GSM_13000);
if (res < 0) if (res < 0)
return res; return res;
break; break;
case AV_CODEC_ID_GSM_MS: case AV_CODEC_ID_GSM_MS:
res = ff_msgsm_decode_block(avctx, samples, buf); res = ff_msgsm_decode_block(avctx, samples, buf,
(GSM_MS_BLOCK_SIZE - avctx->block_align) / 3);
if (res < 0) if (res < 0)
return res; return res;
} }

@ -92,3 +92,29 @@ const int16_t ff_gsm_dequant_tab[64][8] = {
{-26879, -19199, -11520, -3840, 3840, 11520, 19199, 26879}, {-26879, -19199, -11520, -3840, 3840, 11520, 19199, 26879},
{-28671, -20479, -12288, -4096, 4096, 12288, 20479, 28671} {-28671, -20479, -12288, -4096, 4096, 12288, 20479, 28671}
}; };
static const int apcm_bits[11][13] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1 },
{ 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
{ 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
{ 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
{ 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
{ 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }
};
const int* const ff_gsm_apcm_bits[][4] = {
{ apcm_bits[10], apcm_bits[10], apcm_bits[10], apcm_bits[10] }, // 13000
{ apcm_bits[10], apcm_bits[10], apcm_bits[10], apcm_bits[ 6] }, // 12400
{ apcm_bits[10], apcm_bits[10], apcm_bits[ 7], apcm_bits[ 5] }, // 11800
{ apcm_bits[10], apcm_bits[ 8], apcm_bits[ 5], apcm_bits[ 5] }, // 11200
{ apcm_bits[ 9], apcm_bits[ 5], apcm_bits[ 5], apcm_bits[ 5] }, // 10600
{ apcm_bits[ 5], apcm_bits[ 5], apcm_bits[ 5], apcm_bits[ 1] }, // 10000
{ apcm_bits[ 5], apcm_bits[ 5], apcm_bits[ 2], apcm_bits[ 0] }, // 9400
{ apcm_bits[ 5], apcm_bits[ 3], apcm_bits[ 0], apcm_bits[ 0] }, // 8800
{ apcm_bits[ 4], apcm_bits[ 0], apcm_bits[ 0], apcm_bits[ 0] }, // 8200
};

@ -40,4 +40,6 @@ typedef struct GSMContext {
extern const uint16_t ff_gsm_long_term_gain_tab[4]; extern const uint16_t ff_gsm_long_term_gain_tab[4];
extern const int16_t ff_gsm_dequant_tab[64][8]; extern const int16_t ff_gsm_dequant_tab[64][8];
extern const int* const ff_gsm_apcm_bits[][4];
#endif /* AVCODEC_GSMDEC_DATA_H */ #endif /* AVCODEC_GSMDEC_DATA_H */

@ -28,13 +28,22 @@
#include "gsm.h" #include "gsm.h"
#include "gsmdec_data.h" #include "gsmdec_data.h"
static void apcm_dequant_add(GetBitContext *gb, int16_t *dst) static const int requant_tab[4][8] = {
{ 0 },
{ 0, 7 },
{ 0, 2, 5, 7 },
{ 0, 1, 2, 3, 4, 5, 6, 7 }
};
static void apcm_dequant_add(GetBitContext *gb, int16_t *dst, const int *frame_bits)
{ {
int i; int i, val;
int maxidx = get_bits(gb, 6); int maxidx = get_bits(gb, 6);
const int16_t *tab = ff_gsm_dequant_tab[maxidx]; const int16_t *tab = ff_gsm_dequant_tab[maxidx];
for (i = 0; i < 13; i++) for (i = 0; i < 13; i++) {
dst[3*i] += tab[get_bits(gb, 3)]; val = get_bits(gb, frame_bits[i]);
dst[3*i] += tab[requant_tab[frame_bits[i]][val]];
}
} }
static inline int gsm_mult(int a, int b) static inline int gsm_mult(int a, int b)
@ -118,7 +127,7 @@ static int postprocess(int16_t *data, int msr)
} }
static int gsm_decode_block(AVCodecContext *avctx, int16_t *samples, static int gsm_decode_block(AVCodecContext *avctx, int16_t *samples,
GetBitContext *gb) GetBitContext *gb, int mode)
{ {
GSMContext *ctx = avctx->priv_data; GSMContext *ctx = avctx->priv_data;
int i; int i;
@ -139,7 +148,7 @@ static int gsm_decode_block(AVCodecContext *avctx, int16_t *samples,
int offset = get_bits(gb, 2); int offset = get_bits(gb, 2);
lag = av_clip(lag, 40, 120); lag = av_clip(lag, 40, 120);
long_term_synth(ref_dst, lag, gain_idx); long_term_synth(ref_dst, lag, gain_idx);
apcm_dequant_add(gb, ref_dst + offset); apcm_dequant_add(gb, ref_dst + offset, ff_gsm_apcm_bits[mode][i]);
ref_dst += 40; ref_dst += 40;
} }
memcpy(ctx->ref_buf, ctx->ref_buf + 160, 120 * sizeof(*ctx->ref_buf)); memcpy(ctx->ref_buf, ctx->ref_buf + 160, 120 * sizeof(*ctx->ref_buf));

@ -26,13 +26,13 @@
#include "gsmdec_template.c" #include "gsmdec_template.c"
int ff_msgsm_decode_block(AVCodecContext *avctx, int16_t *samples, int ff_msgsm_decode_block(AVCodecContext *avctx, int16_t *samples,
const uint8_t *buf) const uint8_t *buf, int mode)
{ {
int res; int res;
GetBitContext gb; GetBitContext gb;
init_get_bits(&gb, buf, GSM_MS_BLOCK_SIZE * 8); init_get_bits(&gb, buf, GSM_MS_BLOCK_SIZE * 8);
res = gsm_decode_block(avctx, samples, &gb); res = gsm_decode_block(avctx, samples, &gb, mode);
if (res < 0) if (res < 0)
return res; return res;
return gsm_decode_block(avctx, samples + GSM_FRAME_SIZE, &gb); return gsm_decode_block(avctx, samples + GSM_FRAME_SIZE, &gb, mode);
} }

@ -25,6 +25,6 @@
#include "avcodec.h" #include "avcodec.h"
int ff_msgsm_decode_block(AVCodecContext *avctx, int16_t *samples, int ff_msgsm_decode_block(AVCodecContext *avctx, int16_t *samples,
const uint8_t *buf); const uint8_t *buf, int mode);
#endif /* AVCODEC_MSGSMDEC_H */ #endif /* AVCODEC_MSGSMDEC_H */

@ -338,6 +338,7 @@ const AVCodecTag ff_codec_wav_tags[] = {
{ AV_CODEC_ID_ADPCM_YAMAHA, 0x0020 }, { AV_CODEC_ID_ADPCM_YAMAHA, 0x0020 },
{ AV_CODEC_ID_TRUESPEECH, 0x0022 }, { AV_CODEC_ID_TRUESPEECH, 0x0022 },
{ AV_CODEC_ID_GSM_MS, 0x0031 }, { AV_CODEC_ID_GSM_MS, 0x0031 },
{ AV_CODEC_ID_GSM_MS, 0x0032 },
{ AV_CODEC_ID_ADPCM_G726, 0x0045 }, { AV_CODEC_ID_ADPCM_G726, 0x0045 },
{ AV_CODEC_ID_MP2, 0x0050 }, { AV_CODEC_ID_MP2, 0x0050 },
{ AV_CODEC_ID_MP3, 0x0055 }, { AV_CODEC_ID_MP3, 0x0055 },

Loading…
Cancel
Save