make MPEG detection accessible to anyone, add MPEG support for XVAG (though it seems that the sample count is wrong)

git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@831 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
halleyscometsw 2010-09-10 21:49:56 +00:00
parent 51a12c5e30
commit 617ee5cdff
4 changed files with 142 additions and 102 deletions

View File

@ -78,6 +78,7 @@ void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channels
void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL * stream,
mpeg_codec_data * data,
sample * outbuf, int32_t samples_to_do);
mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, long given_sample_rate, int given_channels, coding_t *coding_type);
void decode_mpeg(VGMSTREAMCHANNEL * stream,
mpeg_codec_data * data,
sample * outbuf, int32_t samples_to_do, int channels);

View File

@ -85,6 +85,94 @@ void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL *stream,
}
}
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 rc;
off_t read_offset;
mpeg_codec_data *data = NULL;
data = calloc(1,sizeof(mpeg_codec_data));
if (!data) goto mpeg_fail;
data->m = mpg123_new(NULL,&rc);
if (rc==MPG123_NOT_INITIALIZED) {
if (mpg123_init()!=MPG123_OK) goto mpeg_fail;
data->m = mpg123_new(NULL,&rc);
if (rc!=MPG123_OK) goto mpeg_fail;
} else if (rc!=MPG123_OK) {
goto mpeg_fail;
}
mpg123_param(data->m,MPG123_REMOVE_FLAGS,MPG123_GAPLESS,0.0);
if (mpg123_open_feed(data->m)!=MPG123_OK) {
goto mpeg_fail;
}
/* check format */
read_offset=0;
do {
size_t bytes_done;
if (read_streamfile(data->buffer, start_offset+read_offset,
MPEG_BUFFER_SIZE,streamfile) !=
MPEG_BUFFER_SIZE) goto mpeg_fail;
read_offset+=1;
rc = mpg123_decode(data->m,data->buffer,MPEG_BUFFER_SIZE,
NULL,0,&bytes_done);
if (rc != MPG123_OK && rc != MPG123_NEW_FORMAT &&
rc != MPG123_NEED_MORE) goto mpeg_fail;
} while (rc != MPG123_NEW_FORMAT);
{
long rate;
int channels,encoding;
struct mpg123_frameinfo mi;
rc = mpg123_getformat(data->m,&rate,&channels,&encoding);
if (rc != MPG123_OK) goto mpeg_fail;
//fprintf(stderr,"getformat ok, sr=%ld (%ld) ch=%d (%d) enc=%d (%d)\n",rate,given_sample_rate,channels,vgmstream->channels,encoding,MPG123_ENC_SIGNED_16);
if ((given_sample_rate != -1 && rate != given_sample_rate) ||
(given_channels != -1 && channels != given_channels) ||
encoding != MPG123_ENC_SIGNED_16) goto mpeg_fail;
mpg123_info(data->m,&mi);
if (given_sample_rate != -1 &&
mi.rate != given_sample_rate) goto mpeg_fail;
//fprintf(stderr,"mi.version=%d, mi.layer=%d\n",mi.version,mi.layer);
if (mi.version == MPG123_1_0 && mi.layer == 1)
*coding_type = coding_MPEG1_L1;
else if (mi.version == MPG123_1_0 && mi.layer == 2)
*coding_type = coding_MPEG1_L2;
else if (mi.version == MPG123_1_0 && mi.layer == 3)
*coding_type = coding_MPEG1_L3;
else if (mi.version == MPG123_2_0 && mi.layer == 1)
*coding_type = coding_MPEG2_L1;
else if (mi.version == MPG123_2_0 && mi.layer == 2)
*coding_type = coding_MPEG2_L2;
else if (mi.version == MPG123_2_0 && mi.layer == 3)
*coding_type = coding_MPEG2_L3;
else if (mi.version == MPG123_2_5 && mi.layer == 1)
*coding_type = coding_MPEG25_L1;
else if (mi.version == MPG123_2_5 && mi.layer == 2)
*coding_type = coding_MPEG25_L2;
else if (mi.version == MPG123_2_5 && mi.layer == 3)
*coding_type = coding_MPEG25_L3;
else goto mpeg_fail;
}
/* reinit, to ignore the reading we've done so far */
mpg123_open_feed(data->m);
return data;
mpeg_fail:
fprintf(stderr, "mpeg_fail start_offset=%x\n",(unsigned int)start_offset);
if (data) {
mpg123_delete(data->m);
free(data);
}
return NULL;
}
/* decode anything mpg123 can */
void decode_mpeg(VGMSTREAMCHANNEL *stream,
mpeg_codec_data * data,

View File

@ -26,9 +26,6 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
char filename[260];
int coding;
#ifdef VGM_USE_MPEG
mpeg_codec_data *data = NULL;
#endif
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -325,89 +322,14 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
#ifdef VGM_USE_MPEG
if (coding == coding_MPEG1_L3) {
int rc;
off_t read_offset;
data = calloc(1,sizeof(mpeg_codec_data));
if (!data) goto mpeg_fail;
data->m = mpg123_new(NULL,&rc);
if (rc==MPG123_NOT_INITIALIZED) {
if (mpg123_init()!=MPG123_OK) goto mpeg_fail;
data->m = mpg123_new(NULL,&rc);
if (rc!=MPG123_OK) goto mpeg_fail;
} else if (rc!=MPG123_OK) {
goto mpeg_fail;
}
mpg123_param(data->m,MPG123_REMOVE_FLAGS,MPG123_GAPLESS,0.0);
if (mpg123_open_feed(data->m)!=MPG123_OK) {
goto mpeg_fail;
}
/* check format */
read_offset=0;
do {
size_t bytes_done;
if (read_streamfile(data->buffer, start_offset+read_offset,
MPEG_BUFFER_SIZE,vgmstream->ch[0].streamfile) !=
MPEG_BUFFER_SIZE) goto mpeg_fail;
read_offset+=1;
rc = mpg123_decode(data->m,data->buffer,MPEG_BUFFER_SIZE,
NULL,0,&bytes_done);
if (rc != MPG123_OK && rc != MPG123_NEW_FORMAT &&
rc != MPG123_NEED_MORE) goto mpeg_fail;
} while (rc != MPG123_NEW_FORMAT);
{
long rate;
int channels,encoding;
struct mpg123_frameinfo mi;
rc = mpg123_getformat(data->m,&rate,&channels,&encoding);
if (rc != MPG123_OK) goto mpeg_fail;
if (rate != vgmstream->sample_rate ||
channels != vgmstream->channels ||
encoding != MPG123_ENC_SIGNED_16) goto mpeg_fail;
mpg123_info(data->m,&mi);
if (mi.rate != vgmstream->sample_rate) goto mpeg_fail;
if (mi.version == MPG123_1_0 && mi.layer == 1)
vgmstream->coding_type = coding_MPEG1_L1;
else if (mi.version == MPG123_1_0 && mi.layer == 2)
vgmstream->coding_type = coding_MPEG1_L2;
else if (mi.version == MPG123_1_0 && mi.layer == 3)
vgmstream->coding_type = coding_MPEG1_L3;
else if (mi.version == MPG123_2_0 && mi.layer == 1)
vgmstream->coding_type = coding_MPEG2_L1;
else if (mi.version == MPG123_2_0 && mi.layer == 2)
vgmstream->coding_type = coding_MPEG2_L2;
else if (mi.version == MPG123_2_0 && mi.layer == 3)
vgmstream->coding_type = coding_MPEG2_L3;
else if (mi.version == MPG123_2_5 && mi.layer == 1)
vgmstream->coding_type = coding_MPEG25_L1;
else if (mi.version == MPG123_2_5 && mi.layer == 2)
vgmstream->coding_type = coding_MPEG25_L2;
else if (mi.version == MPG123_2_5 && mi.layer == 3)
vgmstream->coding_type = coding_MPEG25_L3;
else goto mpeg_fail;
}
/* reinit, to ignore the reading we've done so far */
mpg123_open_feed(data->m);
vgmstream->codec_data = data;
vgmstream->codec_data = init_mpeg_codec_data(vgmstream->ch[0].streamfile, start_offset, vgmstream->sample_rate, &(vgmstream->coding_type));
if (!vgmstream->codec_data) goto fail;
}
#endif
return vgmstream;
/* clean up anything we may have opened */
#ifdef VGM_USE_MPEG
mpeg_fail:
if (data) {
mpg123_delete(data->m);
free(data);
}
#endif
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;

View File

@ -1,4 +1,5 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util.h"
/* XVAG (from Ratchet & Clank Future: Quest for Booty) */
@ -18,10 +19,15 @@ VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE *streamFile) {
int channel_count;
off_t readOffset = 0;
int little_endian = 0;
long sample_rate = 0;
long num_samples = 0;
mpeg_codec_data *mpeg_data = NULL;
coding_t mpeg_coding_type = coding_MPEG1_L3;
int loopStartPointsCount=0;
int loopEndPointsCount=0;
int mp3ID;
uint16_t mp3ID;
off_t loopStartPoints[0x10];
off_t loopEndPoints[0x10];
@ -45,18 +51,38 @@ VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE *streamFile) {
{
channel_count = read_32bitLE(0x28,streamFile);
start_offset = read_32bitLE(0x4,streamFile);
sample_rate = read_32bitLE(0x3c,streamFile);
num_samples = read_32bitLE(0x30,streamFile);
}
else
{
channel_count = read_32bitBE(0x28,streamFile);
start_offset = read_32bitBE(0x4,streamFile);
sample_rate = read_32bitBE(0x3c,streamFile);
num_samples = read_32bitBE(0x30,streamFile);
}
readOffset=start_offset;
// MP3s ?
mp3ID=read_16bitLE(0x4C,streamFile);
if(mp3ID!=0xFFFFFBFF) {
mp3ID=(uint16_t)read_16bitBE(0x4C,streamFile);
if(mp3ID==0xFFFB) {
#ifdef VGM_USE_MPEG
long rate;
int channels,encoding;
mpeg_data = init_mpeg_codec_data(streamFile, start_offset, -1, -1, &mpeg_coding_type); // -1 to not check sample rate or channels
if (!mpeg_data) goto fail;
if (MPG123_OK != mpg123_getformat(mpeg_data->m,&rate,&channels,&encoding)) goto fail;
channel_count = channels;
sample_rate = rate;
#else
// reject if no MPEG support
goto fail;
#endif
} else {
// get the loops the same way we get on .MIB
do {
readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile);
@ -121,22 +147,21 @@ VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE *streamFile) {
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
if (little_endian) {
vgmstream->sample_rate = read_32bitLE(0x3c,streamFile);
vgmstream->num_samples = read_32bitLE(0x30,streamFile);
} else {
vgmstream->sample_rate = read_32bitBE(0x3c,streamFile);
vgmstream->num_samples = read_32bitBE(0x30,streamFile);
}
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->channels = channel_count;
vgmstream->meta_type = meta_PS3_XVAG;
if(mp3ID==0xFFFFFBFF) {
// mp3s support doesn't work atm !
if(mp3ID==0xFFFB) {
#ifdef VGM_USE_MPEG
/* NOTE: num_samples seems to be quite wrong for MPEG */
vgmstream->codec_data = mpeg_data;
vgmstream->layout_type = layout_mpeg;
vgmstream->coding_type = coding_MPEG1_L3;
vgmstream->coding_type = mpeg_coding_type;
#else
// reject if no MPEG support
goto fail;
#endif
}
else {
vgmstream->layout_type = layout_interleave;
@ -161,13 +186,7 @@ VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE *streamFile) {
{
int i;
STREAMFILE * file;
if(vgmstream->layout_type == layout_mpeg) {
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,MPEG_BUFFER_SIZE);
vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].offset=start_offset;
}
} else {
if(vgmstream->layout_type == layout_interleave) {
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
@ -179,6 +198,16 @@ VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE *streamFile) {
}
}
#ifdef VGM_USE_MPEG
else if(vgmstream->layout_type == layout_mpeg) {
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,MPEG_BUFFER_SIZE);
vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].offset=start_offset;
}
}
#endif
else { goto fail; }
}
return vgmstream;