Move AHX MPEG init code to mpeg_decoder and other cleanup

This commit is contained in:
bnnm 2017-02-17 18:35:58 +01:00
parent 6b99cf8f72
commit 2e41586e68
3 changed files with 118 additions and 134 deletions

View File

@ -120,6 +120,7 @@ void decode_ogg_vorbis(ogg_vorbis_codec_data * data, sample * outbuf, int32_t sa
/* mpeg_decoder */
#ifdef VGM_USE_MPEG
mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, long given_sample_rate, int given_channels, coding_t *coding_type, int * actual_sample_rate, int * actual_channels);
mpeg_codec_data *init_mpeg_codec_data_ahx(STREAMFILE *streamFile, off_t start_offset, int channel_count);
void decode_mpeg(VGMSTREAMCHANNEL * stream, mpeg_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels);
void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL * stream, mpeg_codec_data * data, sample * outbuf, int32_t samples_to_do);

View File

@ -6,84 +6,6 @@
#include "coding.h"
#include "../util.h"
/* mono, mpg123 expects frames of 0x414 (160kbps, 22050Hz) but they
* actually vary and are much shorter */
void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL *stream,
mpeg_codec_data * data,
sample * outbuf, int32_t samples_to_do) {
int samples_done = 0;
while (samples_done < samples_to_do) {
size_t bytes_done;
int rc;
if (!data->buffer_full) {
/* fill buffer up to next frame ending (or file ending) */
int bytes_into_header = 0;
const uint8_t header[4] = {0xff,0xf5,0xe0,0xc0};
off_t frame_offset = 0;
/* assume that we are starting at a header, skip it and look for the
* next one */
read_streamfile(data->buffer, stream->offset+frame_offset, 4,
stream->streamfile);
frame_offset += 4;
do {
uint8_t byte;
byte =
read_8bit(stream->offset+frame_offset,stream->streamfile);
data->buffer[frame_offset] = byte;
frame_offset++;
if (byte == header[bytes_into_header]) {
bytes_into_header++;
} else {
/* This might have been the first byte of the header, so
* we need to check again.
* No need to get more complicated than this, though, since
* there are no repeated characters in the search string. */
if (bytes_into_header>0) {
frame_offset--;
}
bytes_into_header=0;
}
if (bytes_into_header==4) {
break;
}
} while (frame_offset < AHX_EXPECTED_FRAME_SIZE);
if (bytes_into_header==4) frame_offset-=4;
memset(data->buffer+frame_offset,0,
AHX_EXPECTED_FRAME_SIZE-frame_offset);
data->buffer_full = 1;
data->buffer_used = 0;
stream->offset += frame_offset;
}
if (!data->buffer_used) {
rc = mpg123_decode(data->m,
data->buffer,AHX_EXPECTED_FRAME_SIZE,
(unsigned char *)(outbuf+samples_done),
(samples_to_do-samples_done)*sizeof(sample),
&bytes_done);
data->buffer_used = 1;
} else {
rc = mpg123_decode(data->m,
NULL,0,
(unsigned char *)(outbuf+samples_done),
(samples_to_do-samples_done)*sizeof(sample),
&bytes_done);
}
if (rc == MPG123_NEED_MORE) data->buffer_full = 0;
samples_done += bytes_done/sizeof(sample);
}
}
mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, long given_sample_rate, int given_channels, coding_t *coding_type, int * actual_sample_rate, int * actual_channels) {
int rc;
@ -168,14 +90,39 @@ mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset
return data;
mpeg_fail:
fprintf(stderr, "mpeg_fail start_offset=%x\n",(unsigned int)start_offset);
if (data) {
mpg123_delete(data->m);
free(data);
}
free_mpeg(data);
return NULL;
}
mpeg_codec_data *init_mpeg_codec_data_ahx(STREAMFILE *streamFile, off_t start_offset, int channel_count) {
mpeg_codec_data *data = NULL;
int rc;
data = calloc(1,sizeof(mpeg_codec_data));
if (!data) goto fail;
data->m = mpg123_new(NULL,&rc);
if (rc == MPG123_NOT_INITIALIZED) {
if (mpg123_init() != MPG123_OK) goto fail;
data->m = mpg123_new(NULL,&rc);
if (rc != MPG123_OK) goto fail;
} else if (rc!=MPG123_OK) {
goto fail;
}
if (mpg123_open_feed(data->m) != MPG123_OK) {
goto fail;
}
return data;
fail:
free_mpeg(data);
return NULL;
}
/* decode anything mpg123 can */
void decode_mpeg(VGMSTREAMCHANNEL *stream,
mpeg_codec_data * data,
@ -222,6 +169,85 @@ void decode_mpeg(VGMSTREAMCHANNEL *stream,
}
}
/* mono, mpg123 expects frames of 0x414 (160kbps, 22050Hz) but they
* actually vary and are much shorter */
void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL *stream,
mpeg_codec_data * data,
sample * outbuf, int32_t samples_to_do) {
int samples_done = 0;
while (samples_done < samples_to_do) {
size_t bytes_done;
int rc;
if (!data->buffer_full) {
/* fill buffer up to next frame ending (or file ending) */
int bytes_into_header = 0;
const uint8_t header[4] = {0xff,0xf5,0xe0,0xc0};
off_t frame_offset = 0;
/* assume that we are starting at a header, skip it and look for the
* next one */
read_streamfile(data->buffer, stream->offset+frame_offset, 4,
stream->streamfile);
frame_offset += 4;
do {
uint8_t byte;
byte =
read_8bit(stream->offset+frame_offset,stream->streamfile);
data->buffer[frame_offset] = byte;
frame_offset++;
if (byte == header[bytes_into_header]) {
bytes_into_header++;
} else {
/* This might have been the first byte of the header, so
* we need to check again.
* No need to get more complicated than this, though, since
* there are no repeated characters in the search string. */
if (bytes_into_header>0) {
frame_offset--;
}
bytes_into_header=0;
}
if (bytes_into_header==4) {
break;
}
} while (frame_offset < AHX_EXPECTED_FRAME_SIZE);
if (bytes_into_header==4) frame_offset-=4;
memset(data->buffer+frame_offset,0,
AHX_EXPECTED_FRAME_SIZE-frame_offset);
data->buffer_full = 1;
data->buffer_used = 0;
stream->offset += frame_offset;
}
if (!data->buffer_used) {
rc = mpg123_decode(data->m,
data->buffer,AHX_EXPECTED_FRAME_SIZE,
(unsigned char *)(outbuf+samples_done),
(samples_to_do-samples_done)*sizeof(sample),
&bytes_done);
data->buffer_used = 1;
} else {
rc = mpg123_decode(data->m,
NULL,0,
(unsigned char *)(outbuf+samples_done),
(samples_to_do-samples_done)*sizeof(sample),
&bytes_done);
}
if (rc == MPG123_NEED_MORE) data->buffer_full = 0;
samples_done += bytes_done/sizeof(sample);
}
}
void free_mpeg(mpeg_codec_data *data) {
if (!data)

View File

@ -6,26 +6,22 @@
/* AHX is a CRI format which contains an MPEG-2 Layer 2 audio stream.
* Although the MPEG frame headers are incorrect... */
VGMSTREAM * init_vgmstream_ahx(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t stream_offset;
char filename[PATH_LIMIT];
off_t start_offset;
int channel_count = 1;
int loop_flag = 0;
mpeg_codec_data *data = NULL;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("ahx",filename_extension(filename))) goto fail;
if ( !check_extensions(streamFile, "ahx") ) goto fail;
/* check first 2 bytes */
if ((uint16_t)read_16bitBE(0,streamFile)!=0x8000) goto fail;
/* get stream offset, check for CRI signature just before */
stream_offset = (uint16_t)read_16bitBE(2,streamFile) + 4;
if ((uint16_t)read_16bitBE(stream_offset-6,streamFile)!=0x2863 ||/* "(c" */
(uint32_t)read_32bitBE(stream_offset-4,streamFile)!=0x29435249 /* ")CRI" */
start_offset = (uint16_t)read_16bitBE(2,streamFile) + 4;
if ((uint16_t)read_16bitBE(start_offset-6,streamFile)!=0x2863 ||/* "(c" */
(uint32_t)read_32bitBE(start_offset-4,streamFile)!=0x29435249 /* ")CRI" */
) goto fail;
/* check for encoding type */
@ -58,53 +54,14 @@ VGMSTREAM * init_vgmstream_ahx(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_fake_MPEG2_L2;
vgmstream->layout_type = layout_fake_mpeg;
vgmstream->meta_type = meta_AHX;
vgmstream->codec_data = init_mpeg_codec_data_ahx(streamFile, start_offset, channel_count);
{
int i;
STREAMFILE * chstreamfile;
chstreamfile = streamFile->open(streamFile,filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!chstreamfile) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = chstreamfile;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
stream_offset;
}
}
/* ooh, fun part, set up mpg123 */
{
int rc;
data = calloc(1,sizeof(mpeg_codec_data));
if (!data) goto fail;
data->m = mpg123_new(NULL,&rc);
if (rc==MPG123_NOT_INITIALIZED) {
if (mpg123_init()!=MPG123_OK) goto fail;
data->m = mpg123_new(NULL,&rc);
if (rc!=MPG123_OK) goto fail;
} else if (rc!=MPG123_OK) {
goto fail;
}
if (mpg123_open_feed(data->m)!=MPG123_OK) {
goto fail;
}
vgmstream->codec_data = data;
}
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
free_mpeg(data);
if (vgmstream) vgmstream->codec_data = NULL;
close_vgmstream(vgmstream);
return NULL;
}