2008-05-10 21:59:29 +02:00
|
|
|
#include "meta.h"
|
2008-05-11 03:55:13 +02:00
|
|
|
#include "../layout/layout.h"
|
2008-05-10 21:59:29 +02:00
|
|
|
#include "../util.h"
|
|
|
|
|
|
|
|
/* Sony PSX CD-XA */
|
|
|
|
/* No looped file ! */
|
|
|
|
|
2017-10-28 01:34:32 +02:00
|
|
|
static off_t init_xa_channel(int *channel,STREAMFILE *streamFile);
|
2008-05-11 03:55:13 +02:00
|
|
|
|
2017-10-28 01:34:32 +02:00
|
|
|
static uint8_t AUDIO_CODING_GET_STEREO(uint8_t value) {
|
2008-05-10 21:59:29 +02:00
|
|
|
return (uint8_t)(value & 3);
|
|
|
|
}
|
|
|
|
|
2017-10-28 01:34:32 +02:00
|
|
|
static uint8_t AUDIO_CODING_GET_FREQ(uint8_t value) {
|
2008-05-10 21:59:29 +02:00
|
|
|
return (uint8_t)((value >> 2) & 3);
|
|
|
|
}
|
|
|
|
|
2008-05-20 17:18:38 +02:00
|
|
|
VGMSTREAM * init_vgmstream_cdxa(STREAMFILE *streamFile) {
|
2008-05-10 21:59:29 +02:00
|
|
|
VGMSTREAM * vgmstream = NULL;
|
2013-05-27 05:55:50 +02:00
|
|
|
char filename[PATH_LIMIT];
|
2008-05-10 21:59:29 +02:00
|
|
|
|
|
|
|
int channel_count;
|
2010-10-02 15:49:23 +02:00
|
|
|
int headerless=0;
|
2010-10-03 11:34:44 +02:00
|
|
|
int xa_channel=0;
|
2008-05-10 21:59:29 +02:00
|
|
|
uint8_t bCoding;
|
2008-05-17 20:06:45 +02:00
|
|
|
off_t start_offset;
|
2008-05-10 21:59:29 +02:00
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* check extension, case insensitive */
|
2008-05-20 17:18:38 +02:00
|
|
|
streamFile->get_name(streamFile,filename,sizeof(filename));
|
2008-05-10 21:59:29 +02:00
|
|
|
if (strcasecmp("xa",filename_extension(filename))) goto fail;
|
|
|
|
|
|
|
|
/* check RIFF Header */
|
2008-05-20 17:18:38 +02:00
|
|
|
if (!((read_32bitBE(0x00,streamFile) == 0x52494646) &&
|
|
|
|
(read_32bitBE(0x08,streamFile) == 0x43445841) &&
|
|
|
|
(read_32bitBE(0x0C,streamFile) == 0x666D7420)))
|
2010-10-02 15:49:23 +02:00
|
|
|
headerless=1;
|
2008-05-10 21:59:29 +02:00
|
|
|
|
2017-06-25 00:45:15 +02:00
|
|
|
/* don't misdetect Reflections' XA ("XA30" / "04SW") */
|
|
|
|
if (read_32bitBE(0x00,streamFile) == 0x58413330 || read_32bitBE(0x00,streamFile) == 0x30345357) goto fail;
|
2017-07-08 00:26:03 +02:00
|
|
|
/* don't misdetect Maxis XA ("XAI\0" / "XAJ\0") */
|
|
|
|
if (read_32bitBE(0x00,streamFile) == 0x58414900 || read_32bitBE(0x00,streamFile) == 0x58414A00) goto fail;
|
2017-06-25 00:45:15 +02:00
|
|
|
|
2008-05-17 20:06:45 +02:00
|
|
|
/* First init to have the correct info of the channel */
|
2010-10-02 15:49:23 +02:00
|
|
|
if (!headerless) {
|
|
|
|
start_offset=init_xa_channel(&xa_channel,streamFile);
|
|
|
|
|
|
|
|
/* No sound ? */
|
|
|
|
if(start_offset==0)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
bCoding = read_8bit(start_offset-5,streamFile);
|
|
|
|
|
|
|
|
switch (AUDIO_CODING_GET_STEREO(bCoding)) {
|
|
|
|
case 0: channel_count = 1; break;
|
|
|
|
case 1: channel_count = 2; break;
|
|
|
|
default: channel_count = 0; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* build the VGMSTREAM */
|
|
|
|
vgmstream = allocate_vgmstream(channel_count,0);
|
|
|
|
if (!vgmstream) goto fail;
|
|
|
|
|
|
|
|
/* fill in the vital statistics */
|
|
|
|
vgmstream->channels = channel_count;
|
|
|
|
vgmstream->xa_channel = xa_channel;
|
|
|
|
|
|
|
|
switch (AUDIO_CODING_GET_FREQ(bCoding)) {
|
|
|
|
case 0: vgmstream->sample_rate = 37800; break;
|
|
|
|
case 1: vgmstream->sample_rate = 18900; break;
|
|
|
|
default: vgmstream->sample_rate = 0; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for Compression Scheme */
|
|
|
|
vgmstream->num_samples = (int32_t)((((get_streamfile_size(streamFile) - 0x3C)/2352)*0x1F80)/(2*channel_count));
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
channel_count=2;
|
|
|
|
vgmstream = allocate_vgmstream(2,0);
|
|
|
|
if (!vgmstream) goto fail;
|
|
|
|
|
|
|
|
vgmstream->xa_headerless=1;
|
|
|
|
vgmstream->sample_rate=44100;
|
|
|
|
vgmstream->channels=2;
|
|
|
|
vgmstream->num_samples = (int32_t)(((get_streamfile_size(streamFile)/ 0x80)*0xE0)/2);
|
|
|
|
start_offset=0;
|
2008-05-10 21:59:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
vgmstream->coding_type = coding_XA;
|
|
|
|
vgmstream->layout_type = layout_xa_blocked;
|
|
|
|
vgmstream->meta_type = meta_PSX_XA;
|
|
|
|
|
2008-05-20 17:18:38 +02:00
|
|
|
/* open the file for reading by each channel */
|
2008-05-10 21:59:29 +02:00
|
|
|
{
|
2008-05-20 22:19:46 +02:00
|
|
|
STREAMFILE *chstreamfile;
|
|
|
|
chstreamfile = streamFile->open(streamFile,filename,2352);
|
|
|
|
|
|
|
|
if (!chstreamfile) goto fail;
|
2008-05-10 21:59:29 +02:00
|
|
|
|
2008-05-20 22:19:46 +02:00
|
|
|
for (i=0;i<channel_count;i++) {
|
|
|
|
vgmstream->ch[i].streamfile = chstreamfile;
|
2008-05-10 21:59:29 +02:00
|
|
|
}
|
|
|
|
}
|
2008-05-17 20:06:45 +02:00
|
|
|
|
|
|
|
xa_block_update(start_offset,vgmstream);
|
2008-05-10 21:59:29 +02:00
|
|
|
|
|
|
|
return vgmstream;
|
|
|
|
|
|
|
|
/* clean up anything we may have opened */
|
|
|
|
fail:
|
|
|
|
if (vgmstream) close_vgmstream(vgmstream);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-10-02 15:49:23 +02:00
|
|
|
off_t init_xa_channel(int* channel,STREAMFILE* streamFile) {
|
2008-05-10 21:59:29 +02:00
|
|
|
|
|
|
|
off_t block_offset=0x44;
|
2008-05-20 17:18:38 +02:00
|
|
|
size_t filelength=get_streamfile_size(streamFile);
|
2008-05-10 21:59:29 +02:00
|
|
|
|
2008-05-11 23:27:10 +02:00
|
|
|
int8_t currentChannel;
|
2008-05-10 21:59:29 +02:00
|
|
|
|
2008-05-17 20:06:45 +02:00
|
|
|
// 0 can't be a correct value
|
2008-06-03 20:41:26 +02:00
|
|
|
if(block_offset>=(off_t)filelength)
|
2008-05-17 20:06:45 +02:00
|
|
|
return 0;
|
|
|
|
|
2008-05-20 17:18:38 +02:00
|
|
|
currentChannel=read_8bit(block_offset-7,streamFile);
|
2014-06-27 06:12:48 +02:00
|
|
|
//subAudio=read_8bit(block_offset-6,streamFile);
|
2010-10-02 15:49:23 +02:00
|
|
|
*channel=currentChannel;
|
|
|
|
//if (!((currentChannel==channel) && (subAudio==0x64))) {
|
|
|
|
// block_offset+=2352;
|
|
|
|
// goto begin;
|
|
|
|
//}
|
2008-05-10 21:59:29 +02:00
|
|
|
return block_offset;
|
2008-05-11 03:55:13 +02:00
|
|
|
}
|