aud: support Westwood SND1 audio in AUD files.

Fixes decoding of the handful of "death scream" samples from
"Command and Conquer" that use SND1. e.g.
http://samples.libav.org/game-formats/westwood-aud/nuyell1.aud
http://samples.libav.org/game-formats/westwood-aud/nuyell7.aud
This commit is contained in:
Justin Ruggles 2012-01-24 11:09:05 -05:00
parent 02e7dbf5ad
commit d481227c54
1 changed files with 26 additions and 6 deletions

View File

@ -79,7 +79,7 @@ static int wsaud_probe(AVProbeData *p)
/* note: only check for WS IMA (type 99) right now since there is no
* support for type 1 */
if (p->buf[11] != 99)
if (p->buf[11] != 99 && p->buf[11] != 1)
return 0;
/* read ahead to the first audio chunk and validate the first header signature */
@ -103,6 +103,8 @@ static int wsaud_read_header(AVFormatContext *s,
wsaud->audio_samplerate = AV_RL16(&header[0]);
if (header[11] == 99)
wsaud->audio_type = CODEC_ID_ADPCM_IMA_WS;
else if (header[11] == 1)
wsaud->audio_type = CODEC_ID_WESTWOOD_SND1;
else
return AVERROR_INVALIDDATA;
@ -121,10 +123,10 @@ static int wsaud_read_header(AVFormatContext *s,
st->codec->codec_tag = 0; /* no tag */
st->codec->channels = wsaud->audio_channels;
st->codec->sample_rate = wsaud->audio_samplerate;
st->codec->bits_per_coded_sample = wsaud->audio_bits;
st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
st->codec->bits_per_coded_sample / 4;
st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
if (st->codec->codec_id == CODEC_ID_ADPCM_IMA_WS) {
st->codec->bits_per_coded_sample = 4;
st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 4;
}
wsaud->audio_stream_index = st->index;
wsaud->audio_frame_counter = 0;
@ -140,6 +142,7 @@ static int wsaud_read_packet(AVFormatContext *s,
unsigned char preamble[AUD_CHUNK_PREAMBLE_SIZE];
unsigned int chunk_size;
int ret = 0;
AVStream *st = s->streams[wsaud->audio_stream_index];
if (avio_read(pb, preamble, AUD_CHUNK_PREAMBLE_SIZE) !=
AUD_CHUNK_PREAMBLE_SIZE)
@ -150,15 +153,32 @@ static int wsaud_read_packet(AVFormatContext *s,
return AVERROR_INVALIDDATA;
chunk_size = AV_RL16(&preamble[0]);
if (st->codec->codec_id == CODEC_ID_WESTWOOD_SND1) {
/* For Westwood SND1 audio we need to add the output size and input
size to the start of the packet to match what is in VQA.
Specifically, this is needed to signal when a packet should be
decoding as raw 8-bit pcm or variable-size ADPCM. */
int out_size = AV_RL16(&preamble[2]);
if ((ret = av_new_packet(pkt, chunk_size + 4)))
return ret;
if ((ret = avio_read(pb, &pkt->data[4], chunk_size)) != chunk_size)
return ret < 0 ? ret : AVERROR(EIO);
AV_WL16(&pkt->data[0], out_size);
AV_WL16(&pkt->data[2], chunk_size);
pkt->duration = out_size;
} else {
ret= av_get_packet(pb, pkt, chunk_size);
if (ret != chunk_size)
return AVERROR(EIO);
pkt->stream_index = wsaud->audio_stream_index;
pkt->pts = wsaud->audio_frame_counter;
pkt->pts /= wsaud->audio_samplerate;
/* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
wsaud->audio_frame_counter += (chunk_size * 2) / wsaud->audio_channels;
}
pkt->stream_index = st->index;
return ret;
}