mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-02-20 20:41:08 +01:00
Move AHX MPEG init code to mpeg_decoder and other cleanup
This commit is contained in:
parent
6b99cf8f72
commit
2e41586e68
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user