2008-06-09 02:20:08 +02:00
|
|
|
#include "meta.h"
|
2010-09-11 20:28:43 +02:00
|
|
|
#include "../coding/coding.h"
|
2008-06-10 03:20:54 +02:00
|
|
|
#include "../layout/layout.h"
|
2008-06-09 02:20:08 +02:00
|
|
|
#include "../util.h"
|
|
|
|
|
2017-03-09 16:53:34 +01:00
|
|
|
/* known GENH types */
|
|
|
|
typedef enum {
|
|
|
|
PSX = 0, /* PSX ADPCM */
|
|
|
|
XBOX = 1, /* XBOX IMA ADPCM */
|
|
|
|
NGC_DTK = 2, /* NGC ADP/DTK ADPCM */
|
|
|
|
PCM16BE = 3, /* 16bit big endian PCM */
|
|
|
|
PCM16LE = 4, /* 16bit little endian PCM */
|
|
|
|
PCM8 = 5, /* 8bit PCM */
|
|
|
|
SDX2 = 6, /* SDX2 (3D0 games) */
|
|
|
|
DVI_IMA = 7, /* DVI IMA ADPCM */
|
|
|
|
MPEG = 8, /* MPEG (MP3) */
|
|
|
|
IMA = 9, /* IMA ADPCM */
|
|
|
|
AICA = 10, /* AICA ADPCM (dreamcast) */
|
|
|
|
MSADPCM = 11, /* MS ADPCM (windows) */
|
|
|
|
NGC_DSP = 12, /* NGC DSP (GC) */
|
|
|
|
PCM8_U_int = 13, /* 8bit unsigned PCM (interleaved) */
|
|
|
|
PSX_bf = 14, /* PSX ADPCM bad flagged */
|
|
|
|
MS_IMA = 15, /* Microsoft IMA ADPCM */
|
|
|
|
PCM8_U = 16, /* 8bit unsigned PCM */
|
|
|
|
APPLE_IMA4 = 17, /* Apple Quicktime 4-bit IMA ADPCM */
|
2017-03-09 19:33:31 +01:00
|
|
|
ATRAC3 = 18, /* raw ATRAC3 */
|
|
|
|
ATRAC3PLUS = 19, /* raw ATRAC3PLUS */
|
|
|
|
XMA1 = 20, /* raw XMA1 */
|
|
|
|
XMA2 = 21, /* raw XMA2 */
|
|
|
|
FFMPEG = 22, /* any headered FFmpeg format */
|
2017-03-09 16:53:34 +01:00
|
|
|
} genh_type;
|
2008-06-09 02:20:08 +02:00
|
|
|
|
2017-03-09 16:53:34 +01:00
|
|
|
/* GENH is an artificial "generic" header for headerless streams */
|
2008-06-10 03:20:54 +02:00
|
|
|
VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
2008-12-24 01:00:10 +01:00
|
|
|
VGMSTREAM * vgmstream = NULL;
|
2008-06-09 02:20:08 +02:00
|
|
|
|
2017-03-09 16:53:34 +01:00
|
|
|
int channel_count, loop_flag, sample_rate, interleave;
|
2017-03-09 19:33:31 +01:00
|
|
|
int32_t num_samples = 0, loop_start, loop_end, skip_samples = 0;
|
2017-03-09 16:53:34 +01:00
|
|
|
int32_t start_offset, header_size;
|
2017-03-09 19:33:31 +01:00
|
|
|
off_t datasize = 0;
|
|
|
|
|
2008-12-24 01:00:10 +01:00
|
|
|
int32_t coef[2];
|
|
|
|
int32_t coef_splitted[2];
|
|
|
|
int32_t dsp_interleave_type;
|
|
|
|
int32_t coef_type;
|
2017-03-09 19:33:31 +01:00
|
|
|
int skip_samples_mode, atrac3_mode, xma_mode;
|
2017-03-09 16:53:34 +01:00
|
|
|
int i, j;
|
2008-12-23 19:01:18 +01:00
|
|
|
|
2017-03-09 16:53:34 +01:00
|
|
|
coding_t coding;
|
|
|
|
genh_type type;
|
2008-06-09 02:20:08 +02:00
|
|
|
|
|
|
|
/* check extension, case insensitive */
|
2017-03-09 16:53:34 +01:00
|
|
|
if (!check_extensions(streamFile,"genh")) goto fail;
|
2008-06-09 02:20:08 +02:00
|
|
|
|
|
|
|
/* check header magic */
|
|
|
|
if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail;
|
|
|
|
|
2008-06-13 01:50:45 +02:00
|
|
|
channel_count = read_32bitLE(0x4,streamFile);
|
|
|
|
if (channel_count < 1) goto fail;
|
|
|
|
|
2017-03-09 16:53:34 +01:00
|
|
|
type = read_32bitLE(0x18,streamFile);
|
|
|
|
/* type to coding conversion */
|
|
|
|
switch (type) {
|
|
|
|
case PSX: coding = coding_PSX; break;
|
|
|
|
case XBOX: coding = coding_XBOX; break;
|
|
|
|
case NGC_DTK: coding = coding_NGC_DTK; break;
|
|
|
|
case PCM16BE: coding = coding_PCM16BE; break;
|
|
|
|
case PCM16LE: coding = coding_PCM16LE; break;
|
|
|
|
case PCM8: coding = coding_PCM8; break;
|
|
|
|
case SDX2: coding = coding_SDX2; break;
|
|
|
|
case DVI_IMA: coding = coding_DVI_IMA; break;
|
2008-07-06 17:33:38 +02:00
|
|
|
#ifdef VGM_USE_MPEG
|
2017-03-09 16:53:34 +01:00
|
|
|
case MPEG: coding = coding_MPEG1_L3; break; /* we later find out exactly which */
|
2008-07-06 17:33:38 +02:00
|
|
|
#endif
|
2017-03-09 16:53:34 +01:00
|
|
|
case IMA: coding = coding_IMA; break;
|
|
|
|
case AICA: coding = coding_AICA; break;
|
|
|
|
case MSADPCM: coding = coding_MSADPCM; break;
|
|
|
|
case NGC_DSP: coding = coding_NGC_DSP; break;
|
|
|
|
case PCM8_U_int: coding = coding_PCM8_U_int; break;
|
|
|
|
case PSX_bf: coding = coding_PSX_badflags; break;
|
|
|
|
case MS_IMA: coding = coding_MS_IMA; break;
|
|
|
|
case PCM8_U: coding = coding_PCM8_U; break;
|
|
|
|
case APPLE_IMA4: coding = coding_APPLE_IMA4; break;
|
2017-03-09 19:33:31 +01:00
|
|
|
#ifdef VGM_USE_FFMPEG
|
|
|
|
case ATRAC3:
|
|
|
|
case ATRAC3PLUS:
|
|
|
|
case XMA1:
|
|
|
|
case XMA2:
|
|
|
|
case FFMPEG: coding = coding_FFmpeg; break;
|
|
|
|
#endif
|
2008-06-10 03:20:54 +02:00
|
|
|
default:
|
|
|
|
goto fail;
|
|
|
|
}
|
2008-06-09 02:20:08 +02:00
|
|
|
|
2008-11-17 19:28:14 +01:00
|
|
|
start_offset = read_32bitLE(0x1C,streamFile);
|
2008-06-13 01:50:45 +02:00
|
|
|
header_size = read_32bitLE(0x20,streamFile);
|
2008-06-13 01:33:07 +02:00
|
|
|
|
|
|
|
/* HACK to support old genh */
|
|
|
|
if (header_size == 0) {
|
|
|
|
start_offset = 0x800;
|
|
|
|
header_size = 0x800;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check for audio data start past header end */
|
|
|
|
if (header_size > start_offset) goto fail;
|
|
|
|
|
2008-06-09 02:20:08 +02:00
|
|
|
interleave = read_32bitLE(0x8,streamFile);
|
|
|
|
sample_rate = read_32bitLE(0xc,streamFile);
|
|
|
|
loop_start = read_32bitLE(0x10,streamFile);
|
|
|
|
loop_end = read_32bitLE(0x14,streamFile);
|
2008-12-24 01:00:10 +01:00
|
|
|
|
|
|
|
coef[0] = read_32bitLE(0x24,streamFile);
|
|
|
|
coef[1] = read_32bitLE(0x28,streamFile);
|
|
|
|
dsp_interleave_type = read_32bitLE(0x2C,streamFile);
|
Extend GENH to support little-endian "Gamecube" DSP ADPCM coefficients, for some 3DS titles.
This involves a reinterpretation of byte 0x30 (coef type). Formerly this byte took on only two values, to indicate how the ADPCM coefficients (aka codebook) were stored:
0 - normal coefs: all 16 coefs interleaved into one array, offset given at 0x24 for left, 0x28 for right
1 - split coefs: 8 coefs in the main array, additional offset to 2nd array given at 0x34 for left, 0x38 for right
Now I am considering this to be indicated only by bit 0 of the coef type. Bit 1 is taking on an additional interpretation, if it is set, we consider the coefficients to be little endian rather than the normal big endian.
This should maintain backwards compatibility with old GENH files, which should have only used the value 0 or 1.
Thus, in effect we have:
0: normal, big endian
1: split, big endian
2: normal, little endian
3: split, little endian
I don't know of any situation in which 3 would be used (yet), but I'm sure devs will continue to surprise me.
2014-06-27 05:53:49 +02:00
|
|
|
|
|
|
|
/* DSP coefficient variants */
|
|
|
|
/* bit 0 - split coefs (2 arrays) */
|
|
|
|
/* bit 1 - little endian coefs */
|
|
|
|
coef_type = read_32bitLE(0x30,streamFile);
|
|
|
|
/* when using split coefficients, 2nd array is at: */
|
2008-12-24 01:00:10 +01:00
|
|
|
coef_splitted[0] = read_32bitLE(0x34,streamFile);
|
|
|
|
coef_splitted[1] = read_32bitLE(0x38,streamFile);
|
Extend GENH to support little-endian "Gamecube" DSP ADPCM coefficients, for some 3DS titles.
This involves a reinterpretation of byte 0x30 (coef type). Formerly this byte took on only two values, to indicate how the ADPCM coefficients (aka codebook) were stored:
0 - normal coefs: all 16 coefs interleaved into one array, offset given at 0x24 for left, 0x28 for right
1 - split coefs: 8 coefs in the main array, additional offset to 2nd array given at 0x34 for left, 0x38 for right
Now I am considering this to be indicated only by bit 0 of the coef type. Bit 1 is taking on an additional interpretation, if it is set, we consider the coefficients to be little endian rather than the normal big endian.
This should maintain backwards compatibility with old GENH files, which should have only used the value 0 or 1.
Thus, in effect we have:
0: normal, big endian
1: split, big endian
2: normal, little endian
3: split, little endian
I don't know of any situation in which 3 would be used (yet), but I'm sure devs will continue to surprise me.
2014-06-27 05:53:49 +02:00
|
|
|
|
2017-03-09 19:33:31 +01:00
|
|
|
/* other fields */
|
|
|
|
num_samples = read_32bitLE(0x40,streamFile);
|
|
|
|
skip_samples = read_32bitLE(0x44,streamFile); /* for FFmpeg based codecs */
|
|
|
|
skip_samples_mode = read_8bit(0x48,streamFile); /* 0=autodetect, 1=force manual value @ 0x44 */
|
|
|
|
atrac3_mode = read_8bit(0x49,streamFile); /* 0=autodetect, 1=force joint stereo, 2=force full stereo */
|
|
|
|
xma_mode = read_8bit(0x4a,streamFile); /* 0=default (4ch = 2ch + 2ch), 1=single (4ch = 1ch + 1ch + 1ch + 1ch) */
|
|
|
|
datasize = read_32bitLE(0x50,streamFile);
|
|
|
|
if (!datasize)
|
|
|
|
datasize = get_streamfile_size(streamFile)-start_offset;
|
|
|
|
|
2017-03-09 16:53:34 +01:00
|
|
|
num_samples = num_samples > 0 ? num_samples : loop_end;
|
|
|
|
loop_flag = loop_start != -1;
|
|
|
|
|
2008-06-10 03:20:54 +02:00
|
|
|
|
2008-06-09 02:20:08 +02:00
|
|
|
/* build the VGMSTREAM */
|
2017-03-09 16:53:34 +01:00
|
|
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
2008-06-09 02:20:08 +02:00
|
|
|
if (!vgmstream) goto fail;
|
|
|
|
|
|
|
|
vgmstream->sample_rate = sample_rate;
|
2017-03-09 16:53:34 +01:00
|
|
|
vgmstream->num_samples = num_samples;
|
2008-06-09 02:20:08 +02:00
|
|
|
vgmstream->loop_start_sample = loop_start;
|
|
|
|
vgmstream->loop_end_sample = loop_end;
|
|
|
|
|
2017-03-09 16:53:34 +01:00
|
|
|
/* codec specific */
|
2008-06-10 03:20:54 +02:00
|
|
|
switch (coding) {
|
2008-11-24 19:27:28 +01:00
|
|
|
case coding_PCM8_U_int:
|
2008-12-24 01:00:10 +01:00
|
|
|
vgmstream->layout_type=layout_none;
|
|
|
|
break;
|
|
|
|
case coding_PCM16LE:
|
2008-06-18 12:40:35 +02:00
|
|
|
case coding_PCM16BE:
|
2008-07-01 05:19:02 +02:00
|
|
|
case coding_PCM8:
|
2009-04-28 18:52:49 +02:00
|
|
|
case coding_PCM8_U:
|
2008-07-01 18:10:18 +02:00
|
|
|
case coding_SDX2:
|
2008-06-10 03:20:54 +02:00
|
|
|
case coding_PSX:
|
2008-12-24 01:00:10 +01:00
|
|
|
case coding_PSX_badflags:
|
2008-07-02 03:41:20 +02:00
|
|
|
case coding_DVI_IMA:
|
2008-07-18 07:25:05 +02:00
|
|
|
case coding_IMA:
|
2008-08-15 04:21:19 +02:00
|
|
|
case coding_AICA:
|
2017-03-09 16:53:34 +01:00
|
|
|
case coding_APPLE_IMA4:
|
2008-06-10 03:20:54 +02:00
|
|
|
vgmstream->interleave_block_size = interleave;
|
|
|
|
if (channel_count > 1)
|
|
|
|
{
|
2008-07-14 22:42:49 +02:00
|
|
|
if (coding == coding_SDX2) {
|
|
|
|
coding = coding_SDX2_int;
|
|
|
|
}
|
2017-04-29 20:28:14 +02:00
|
|
|
|
|
|
|
if (vgmstream->interleave_block_size==0xffffffff) {
|
|
|
|
vgmstream->layout_type = layout_none;
|
|
|
|
}
|
2008-12-24 01:00:10 +01:00
|
|
|
else {
|
|
|
|
vgmstream->layout_type = layout_interleave;
|
2017-04-29 20:28:14 +02:00
|
|
|
if (coding == coding_DVI_IMA)
|
|
|
|
coding = coding_DVI_IMA_int;
|
|
|
|
if (coding == coding_IMA)
|
|
|
|
coding = coding_IMA_int;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* to avoid endless loops */
|
|
|
|
if (!interleave && (
|
|
|
|
coding == coding_PSX ||
|
|
|
|
coding == coding_PSX_badflags ||
|
|
|
|
coding == coding_IMA_int ||
|
|
|
|
coding == coding_DVI_IMA_int ||
|
|
|
|
coding == coding_SDX2_int) ) {
|
|
|
|
goto fail;
|
2008-12-24 01:00:10 +01:00
|
|
|
}
|
2008-06-10 03:20:54 +02:00
|
|
|
} else {
|
|
|
|
vgmstream->layout_type = layout_none;
|
|
|
|
}
|
2017-03-09 16:53:34 +01:00
|
|
|
|
|
|
|
/* setup adpcm */
|
|
|
|
if (coding == coding_AICA) {
|
|
|
|
int i;
|
|
|
|
for (i=0;i<channel_count;i++) {
|
|
|
|
vgmstream->ch[i].adpcm_step_index = 0x7f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-10 03:20:54 +02:00
|
|
|
break;
|
2009-03-09 13:48:53 +01:00
|
|
|
case coding_MS_IMA:
|
2017-04-29 20:28:14 +02:00
|
|
|
if (!interleave) goto fail; /* creates garbage */
|
|
|
|
|
2009-03-09 13:48:53 +01:00
|
|
|
vgmstream->interleave_block_size = interleave;
|
|
|
|
vgmstream->layout_type = layout_none;
|
|
|
|
break;
|
2008-08-18 01:21:12 +02:00
|
|
|
case coding_MSADPCM:
|
2017-04-29 20:28:14 +02:00
|
|
|
if (channel_count > 2) goto fail;
|
|
|
|
if (!interleave) goto fail; /* creates garbage */
|
|
|
|
|
2008-08-18 01:21:12 +02:00
|
|
|
vgmstream->interleave_block_size = interleave;
|
|
|
|
vgmstream->layout_type = layout_none;
|
|
|
|
break;
|
2008-06-10 03:20:54 +02:00
|
|
|
case coding_XBOX:
|
2008-08-10 22:08:03 +02:00
|
|
|
vgmstream->layout_type = layout_none;
|
2008-06-13 01:33:07 +02:00
|
|
|
break;
|
|
|
|
case coding_NGC_DTK:
|
2017-03-09 16:53:34 +01:00
|
|
|
if (channel_count != 2) goto fail;
|
2017-01-08 01:09:20 +01:00
|
|
|
vgmstream->layout_type = layout_none;
|
2008-06-10 03:20:54 +02:00
|
|
|
break;
|
2008-11-17 19:28:14 +01:00
|
|
|
case coding_NGC_DSP:
|
2008-12-24 01:00:10 +01:00
|
|
|
if (dsp_interleave_type == 0) {
|
2017-04-29 20:28:14 +02:00
|
|
|
if (!interleave) goto fail;
|
2008-12-24 01:00:10 +01:00
|
|
|
vgmstream->layout_type = layout_interleave;
|
|
|
|
vgmstream->interleave_block_size = interleave;
|
|
|
|
} else if (dsp_interleave_type == 1) {
|
2017-04-29 20:28:14 +02:00
|
|
|
if (!interleave) goto fail;
|
2008-12-24 01:00:10 +01:00
|
|
|
vgmstream->layout_type = layout_interleave_byte;
|
|
|
|
vgmstream->interleave_block_size = interleave;
|
|
|
|
} else if (dsp_interleave_type == 2) {
|
|
|
|
vgmstream->layout_type = layout_none;
|
|
|
|
}
|
2017-03-09 16:53:34 +01:00
|
|
|
|
|
|
|
/* get coefs */
|
|
|
|
for (i=0;i<channel_count;i++) {
|
|
|
|
int16_t (*read_16bit)(off_t , STREAMFILE*);
|
|
|
|
/* bit 1 - little endian coefs */
|
|
|
|
if ((coef_type & 2) == 0) {
|
|
|
|
read_16bit = read_16bitBE;
|
|
|
|
} else {
|
|
|
|
read_16bit = read_16bitLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* bit 0 - split coefs (2 arrays) */
|
|
|
|
if ((coef_type & 1) == 0) {
|
|
|
|
for (j=0;j<16;j++) {
|
|
|
|
vgmstream->ch[i].adpcm_coef[j] = read_16bit(coef[i]+j*2,streamFile);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (j=0;j<8;j++) {
|
|
|
|
vgmstream->ch[i].adpcm_coef[j*2]=read_16bit(coef[i]+j*2,streamFile);
|
|
|
|
vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bit(coef_splitted[i]+j*2,streamFile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-24 01:00:10 +01:00
|
|
|
break;
|
2008-07-06 17:33:38 +02:00
|
|
|
#ifdef VGM_USE_MPEG
|
|
|
|
case coding_MPEG1_L3:
|
|
|
|
vgmstream->layout_type = layout_mpeg;
|
2017-03-09 16:53:34 +01:00
|
|
|
vgmstream->codec_data = init_mpeg_codec_data(streamFile, start_offset, &coding, vgmstream->channels);
|
|
|
|
if (!vgmstream->codec_data) goto fail;
|
|
|
|
|
2008-07-06 17:33:38 +02:00
|
|
|
break;
|
2017-03-09 19:33:31 +01:00
|
|
|
#endif
|
|
|
|
#ifdef VGM_USE_FFMPEG
|
|
|
|
case coding_FFmpeg: {
|
|
|
|
ffmpeg_codec_data *ffmpeg_data = NULL;
|
|
|
|
|
|
|
|
if (type == FFMPEG) {
|
|
|
|
/* default FFmpeg */
|
|
|
|
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,datasize);
|
|
|
|
if ( !ffmpeg_data ) goto fail;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* fake header FFmpeg */
|
|
|
|
uint8_t buf[200];
|
|
|
|
int32_t bytes;
|
|
|
|
|
|
|
|
if (type == ATRAC3) {
|
|
|
|
int block_size = interleave;
|
|
|
|
int joint_stereo;
|
|
|
|
switch(atrac3_mode) {
|
|
|
|
case 0: joint_stereo = vgmstream->channels > 1 && interleave/vgmstream->channels==0x60 ? 1 : 0; break; /* autodetect */
|
|
|
|
case 1: joint_stereo = 1; break; /* force joint stereo */
|
|
|
|
case 2: joint_stereo = 0; break; /* force stereo */
|
|
|
|
default: goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, skip_samples);
|
|
|
|
}
|
|
|
|
else if (type == ATRAC3PLUS) {
|
|
|
|
int block_size = interleave;
|
|
|
|
|
|
|
|
bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, skip_samples);
|
|
|
|
}
|
|
|
|
else if (type == XMA1) {
|
|
|
|
int xma_stream_mode = xma_mode == 1 ? 1 : 0;
|
|
|
|
|
|
|
|
bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
|
|
|
|
}
|
|
|
|
else if (type == XMA2) {
|
|
|
|
int block_size = interleave ? interleave : 2048;
|
|
|
|
int block_count = datasize / block_size;
|
|
|
|
|
|
|
|
bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
if (bytes <= 0) goto fail;
|
|
|
|
|
|
|
|
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
|
|
|
|
if ( !ffmpeg_data ) goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
vgmstream->codec_data = ffmpeg_data;
|
|
|
|
vgmstream->layout_type = layout_none;
|
|
|
|
|
|
|
|
/* force encoder delay */
|
2017-03-24 16:39:57 +01:00
|
|
|
if (skip_samples_mode && skip_samples >= 0) {
|
2017-03-09 19:33:31 +01:00
|
|
|
ffmpeg_set_skip_samples(ffmpeg_data, skip_samples);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2008-07-06 17:33:38 +02:00
|
|
|
#endif
|
2017-03-09 16:53:34 +01:00
|
|
|
default:
|
|
|
|
break;
|
2008-06-09 12:26:17 +02:00
|
|
|
}
|
2017-03-09 16:53:34 +01:00
|
|
|
|
2008-12-24 01:00:10 +01:00
|
|
|
vgmstream->coding_type = coding;
|
|
|
|
vgmstream->meta_type = meta_GENH;
|
2008-06-13 01:33:07 +02:00
|
|
|
|
|
|
|
|
2017-03-09 16:53:34 +01:00
|
|
|
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) )
|
|
|
|
goto fail;
|
2008-07-06 17:33:38 +02:00
|
|
|
|
2008-06-09 02:20:08 +02:00
|
|
|
return vgmstream;
|
|
|
|
|
|
|
|
fail:
|
2017-03-09 16:53:34 +01:00
|
|
|
close_vgmstream(vgmstream);
|
2008-06-09 02:20:08 +02:00
|
|
|
return NULL;
|
|
|
|
}
|