Merge pull request #72 from bnnm/stuff

Stuff
This commit is contained in:
Christopher Snowhill 2017-03-05 12:52:46 -08:00 committed by GitHub
commit 4f9df81f9b
12 changed files with 271 additions and 308 deletions

View File

@ -404,7 +404,7 @@ void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
break;
}
#if 0
#if XMA_CHECK_SKIPS
// more header stuff (info from FFmpeg)
{
int flag;
@ -432,6 +432,7 @@ void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
flag = read_bitsBE_b(frame_offset_b, 1, streamFile);
frame_offset_b += 1;
if (flag) {
VGM_LOG("start_skip at 0x%I64x\n", frame_offset_b);
new_skip = read_bitsBE_b(frame_offset_b, 10, streamFile);
frame_offset_b += 10;
VGM_ASSERT(start_skip, "XMA: more than one start_skip (%i)\n", new_skip);
@ -449,6 +450,7 @@ void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
flag = read_bitsBE_b(frame_offset_b, 1, streamFile);
frame_offset_b += 1;
if (flag) {
VGM_LOG("end_skip at 0x%I64x\n", frame_offset_b);
new_skip = read_bitsBE_b(frame_offset_b, 10, streamFile);
frame_offset_b += 10;
VGM_ASSERT(end_skip, "XMA: more than one end_skip (%i)\n", new_skip);

View File

@ -93,7 +93,7 @@ static uint32_t bik_get_num_samples(STREAMFILE *streamFile, int bits_per_sample)
* (num_samples for other streams seem erratic though) */
if (target_stream > num_tracks) goto fail;
if (target_stream == 0) target_stream = 1;
VGM_ASSERT(num_tracks > 1, "BIK: multiple streams found (%i entries)\n", num_tracks);
//VGM_ASSERT(num_tracks > 1, "BIK: multiple streams found (%i entries)\n", num_tracks);//FFmpeg data has this
/* read each frame header and sum all samples
* a frame has N audio packets with header (one per track) + video packet */

View File

@ -225,7 +225,7 @@ ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t *
int errcode, i;
int streamIndex;
int streamIndex, streamCount;
AVStream *stream;
AVCodecParameters *codecPar;
@ -273,6 +273,7 @@ ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t *
/* find valid audio stream inside */
streamIndex = -1;
streamCount = 0; /* audio streams only */
for (i = 0; i < data->formatCtx->nb_streams; ++i) {
stream = data->formatCtx->streams[i];
@ -282,12 +283,15 @@ ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t *
} else {
stream->discard = AVDISCARD_ALL; /* disable demuxing unneded streams */
}
if (codecPar->codec_type == AVMEDIA_TYPE_AUDIO)
streamCount++;
}
if (streamIndex < 0) goto fail;
data->streamIndex = streamIndex;
stream = data->formatCtx->streams[streamIndex];
data->streamCount = streamCount;
/* prepare codec and frame/packet buffers */

View File

@ -243,8 +243,6 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) {
}
}
VGM_ASSERT(fsbh.numsamples > 1, "FSB: multiple streams found (%i entries)\n", fsbh.numsamples);
/* XOR encryption for some FSB4 */
if (fsbh.flags & FMOD_FSB_SOURCE_ENCRYPTED) {
VGM_LOG("FSB ENCRYPTED found\n");
@ -272,6 +270,7 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) {
vgmstream->num_samples = fsbh.lengthsamples;
vgmstream->loop_start_sample = fsbh.loopstart;
vgmstream->loop_end_sample = fsbh.loopend;
vgmstream->num_streams = fsbh.numsamples;
vgmstream->meta_type = fsbh.meta_type;
/* parse format */

View File

@ -5,115 +5,131 @@
/* FSB5 header */
VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t StartOffset;
int LoopFlag = 0;
int32_t LoopStart, LoopEnd;
int NumSamples;
int ChannelCount;
int SampleRate;
int DSPInfoStart = 0;
off_t StartOffset = 0;
off_t SampleHeaderStart = 0, DSPInfoStart = 0;
size_t SampleHeaderLength, NameTableLength, SampleDataLength, BaseHeaderLength;
uint32_t BaseSamples = 0, LoopStart = 0, LoopEnd = 0, NumSamples = 0;
int LoopFlag = 0, ChannelCount = 0, SampleRate = 0, CodingID;
int TotalStreams, TargetStream = 0;
int i;
int SampleHeaderStart, SampleHeaderLength, NameTableLength, SampleDataLength, CodingID, SampleMode;
int ExtraFlag, ExtraFlagStart, ExtraFlagType, ExtraFlagSize, ExtraFlagEnd;
int freq_mode, ch_mode;
/* check extension, case insensitive */
if (!check_extensions(streamFile,"fsb")) goto fail;
if (read_32bitBE(0x00,streamFile) != 0x46534235) goto fail; /* "FSB5" */
if (read_32bitLE(0x04,streamFile) != 0x01) goto fail; /* Version ID */
if (read_32bitLE(0x08,streamFile) != 0x01) goto fail; /* Number of Sample Files */
SampleHeaderStart = 0x3C;
//v0 has extra flags at 0x1c and SampleHeaderStart = 0x40?
if (read_32bitLE(0x04,streamFile) != 0x01) goto fail; /* Version ID */
TotalStreams = read_32bitLE(0x08,streamFile);
SampleHeaderLength = read_32bitLE(0x0C,streamFile);
NameTableLength = read_32bitLE(0x10,streamFile);
SampleDataLength = read_32bitLE(0x14,streamFile);
NameTableLength = read_32bitLE(0x10,streamFile);
SampleDataLength = read_32bitLE(0x14,streamFile);
CodingID = read_32bitLE(0x18,streamFile);
/* 0x1c (8): zero, 0x24 (16): hash, 0x34 (8): unk */
BaseHeaderLength = 0x3C;
SampleHeaderStart = BaseHeaderLength;
if ((SampleHeaderLength + NameTableLength + SampleDataLength + 0x3C) != get_streamfile_size(streamFile)) goto fail;
if (TargetStream == 0) TargetStream = 1; /* default to 1 */
if (TargetStream > TotalStreams || TotalStreams < 0) goto fail;
StartOffset = SampleHeaderLength + NameTableLength + 0x3C;
SampleMode = read_32bitLE(SampleHeaderStart+0x00,streamFile);
/* get sample rate */
freq_mode = (SampleMode >> 1) & 0x0f; /* bits 5..1 */
switch (freq_mode) {
case 0: SampleRate = 4000; break; //???
case 1: SampleRate = 8000; break;
case 2: SampleRate = 11000; break;
case 3: SampleRate = 11025; break;
case 4: SampleRate = 16000; break;
case 5: SampleRate = 22050; break;
case 6: SampleRate = 24000; break;
case 7: SampleRate = 32000; break;
case 8: SampleRate = 44100; break;
case 9: SampleRate = 48000; break;
case 10: SampleRate = 96000; break; //???
default:
SampleRate = 44100;
//goto fail; /* probably better? */
break;
}
/* find target stream header and data offset and read all needed values for later use
* (reads one by one as the size of a single stream header is variable) */
for (i = 0; i < TotalStreams; i++) {
off_t DataStart = 0;
size_t StreamHeaderLength = 0;
uint32_t SampleMode;
/* get channels (from tests seems correct, but multichannel isn't very common, ex. no 4ch mode?) */
ch_mode = (SampleMode >> 5) & 0x03; /* bits 7..6 (maybe 8 too?) */
switch (ch_mode) {
case 0: ChannelCount = 1; break;
case 1: ChannelCount = 2; break;
case 2: ChannelCount = 6; break;/* some Dark Souls 2 MPEG; some IMA ADPCM */
case 3: ChannelCount = 8; break;/* some IMA ADPCM */
/* other values (ex. 10ch) seem specified in the extra flags */
default:
goto fail;
}
SampleMode = read_32bitLE(SampleHeaderStart+0x00,streamFile);
BaseSamples = read_32bitLE(SampleHeaderStart+0x04,streamFile);
StreamHeaderLength += 0x08;
/* get extra flags */
ExtraFlagStart = SampleHeaderStart+0x08;
if (SampleMode&0x01) /* bit 0 */
{
do
{
ExtraFlag = read_32bitLE(ExtraFlagStart,streamFile);
ExtraFlagType = (ExtraFlag>>25)&0x7F;
ExtraFlagSize = (ExtraFlag>>1)&0xFFFFFF;
ExtraFlagEnd = (ExtraFlag&0x01);
switch(ExtraFlagType)
{
case 0x01: /* Channel Info */
{
ChannelCount = read_8bit(ExtraFlagStart+0x04,streamFile);
}
break;
case 0x02: /* Sample Rate Info */
{
SampleRate = read_32bitLE(ExtraFlagStart+0x04,streamFile);
}
break;
case 0x03: /* Loop Info */
{
LoopStart = read_32bitLE(ExtraFlagStart+0x04,streamFile);
if (LoopStart != 0x00) {
LoopFlag = 1;
LoopEnd = read_32bitLE(ExtraFlagStart+0x08,streamFile);
}
}
break;
case 0x07: /* DSP Info (Coeffs), only used if coding is DSP??? */
{
DSPInfoStart = ExtraFlagStart+0x04;
}
break;
/* get global offset */
DataStart = (SampleMode >> 7) * 0x20;
/* get sample rate */
switch ((SampleMode >> 1) & 0x0f) { /* bits 5..1 */
case 0: SampleRate = 4000; break; //???
case 1: SampleRate = 8000; break;
case 2: SampleRate = 11000; break;
case 3: SampleRate = 11025; break;
case 4: SampleRate = 16000; break;
case 5: SampleRate = 22050; break;
case 6: SampleRate = 24000; break;
case 7: SampleRate = 32000; break;
case 8: SampleRate = 44100; break;
case 9: SampleRate = 48000; break;
case 10: SampleRate = 96000; break; //???
default:
SampleRate = 44100;
break; /* probably specified in the extra flags */
}
ExtraFlagStart+=ExtraFlagSize+0x04;
}
while (ExtraFlagEnd != 0x00);
/* get channels (from tests seems correct, but multichannel isn't very common, ex. no 4ch mode?) */
switch ((SampleMode >> 5) & 0x03) { /* bits 7..6 */
case 0: ChannelCount = 1; break;
case 1: ChannelCount = 2; break;
case 2: ChannelCount = 6; break;/* some Dark Souls 2 MPEG; some IMA ADPCM */
case 3: ChannelCount = 8; break;/* some IMA ADPCM */
default: /* other values (ex. 10ch) seem specified in the extra flags */
goto fail;
}
/* get extra flags */
if (SampleMode&0x01) { /* bit 0 */
uint32_t ExtraFlag, ExtraFlagStart, ExtraFlagType, ExtraFlagSize, ExtraFlagEnd;
ExtraFlagStart = SampleHeaderStart+0x08;
do {
ExtraFlag = read_32bitLE(ExtraFlagStart,streamFile);
ExtraFlagType = (ExtraFlag>>25)&0x7F;
ExtraFlagSize = (ExtraFlag>>1)&0xFFFFFF;
ExtraFlagEnd = (ExtraFlag&0x01);
switch(ExtraFlagType) {
case 0x01: /* Channel Info */
ChannelCount = read_8bit(ExtraFlagStart+0x04,streamFile);
break;
case 0x02: /* Sample Rate Info */
SampleRate = read_32bitLE(ExtraFlagStart+0x04,streamFile);
break;
case 0x03: /* Loop Info */
LoopStart = read_32bitLE(ExtraFlagStart+0x04,streamFile);
if (ExtraFlagSize > 0x04) /* probably no needed */
LoopEnd = read_32bitLE(ExtraFlagStart+0x08,streamFile);
/* when start is 0 seems the song reoeats with no real looping (ex. Sonic Boom Fire & Ice jingles) */
LoopFlag = (LoopStart != 0x00);
break;
case 0x07: /* DSP Info (Coeffs), only used if coding is DSP??? */
DSPInfoStart = ExtraFlagStart + 0x04;
break;
default:
VGM_LOG("FSB5: unknown extra flag %i at 0x%04x\n", ExtraFlagType, ExtraFlagStart);
break;
}
ExtraFlagStart += 0x04 + ExtraFlagSize;
StreamHeaderLength += 0x04 + ExtraFlagSize;
} while (ExtraFlagEnd != 0x00);
}
/* stream found */
if (i == TotalStreams-1) {
StartOffset = BaseHeaderLength + SampleHeaderLength + NameTableLength + DataStart;
break;
}
/* continue searching */
SampleHeaderStart += StreamHeaderLength;
}
/* target stream not found*/
if (!StartOffset) goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(ChannelCount,LoopFlag);
@ -122,179 +138,128 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
/* fill in the vital statistics */
vgmstream->channels = ChannelCount;
vgmstream->sample_rate = SampleRate;
vgmstream->num_streams = TotalStreams;
vgmstream->meta_type = meta_FSB5;
switch (CodingID) {
case 0x00: /* FMOD_SOUND_FORMAT_NONE */
goto fail;
switch (CodingID)
{
case 0x00: /* FMOD_SOUND_FORMAT_NONE */
{
goto fail;
}
break;
case 0x01: /* FMOD_SOUND_FORMAT_PCM8 */
{
goto fail;
}
break;
case 0x01: /* FMOD_SOUND_FORMAT_PCM8 */
goto fail;
case 0x02: /* FMOD_SOUND_FORMAT_PCM16 */
{
case 0x02: /* FMOD_SOUND_FORMAT_PCM16 */
NumSamples = BaseSamples / 4;
if (ChannelCount == 1) {
vgmstream->layout_type = layout_none;
} else {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
}
NumSamples = read_32bitLE(SampleHeaderStart+0x04,streamFile)/4;
vgmstream->coding_type = coding_PCM16LE;
break;
if (ChannelCount == 1)
{
vgmstream->layout_type = layout_none;
} else {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
}
case 0x03: /* FMOD_SOUND_FORMAT_PCM24 */
goto fail;
case 0x04: /* FMOD_SOUND_FORMAT_PCM32 */
goto fail;
vgmstream->coding_type = coding_PCM16LE;
}
break;
case 0x05: /* FMOD_SOUND_FORMAT_PCMFLOAT */
goto fail;
case 0x03:/* FMOD_SOUND_FORMAT_PCM24 */
{
goto fail;
}
break;
case 0x06: /* FMOD_SOUND_FORMAT_GCADPCM */
if (ChannelCount == 1) {
NumSamples = BaseSamples / 4;
vgmstream->layout_type = layout_none;
} else {
NumSamples = BaseSamples / (2*ChannelCount);
vgmstream->layout_type = layout_interleave_byte;
vgmstream->interleave_block_size = 0x02;
}
case 0x04: /* FMOD_SOUND_FORMAT_PCM32 */
{
goto fail;
}
break;
dsp_read_coefs_be(vgmstream,streamFile,DSPInfoStart,0x2E);
vgmstream->coding_type = coding_NGC_DSP;
break;
case 0x05: /* FMOD_SOUND_FORMAT_PCMFLOAT */
{
goto fail;
}
break;
case 0x07: /* FMOD_SOUND_FORMAT_IMAADPCM */
NumSamples = BaseSamples / 4;
vgmstream->layout_type = layout_none;
vgmstream->coding_type = coding_XBOX;
if (vgmstream->channels > 2) /* multichannel FSB IMA (interleaved header) */
vgmstream->coding_type = coding_FSB_IMA;
break;
case 0x06: /* FMOD_SOUND_FORMAT_GCADPCM */
{
if (ChannelCount == 1)
{
NumSamples = read_32bitLE(SampleHeaderStart+0x04,streamFile)/4;
vgmstream->layout_type = layout_none;
} else {
NumSamples = read_32bitLE(SampleHeaderStart+0x04,streamFile)/(2*ChannelCount);
vgmstream->layout_type = layout_interleave_byte;
vgmstream->interleave_block_size = 0x02;
}
case 0x08: /* FMOD_SOUND_FORMAT_VAG */
goto fail;
vgmstream->coding_type = coding_NGC_DSP;
case 0x09: /* FMOD_SOUND_FORMAT_HEVAG */
goto fail;
dsp_read_coefs_be(vgmstream,streamFile,DSPInfoStart,0x2E);
}
break;
case 0x07: /* FMOD_SOUND_FORMAT_IMAADPCM */
{
NumSamples = read_32bitLE(SampleHeaderStart+0x04,streamFile)/4;
vgmstream->layout_type = layout_none;
vgmstream->coding_type = coding_XBOX;
if (vgmstream->channels > 2) /* multichannel FSB IMA (interleaved header) */
vgmstream->coding_type = coding_FSB_IMA;
}
break;
case 0x08: /* FMOD_SOUND_FORMAT_VAG */
{
goto fail;
}
break;
case 0x09: /* FMOD_SOUND_FORMAT_HEVAG */
{
goto fail;
}
break;
case 0x0A: /* FMOD_SOUND_FORMAT_XMA */
{
goto fail;
}
break;
case 0x0B: /* FMOD_SOUND_FORMAT_MPEG */
{
NumSamples = read_32bitLE(SampleHeaderStart+0x04,streamFile)/2/ChannelCount;
case 0x0A: /* FMOD_SOUND_FORMAT_XMA */
goto fail;
#ifdef VGM_USE_MPEG
{
mpeg_codec_data *mpeg_data = NULL;
coding_t mpeg_coding_type;
case 0x0B: {/* FMOD_SOUND_FORMAT_MPEG */
mpeg_codec_data *mpeg_data = NULL;
coding_t mpeg_coding_type;
NumSamples = BaseSamples / 2 / ChannelCount;
#if 0
int fsb_padding = vgmstream->channels > 2 ? 16 : 0;//todo fix
int fsb_padding = vgmstream->channels > 2 ? 16 : 0;//todo fix
mpeg_data = init_mpeg_codec_data_interleaved(streamFile, StartOffset, &mpeg_coding_type, vgmstream->channels, 0, fsb_padding);
if (!mpeg_data) goto fail;
mpeg_data = init_mpeg_codec_data_interleaved(streamFile, StartOffset, &mpeg_coding_type, vgmstream->channels, 0, fsb_padding);
if (!mpeg_data) goto fail;
vgmstream->interleave_block_size = mpeg_data->current_frame_size + mpeg_data->current_padding;
if (vgmstream->channels > 2) vgmstream->loop_flag = 0;//todo not implemented yet
vgmstream->interleave_block_size = mpeg_data->current_frame_size + mpeg_data->current_padding;
if (vgmstream->channels > 2) vgmstream->loop_flag = 0;//todo not implemented yet
#endif
mpeg_data = init_mpeg_codec_data(streamFile, StartOffset, &mpeg_coding_type, vgmstream->channels);
if (!mpeg_data) goto fail;
if (vgmstream->channels > 2)
goto fail; /* no multichannel for now */
vgmstream->codec_data = mpeg_data;
vgmstream->coding_type = mpeg_coding_type;
vgmstream->layout_type = layout_mpeg;
mpeg_data = init_mpeg_codec_data(streamFile, StartOffset, &mpeg_coding_type, vgmstream->channels);
if (!mpeg_data) goto fail;
mpeg_set_error_logging(mpeg_data, 0);
}
vgmstream->codec_data = mpeg_data;
vgmstream->coding_type = mpeg_coding_type;
vgmstream->layout_type = layout_mpeg;
mpeg_set_error_logging(mpeg_data, 0);
break;
}
#endif
}
break;
case 0x0C: /* FMOD_SOUND_FORMAT_CELT */
goto fail;
case 0x0C: /* FMOD_SOUND_FORMAT_CELT */
{
goto fail;
}
break;
case 0x0D: /* FMOD_SOUND_FORMAT_AT9 */
goto fail;
case 0x0D: /* FMOD_SOUND_FORMAT_AT9 */
{
goto fail;
}
break;
case 0x0E: /* FMOD_SOUND_FORMAT_XWMA */
goto fail;
case 0x0E: /* FMOD_SOUND_FORMAT_XWMA */
{
goto fail;
}
break;
case 0x0F: /* FMOD_SOUND_FORMAT_VORBIS */
goto fail;
case 0x0F: /* FMOD_SOUND_FORMAT_VORBIS */
{
goto fail;
}
break;
default:
goto fail;
}
vgmstream->num_samples = NumSamples;
vgmstream->meta_type = meta_FSB5;
if (LoopFlag)
{
vgmstream->loop_start_sample = LoopStart;
vgmstream->loop_end_sample = LoopEnd;
vgmstream->num_samples = NumSamples;
if (LoopFlag) {
vgmstream->loop_start_sample = LoopStart;
vgmstream->loop_end_sample = LoopEnd;
}
if (!vgmstream_open_stream(vgmstream,streamFile,StartOffset))
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,27 +1,19 @@
/*
Capcom MADP format found in Capcom 3DS games.
*/
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/* Capcom MADP - found in Capcom 3DS games */
VGMSTREAM * init_vgmstream_mca(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int channel_count;
int loop_flag;
int version;
int channel_count, loop_flag, version;
size_t head_size, data_size, file_size;
off_t start_offset, coef_offset, coef_start, coef_shift;
int i, j;
int coef_spacing;
/* check extension, case insensitive */
streamFile->get_name(streamFile, filename, sizeof(filename));
if (strcasecmp("mca", filename_extension(filename)))
if (!check_extensions(streamFile,"mca"))
goto fail;
/* check header */
if ((uint32_t)read_32bitBE(0, streamFile) != 0x4D414450) /* "MADP" */
goto fail;
@ -41,10 +33,7 @@ VGMSTREAM * init_vgmstream_mca(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = read_32bitLE(0x18, streamFile);
vgmstream->coding_type = coding_NGC_DSP;
if (channel_count == 1)
vgmstream->layout_type = layout_none;
else
vgmstream->layout_type = layout_interleave;
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave;
vgmstream->meta_type = meta_MCA;
@ -78,7 +67,7 @@ VGMSTREAM * init_vgmstream_mca(STREAMFILE *streamFile) {
coef_offset = coef_start + coef_shift * 0x14;
}
/* sanity check */
/* sanity check (for bad rips with the header manually truncated to in attempt to "fix" v5 headers) */
file_size = get_streamfile_size(streamFile);
if (start_offset + data_size > file_size) {
@ -88,40 +77,16 @@ VGMSTREAM * init_vgmstream_mca(STREAMFILE *streamFile) {
start_offset = file_size - data_size;
}
/* set up ADPCM coefs */
for (j = 0; j<vgmstream->channels; j++) {
for (i = 0; i<16; i++) {
vgmstream->ch[j].adpcm_coef[i] = read_16bitLE(coef_offset + j*coef_spacing + i * 2, streamFile);
}
}
/* set up ADPCM coefs */
dsp_read_coefs_le(vgmstream, streamFile, coef_offset, coef_spacing);
/* open the file for reading by each channel */
{
for (i = 0; i<channel_count; i++) {
if (vgmstream->layout_type == layout_interleave_shortblock)
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
vgmstream->interleave_block_size);
else if (vgmstream->layout_type == layout_interleave)
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
else
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
0x1000);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset =
vgmstream->ch[i].offset =
start_offset + i*vgmstream->interleave_block_size;
}
}
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream,streamFile, start_offset) )
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -28,14 +28,14 @@ VGMSTREAM * init_vgmstream_ps3_sgdx(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamHeader = NULL;
off_t start_offset, data_offset;
int32_t data_size;
off_t start_offset, data_offset, chunk_offset;
size_t data_size;
int is_sgx, is_sgb;
int loop_flag, channels, type;
int sample_rate, num_samples, loop_start_sample, loop_end_sample;
int target_stream = 0;
int target_stream = 0, total_streams;
/* check extension, case insensitive */
@ -54,7 +54,7 @@ VGMSTREAM * init_vgmstream_ps3_sgdx(STREAMFILE *streamFile) {
}
/* SGXD chunk (size 0x10) */
/* SGXD base (size 0x10) */
if (read_32bitBE(0x00,streamHeader) != 0x53475844) /* "SGXD" */
goto fail;
/* 0x04 SGX: full header_size; SGD/SGH: unknown header_size (counting from 0x0/0x8/0x10, varies) */
@ -70,24 +70,23 @@ VGMSTREAM * init_vgmstream_ps3_sgdx(STREAMFILE *streamFile) {
/* WAVE chunk (size 0x10 + files * 0x38 + optional padding) */
/* the format reads chunks until header_size, but we only want WAVE in the first position meaning BGM */
if (read_32bitBE(0x10,streamHeader) != 0x57415645) /* "WAVE" */
goto fail;
/* 0x04 SGX: unknown; SGD/SGH: chunk length */
/* 0x08 null */
/* validate multi-streams (usually only SE containers) */
{
int total_streams = read_32bitLE(0x1c,streamHeader);
VGM_ASSERT(total_streams > 1, "SGXD: multiple streams found (%i entries)\n", total_streams);
if (target_stream == 0) target_stream = 1; /* auto: default to 1 */
if (target_stream > total_streams) goto fail;
/* 0x04 SGX: unknown; SGD/SGH: chunk length, 0x08 null */
if (is_sgx) { /* position after chunk+size */
if (read_32bitBE(0x10,streamHeader) != 0x57415645) goto fail; /* "WAVE" */
chunk_offset = 0x18;
} else {
if (!find_chunk_le(streamHeader, 0x57415645,0x10,0, &chunk_offset,NULL)) goto fail; /* "WAVE" */
}
/* check multi-streams (usually only SE containers; Puppeteer) */
total_streams = read_32bitLE(chunk_offset+0x04,streamHeader);
if (target_stream == 0) target_stream = 1;
if (target_stream > total_streams) goto fail;
/* read stream header */
{
off_t chunk_offset, stream_offset;
chunk_offset = 0x10 + 0x10 + 0x38 * (target_stream-1); /* position in target header*/
off_t stream_offset;
chunk_offset += 0x08 + 0x38 * (target_stream-1); /* position in target header*/
/* 0x00 ? (00/01/02) */
/* 0x04 sometimes global offset to wave_name */
@ -122,11 +121,11 @@ VGMSTREAM * init_vgmstream_ps3_sgdx(STREAMFILE *streamFile) {
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->num_samples = num_samples;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->num_streams = total_streams;
vgmstream->meta_type = meta_PS3_SGDX;
switch (type) {

View File

@ -109,7 +109,6 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
/* 0x18: unknown offset */
/* 0x1c: unknown (0x0) */
headers_entries = read_16bit(tables_offset+0x04,streamFile);
VGM_ASSERT(headers_entries > 1, "SCD: multiple streams found (%i entries)\n", headers_entries);
if (target_stream == 0) target_stream = 1; /* auto: default to 1 */
if (target_stream > headers_entries) goto fail;
headers_offset = read_32bit(tables_offset+0x0c,streamFile);
@ -220,6 +219,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bit(meta_offset+8,streamFile);
vgmstream->num_streams = headers_entries;
vgmstream->meta_type = meta_SQEX_SCD;
switch (codec_id) {
case 0x1:
@ -409,8 +410,6 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
goto fail;
}
vgmstream->meta_type = meta_SQEX_SCD;
/* open the file for reading */
if (vgmstream->layout_type != layout_scd_int
#ifdef VGM_USE_FFMPEG

View File

@ -88,7 +88,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
xwb.xact = 1; /* XACT1: XBOX [The King of Fighters 2003] */
} else if (xwb.version < 42) {
xwb.xact = 2; /* XACT2: early XBOX360 [Kameo, Table Tennis, Blue Dragon], Windows */
} else {
} else { /* highest seen: tool=v46, header=v44 */
xwb.xact = 3; /* XACT3: late XBOX360, Windows */
}
@ -118,7 +118,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
xwb.format = read_32bit(off+suboff+0x0c, streamFile); /* compact mode only */
/* suboff+0x10: build time 64b (XACT2/3) */
VGM_ASSERT(xwb.streams > 1, "XWB: multiple streams found (%i entries)\n", xwb.streams);
if (target_stream == 0) target_stream = 1; /* auto: default to 1 */
if (xwb.streams < 1 || target_stream > xwb.streams) goto fail;
@ -155,7 +154,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
if (xwb.xact == 1) { //LoopRegion (bytes within data)
xwb.loop_start = (uint32_t)read_32bit(off+0x10, streamFile);
xwb.loop_end = (uint32_t)read_32bit(off+0x14, streamFile);//length
} else if (xwb.xact == 2) {//LoopRegion (bytes within data) or XMALoopRegion (bits within data)
} else if (xwb.xact == 2 && xwb.version <= 38) {//LoopRegion (bytes within data) or XMALoopRegion (bits within data)
xwb.loop_start = (uint32_t)read_32bit(off+0x10, streamFile);
xwb.loop_end = (uint32_t)read_32bit(off+0x14, streamFile);//length (LoopRegion) or offset (XMALoopRegion)
} else {//LoopRegion (samples)
@ -240,7 +239,8 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
xwb.loop_start_sample = (xwb.loop_start) / block_size / samples_per_frame;
xwb.loop_end_sample = (xwb.loop_start + xwb.loop_end) / block_size / samples_per_frame;
}
else if (xwb.xact == 2 && (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) {
else if (xwb.xact == 2 && xwb.version <= 38 /* v38: byte offset, v40+: sample offset, v39: ? */
&& (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) {
/* need to manually find sample offsets, thanks to Microsoft dumb headers */
xma_sample_data xma_sd;
memset(&xma_sd,0,sizeof(xma_sample_data));
@ -259,9 +259,15 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
xma_get_samples(&xma_sd, streamFile);
xwb.loop_start_sample = xma_sd.loop_start_sample;
xwb.loop_end_sample = xma_sd.loop_end_sample;
// todo fix properly (XWB loop_start/end seem to count padding samples while XMA1 RIFF doesn't)
xwb.loop_start_sample -= 512;
xwb.loop_end_sample -= 512;
//this doesn't seem ok because can fall within 0 to 512 (ie.- first frame)
//if (xwb.loop_start_sample) xwb.loop_start_sample -= 512;
//if (xwb.loop_end_sample) xwb.loop_end_sample -= 512;
//add padding back until it's fixed (affects looping)
// (in rare cases this causes a glitch in FFmpeg since it has a bug where it's missing some samples)
xwb.num_samples += 64 + 512;
}
@ -273,6 +279,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
vgmstream->num_samples = xwb.num_samples;
vgmstream->loop_start_sample = xwb.loop_start_sample;
vgmstream->loop_end_sample = xwb.loop_end_sample;
vgmstream->num_streams = xwb.streams;
vgmstream->meta_type = meta_XWB;
switch(xwb.codec) {

View File

@ -408,6 +408,16 @@ VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile, int do_dfs) {
try_dual_file_stereo(vgmstream, streamFile);
}
#ifdef VGM_USE_FFMPEG
/* check FFmpeg streams here, for lack of a better place */
if (vgmstream->coding_type == coding_FFmpeg) {
ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data;
if (data->streamCount && !vgmstream->num_streams) {
vgmstream->num_streams = data->streamCount;
}
}
#endif
/* save start things so we can restart for seeking */
/* copy the channels */
memcpy(vgmstream->start_ch,vgmstream->ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
@ -1942,6 +1952,12 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
break;
}
concatn(length,desc,temp);
/* only interesting if more than one */
if (vgmstream->num_streams > 1) {
snprintf(temp,TEMPSIZE,"\nnumber of streams: %d",vgmstream->num_streams);
concatn(length,desc,temp);
}
}
/* filename search pairs for dual file stereo */

View File

@ -678,6 +678,7 @@ typedef struct {
coding_t coding_type; /* type of encoding */
layout_t layout_type; /* type of layout for data */
meta_t meta_type; /* how we know the metadata */
int num_streams; /* info only, for a few multi-stream formats (0=not set/one, 1=one stream) */
/* looping */
int loop_flag; /* is this stream looped? */
@ -909,6 +910,7 @@ typedef struct {
int64_t blockAlign; // coded block of bytes, counting channels (the block can be joint stereo)
int64_t frameSize; // decoded samples per block
int64_t skipSamples; // number of start samples that will be skipped (encoder delay), for looping adjustments
int streamCount; // number of FFmpeg audio streams
/*** internal state ***/
// Intermediate byte buffer

View File

@ -257,6 +257,11 @@ int main(int argc, char ** argv) {
}
buf = malloc(BUFSIZE*sizeof(sample)*s->channels);
if (!buf) {
fprintf(stderr,"failed allocating output buffer\n");
close_vgmstream(s);
return 1;
}
len = get_vgmstream_play_samples(loop_count,fade_seconds,fade_delay_seconds,s);
if (!play && !adxencd && !oggenc && !batchvar) printf("samples to play: %d (%.4lf seconds)\n",len,(double)len/s->sample_rate);