mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 01:30:49 +01:00
cleanup: misc doc/fixes
This commit is contained in:
parent
5f5eacd824
commit
6805937d1b
@ -442,6 +442,7 @@ bool VgmstreamPlugin::play(const char * filename, VFSFile & file) {
|
|||||||
render_vgmstream(buffer, to_do, vgmstream);
|
render_vgmstream(buffer, to_do, vgmstream);
|
||||||
|
|
||||||
write_audio(buffer, to_do * sizeof(short) * output_channels);
|
write_audio(buffer, to_do * sizeof(short) * output_channels);
|
||||||
|
//TODO: detect how many written
|
||||||
decode_pos_samples += to_do;
|
decode_pos_samples += to_do;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -901,7 +901,7 @@ static int write_file(VGMSTREAM* vgmstream, cli_config* cfg) {
|
|||||||
|
|
||||||
render_vgmstream(buf, to_get, vgmstream);
|
render_vgmstream(buf, to_get, vgmstream);
|
||||||
|
|
||||||
swap_samples_le(buf, channels * to_get); /* write PC endian */
|
swap_samples_le(buf, channels * to_get); /* change to WAV (LE) endian if PC is Big Endian */
|
||||||
fwrite(buf, sizeof(sample_t), to_get * channels, outfile);
|
fwrite(buf, sizeof(sample_t), to_get * channels, outfile);
|
||||||
/* should write infinitely until program kill */
|
/* should write infinitely until program kill */
|
||||||
}
|
}
|
||||||
@ -929,7 +929,7 @@ static int write_file(VGMSTREAM* vgmstream, cli_config* cfg) {
|
|||||||
render_vgmstream(buf, to_get, vgmstream);
|
render_vgmstream(buf, to_get, vgmstream);
|
||||||
|
|
||||||
if (!cfg->decode_only) {
|
if (!cfg->decode_only) {
|
||||||
swap_samples_le(buf, channels * to_get); /* write PC endian */
|
swap_samples_le(buf, channels * to_get); /* change to WAV (LE) endian if PC is Big Endian */
|
||||||
fwrite(buf, sizeof(sample_t), to_get * channels, outfile);
|
fwrite(buf, sizeof(sample_t), to_get * channels, outfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,26 +4,26 @@
|
|||||||
|
|
||||||
/* Must pass at least 8 bytes of data to this function.
|
/* Must pass at least 8 bytes of data to this function.
|
||||||
* Returns <0 on non-match, or header size on success. */
|
* Returns <0 on non-match, or header size on success. */
|
||||||
int clHCA_isOurFile(const void *data, unsigned int size);
|
int clHCA_isOurFile(const void* data, unsigned int size);
|
||||||
|
|
||||||
/* The opaque state structure. */
|
/* The opaque state structure. */
|
||||||
typedef struct clHCA clHCA;
|
typedef struct clHCA clHCA;
|
||||||
|
|
||||||
/* In case you wish to allocate and reset the structure on your own. */
|
/* In case you wish to allocate and reset the structure on your own. */
|
||||||
int clHCA_sizeof(void);
|
int clHCA_sizeof(void);
|
||||||
void clHCA_clear(clHCA *);
|
void clHCA_clear(clHCA* hca);
|
||||||
void clHCA_done(clHCA *);
|
void clHCA_done(clHCA* hca);
|
||||||
|
|
||||||
/* Or you could let the library allocate it. */
|
/* Or you could let the library allocate it. */
|
||||||
clHCA * clHCA_new(void);
|
clHCA* clHCA_new(void);
|
||||||
void clHCA_delete(clHCA *);
|
void clHCA_delete(clHCA* hca);
|
||||||
|
|
||||||
/* Parses the HCA header. Must be called before any decoding may be performed,
|
/* Parses the HCA header. Must be called before any decoding may be performed,
|
||||||
* and size must be at least headerSize long. The recommended way is to detect
|
* and size must be at least headerSize long. The recommended way is to detect
|
||||||
* the header length with clHCA_isOurFile, then read data and call this.
|
* the header length with clHCA_isOurFile, then read data and call this.
|
||||||
* May be called multiple times to reset decoder state.
|
* May be called multiple times to reset decoder state.
|
||||||
* Returns 0 on success, <0 on failure. */
|
* Returns 0 on success, <0 on failure. */
|
||||||
int clHCA_DecodeHeader(clHCA *, const void *data, unsigned int size);
|
int clHCA_DecodeHeader(clHCA* hca, const void* data, unsigned int size);
|
||||||
|
|
||||||
typedef struct clHCA_stInfo {
|
typedef struct clHCA_stInfo {
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
@ -40,7 +40,7 @@ typedef struct clHCA_stInfo {
|
|||||||
unsigned int loopStartDelay; /* samples in block before loop starts */
|
unsigned int loopStartDelay; /* samples in block before loop starts */
|
||||||
unsigned int loopEndPadding; /* samples in block after loop ends */
|
unsigned int loopEndPadding; /* samples in block after loop ends */
|
||||||
unsigned int samplesPerBlock; /* should be 1024 */
|
unsigned int samplesPerBlock; /* should be 1024 */
|
||||||
const char *comment;
|
const char* comment;
|
||||||
unsigned int encryptionEnabled; /* requires keycode */
|
unsigned int encryptionEnabled; /* requires keycode */
|
||||||
|
|
||||||
/* Derived sample formulas:
|
/* Derived sample formulas:
|
||||||
@ -53,33 +53,33 @@ typedef struct clHCA_stInfo {
|
|||||||
/* Retrieves header information for decoding and playback (it's the caller's responsability
|
/* Retrieves header information for decoding and playback (it's the caller's responsability
|
||||||
* to apply looping, encoder delay/skip samples, etc). May be called after clHCA_DecodeHeader.
|
* to apply looping, encoder delay/skip samples, etc). May be called after clHCA_DecodeHeader.
|
||||||
* Returns 0 on success, <0 on failure. */
|
* Returns 0 on success, <0 on failure. */
|
||||||
int clHCA_getInfo(clHCA *, clHCA_stInfo *out);
|
int clHCA_getInfo(clHCA* hca, clHCA_stInfo* out);
|
||||||
|
|
||||||
/* Decodes a single frame, from data after headerSize. Should be called after
|
/* Decodes a single frame, from data after headerSize. Should be called after
|
||||||
* clHCA_DecodeHeader and size must be at least blockSize long.
|
* clHCA_DecodeHeader and size must be at least blockSize long.
|
||||||
* Data may be modified if encrypted.
|
* Data may be modified if encrypted.
|
||||||
* Returns 0 on success, <0 on failure. */
|
* Returns 0 on success, <0 on failure. */
|
||||||
int clHCA_DecodeBlock(clHCA *, void *data, unsigned int size);
|
int clHCA_DecodeBlock(clHCA* hca, void* data, unsigned int size);
|
||||||
|
|
||||||
/* Extracts signed and clipped 16 bit samples into sample buffer.
|
/* Extracts signed and clipped 16 bit samples into sample buffer.
|
||||||
* May be called after clHCA_DecodeBlock, and will return the same data until
|
* May be called after clHCA_DecodeBlock, and will return the same data until
|
||||||
* next decode. Buffer must be at least (samplesPerBlock*channels) long. */
|
* next decode. Buffer must be at least (samplesPerBlock*channels) long. */
|
||||||
void clHCA_ReadSamples16(clHCA *, signed short * outSamples);
|
void clHCA_ReadSamples16(clHCA* hca, short* outSamples);
|
||||||
|
|
||||||
/* Sets a 64 bit encryption key, to properly decode blocks. This may be called
|
/* Sets a 64 bit encryption key, to properly decode blocks. This may be called
|
||||||
* multiple times to change the key, before or after clHCA_DecodeHeader.
|
* multiple times to change the key, before or after clHCA_DecodeHeader.
|
||||||
* Key is ignored if the file is not encrypted. */
|
* Key is ignored if the file is not encrypted. */
|
||||||
void clHCA_SetKey(clHCA *, unsigned long long keycode);
|
void clHCA_SetKey(clHCA* hca, unsigned long long keycode);
|
||||||
|
|
||||||
/* Tests a single frame for validity, mainly to test if current key is correct.
|
/* Tests a single frame for validity, mainly to test if current key is correct.
|
||||||
* Returns <0 on incorrect block (wrong key), 0 on silent block (not useful to determine)
|
* Returns <0 on incorrect block (wrong key), 0 on silent block (not useful to determine)
|
||||||
* and >0 if block is correct (the closer to 1 the more likely).
|
* and >0 if block is correct (the closer to 1 the more likely).
|
||||||
* Incorrect keys may give a few valid frames, so it's best to test a number of them
|
* Incorrect keys may give a few valid frames, so it's best to test a number of them
|
||||||
* and select the key with scores closer to 1. */
|
* and select the key with scores closer to 1. */
|
||||||
int clHCA_TestBlock(clHCA *hca, void *data, unsigned int size);
|
int clHCA_TestBlock(clHCA* hca, void* data, unsigned int size);
|
||||||
|
|
||||||
/* Resets the internal decode state, used when restarting to decode the file from the beginning.
|
/* Resets the internal decode state, used when restarting to decode the file from the beginning.
|
||||||
* Without it there are minor differences, mainly useful when testing a new key. */
|
* Without it there are minor differences, mainly useful when testing a new key. */
|
||||||
void clHCA_DecodeReset(clHCA * hca);
|
void clHCA_DecodeReset(clHCA* hca);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -734,12 +734,18 @@ static const char* common_extension_list[] = {
|
|||||||
|
|
||||||
|
|
||||||
/* List supported formats and return elements in the list, for plugins that need to know. */
|
/* List supported formats and return elements in the list, for plugins that need to know. */
|
||||||
const char ** vgmstream_get_formats(size_t * size) {
|
const char** vgmstream_get_formats(size_t* size) {
|
||||||
|
if (!size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
*size = sizeof(extension_list) / sizeof(char*);
|
*size = sizeof(extension_list) / sizeof(char*);
|
||||||
return extension_list;
|
return extension_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char ** vgmstream_get_common_formats(size_t * size) {
|
const char** vgmstream_get_common_formats(size_t* size) {
|
||||||
|
if (!size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
*size = sizeof(common_extension_list) / sizeof(char*);
|
*size = sizeof(common_extension_list) / sizeof(char*);
|
||||||
return common_extension_list;
|
return common_extension_list;
|
||||||
}
|
}
|
||||||
@ -766,18 +772,18 @@ typedef struct {
|
|||||||
static const coding_info coding_info_list[] = {
|
static const coding_info coding_info_list[] = {
|
||||||
{coding_SILENCE, "Silence"},
|
{coding_SILENCE, "Silence"},
|
||||||
|
|
||||||
{coding_PCM16LE, "Little Endian 16-bit PCM"},
|
{coding_PCM16LE, "16-bit Little Endian PCM"},
|
||||||
{coding_PCM16BE, "Big Endian 16-bit PCM"},
|
{coding_PCM16BE, "16-bit Big Endian PCM"},
|
||||||
{coding_PCM16_int, "16-bit PCM with 2 byte interleave (block)"},
|
{coding_PCM16_int, "16-bit PCM (block)"},
|
||||||
{coding_PCM8, "8-bit signed PCM"},
|
{coding_PCM8, "8-bit signed PCM"},
|
||||||
{coding_PCM8_int, "8-bit signed PCM with 1 byte interleave (block)"},
|
{coding_PCM8_int, "8-bit signed PCM (block)"},
|
||||||
{coding_PCM8_U, "8-bit unsigned PCM"},
|
{coding_PCM8_U, "8-bit unsigned PCM"},
|
||||||
{coding_PCM8_U_int, "8-bit unsigned PCM with 1 byte interleave (block)"},
|
{coding_PCM8_U_int, "8-bit unsigned PCM (block)"},
|
||||||
{coding_PCM8_SB, "8-bit PCM with sign bit"},
|
{coding_PCM8_SB, "8-bit sign bit PCM"},
|
||||||
{coding_PCM4, "4-bit signed PCM"},
|
{coding_PCM4, "4-bit signed PCM"},
|
||||||
{coding_PCM4_U, "4-bit unsigned PCM"},
|
{coding_PCM4_U, "4-bit unsigned PCM"},
|
||||||
{coding_ULAW, "8-bit u-Law"},
|
{coding_ULAW, "8-bit u-Law"},
|
||||||
{coding_ULAW_int, "8-bit u-Law with 1 byte interleave (block)"},
|
{coding_ULAW_int, "8-bit u-Law (block)"},
|
||||||
{coding_ALAW, "8-bit a-Law"},
|
{coding_ALAW, "8-bit a-Law"},
|
||||||
{coding_PCMFLOAT, "32-bit float PCM"},
|
{coding_PCMFLOAT, "32-bit float PCM"},
|
||||||
{coding_PCM24LE, "24-bit Little Endian PCM"},
|
{coding_PCM24LE, "24-bit Little Endian PCM"},
|
||||||
@ -876,9 +882,9 @@ static const coding_info coding_info_list[] = {
|
|||||||
{coding_COMPRESSWAVE, "CompressWave Huffman ADPCM"},
|
{coding_COMPRESSWAVE, "CompressWave Huffman ADPCM"},
|
||||||
|
|
||||||
{coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"},
|
{coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"},
|
||||||
{coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"},
|
{coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM (block)"},
|
||||||
{coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"},
|
{coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"},
|
||||||
{coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"},
|
{coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM (block)"},
|
||||||
{coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"},
|
{coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"},
|
||||||
{coding_DERF, "Xilam DERF 8-bit DPCM"},
|
{coding_DERF, "Xilam DERF 8-bit DPCM"},
|
||||||
{coding_WADY, "Marble WADY 8-bit DPCM"},
|
{coding_WADY, "Marble WADY 8-bit DPCM"},
|
||||||
@ -1010,7 +1016,7 @@ static const meta_info meta_info_list[] = {
|
|||||||
{meta_XA, "Sony XA header"},
|
{meta_XA, "Sony XA header"},
|
||||||
{meta_RXWS, "Sony RXWS header"},
|
{meta_RXWS, "Sony RXWS header"},
|
||||||
{meta_RAW_INT, "PS2 .int raw header"},
|
{meta_RAW_INT, "PS2 .int raw header"},
|
||||||
{meta_OMU, "Outrage OMU Header"},
|
{meta_OMU, "Outrage OMU header"},
|
||||||
{meta_DSP_STM, "Intelligent Systems STM header"},
|
{meta_DSP_STM, "Intelligent Systems STM header"},
|
||||||
{meta_EXST, "Sony EXST header"},
|
{meta_EXST, "Sony EXST header"},
|
||||||
{meta_SVAG_KCET, "Konami SVAG header"},
|
{meta_SVAG_KCET, "Konami SVAG header"},
|
||||||
@ -1035,8 +1041,8 @@ static const meta_info meta_info_list[] = {
|
|||||||
{meta_DSP_STR, "Cauldron .STR header"},
|
{meta_DSP_STR, "Cauldron .STR header"},
|
||||||
{meta_EA_SCHL, "Electronic Arts SCHl header"},
|
{meta_EA_SCHL, "Electronic Arts SCHl header"},
|
||||||
{meta_EA_SCHL_fixed, "Electronic Arts SCHl header (fixed)"},
|
{meta_EA_SCHL_fixed, "Electronic Arts SCHl header (fixed)"},
|
||||||
{meta_CAF, "tri-Crescendo CAF Header"},
|
{meta_CAF, "tri-Crescendo CAF header"},
|
||||||
{meta_VPK, "SCE America VPK Header"},
|
{meta_VPK, "SCE America VPK header"},
|
||||||
{meta_GENH, "GENH generic header"},
|
{meta_GENH, "GENH generic header"},
|
||||||
{meta_DSP_SADB, "Procyon Studio SADB header"},
|
{meta_DSP_SADB, "Procyon Studio SADB header"},
|
||||||
{meta_SADL, "Procyon Studio SADL header"},
|
{meta_SADL, "Procyon Studio SADL header"},
|
||||||
@ -1055,7 +1061,7 @@ static const meta_info meta_info_list[] = {
|
|||||||
{meta_NWA_GAMEEXEINI, "VisualArt's NWA header (Gameexe.ini looping)"},
|
{meta_NWA_GAMEEXEINI, "VisualArt's NWA header (Gameexe.ini looping)"},
|
||||||
{meta_XSS, "Dino Crisis 3 XSS File"},
|
{meta_XSS, "Dino Crisis 3 XSS File"},
|
||||||
{meta_HGC1, "Cauldron HGC1 header"},
|
{meta_HGC1, "Cauldron HGC1 header"},
|
||||||
{meta_AUS, "Capcom AUS Header"},
|
{meta_AUS, "Atomic Planet AUS header"},
|
||||||
{meta_RWS, "RenderWare RWS header"},
|
{meta_RWS, "RenderWare RWS header"},
|
||||||
{meta_EA_1SNH, "Electronic Arts 1SNh header"},
|
{meta_EA_1SNH, "Electronic Arts 1SNh header"},
|
||||||
{meta_EA_EACS, "Electronic Arts EACS header"},
|
{meta_EA_EACS, "Electronic Arts EACS header"},
|
||||||
@ -1070,17 +1076,17 @@ static const meta_info meta_info_list[] = {
|
|||||||
{meta_PS2_XA30, "Reflections XA30 PS2 header"},
|
{meta_PS2_XA30, "Reflections XA30 PS2 header"},
|
||||||
{meta_MUSC, "Krome MUSC header"},
|
{meta_MUSC, "Krome MUSC header"},
|
||||||
{meta_MUSX, "Eurocom MUSX header"},
|
{meta_MUSX, "Eurocom MUSX header"},
|
||||||
{meta_FILP, "cavia FILp Header"},
|
{meta_FILP, "cavia FILp header"},
|
||||||
{meta_IKM, "MiCROViSiON IKM header"},
|
{meta_IKM, "MiCROViSiON IKM header"},
|
||||||
{meta_STER, "ALCHEMY STER header"},
|
{meta_STER, "ALCHEMY STER header"},
|
||||||
{meta_SAT_DVI, "Konami DVI. header"},
|
{meta_SAT_DVI, "Konami DVI. header"},
|
||||||
{meta_DC_KCEY, "Konami KCEY header"},
|
{meta_DC_KCEY, "Konami KCEY header"},
|
||||||
{meta_BG00, "Cave BG00 header"},
|
{meta_BG00, "Cave BG00 header"},
|
||||||
{meta_RSTM_ROCKSTAR, "Rockstar Games RSTM Header"},
|
{meta_RSTM_ROCKSTAR, "Rockstar Games RSTM header"},
|
||||||
{meta_ACM, "InterPlay ACM Header"},
|
{meta_ACM, "InterPlay ACM header"},
|
||||||
{meta_MUS_ACM, "InterPlay MUS ACM header"},
|
{meta_MUS_ACM, "InterPlay MUS ACM header"},
|
||||||
{meta_VIG_KCES, "Konami .VIG Header"},
|
{meta_VIG_KCES, "Konami .VIG header"},
|
||||||
{meta_HXD, "Tecmo HXD Header"},
|
{meta_HXD, "Tecmo HXD header"},
|
||||||
{meta_VSV, "Square Enix .vsv Header"},
|
{meta_VSV, "Square Enix .vsv Header"},
|
||||||
{meta_RIFF_WAVE_labl, "RIFF WAVE header (labl looping)"},
|
{meta_RIFF_WAVE_labl, "RIFF WAVE header (labl looping)"},
|
||||||
{meta_RIFF_WAVE_smpl, "RIFF WAVE header (smpl looping)"},
|
{meta_RIFF_WAVE_smpl, "RIFF WAVE header (smpl looping)"},
|
||||||
@ -1101,7 +1107,7 @@ static const meta_info meta_info_list[] = {
|
|||||||
{meta_STR_SEGA_custom, "Sega Stream Asset Builder header (custom)"},
|
{meta_STR_SEGA_custom, "Sega Stream Asset Builder header (custom)"},
|
||||||
{meta_XMU, "Outrage XMU header"},
|
{meta_XMU, "Outrage XMU header"},
|
||||||
{meta_XVAS, "Konami .XVAS header"},
|
{meta_XVAS, "Konami .XVAS header"},
|
||||||
{meta_XA2_ACCLAIM, "Acclaim .XA2 Header"},
|
{meta_XA2_ACCLAIM, "Acclaim .XA2 header"},
|
||||||
{meta_SAP, "VING .SAP header"},
|
{meta_SAP, "VING .SAP header"},
|
||||||
{meta_DC_IDVI, "Capcom IDVI header"},
|
{meta_DC_IDVI, "Capcom IDVI header"},
|
||||||
{meta_KRAW, "Geometry Wars: Galaxies KRAW header"},
|
{meta_KRAW, "Geometry Wars: Galaxies KRAW header"},
|
||||||
|
@ -2,20 +2,31 @@
|
|||||||
#include "../vgmstream.h"
|
#include "../vgmstream.h"
|
||||||
|
|
||||||
/* each block is a new CAF header */
|
/* each block is a new CAF header */
|
||||||
void block_update_caf(off_t block_offset, VGMSTREAM * vgmstream) {
|
void block_update_caf(off_t block_offset, VGMSTREAM* vgmstream) {
|
||||||
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
|
STREAMFILE* sf = vgmstream->ch[0].streamfile;
|
||||||
int i,ch;
|
|
||||||
|
|
||||||
|
// 00: "CAF "
|
||||||
|
// 04: block size
|
||||||
|
// 08: block number
|
||||||
|
// 0c: empty
|
||||||
|
// 10: channel 1 offset
|
||||||
|
// 14: channel 1 size
|
||||||
|
// 18: channel 2 offset
|
||||||
|
// 1c: channel 2 size
|
||||||
|
// 20: loop start
|
||||||
|
// 24: loop end (same as last block)
|
||||||
|
// 28: DSP header stuff (repeated per block)
|
||||||
|
|
||||||
vgmstream->current_block_offset = block_offset;
|
vgmstream->current_block_offset = block_offset;
|
||||||
vgmstream->next_block_offset = block_offset + read_32bitBE(block_offset+0x04, streamFile);
|
vgmstream->next_block_offset = block_offset + read_u32be(block_offset + 0x04, sf);
|
||||||
vgmstream->current_block_size = read_32bitBE(block_offset+0x14, streamFile);
|
vgmstream->current_block_size = read_u32be(block_offset + 0x14, sf);
|
||||||
|
|
||||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
for (int ch = 0; ch < vgmstream->channels; ch++) {
|
||||||
vgmstream->ch[ch].offset = block_offset + read_32bitBE(block_offset+0x10+(0x08*ch), streamFile);
|
vgmstream->ch[ch].offset = block_offset + read_u32be(block_offset + 0x10 + 0x08 * ch, sf);
|
||||||
|
|
||||||
/* re-read coeffs (though blocks seem to repeat them) */
|
/* re-read coeffs (though blocks seem to repeat them) */
|
||||||
for (i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
vgmstream->ch[ch].adpcm_coef[i] = read_16bitBE(block_offset+0x34 + 0x2c*ch + 0x02*i, streamFile);
|
vgmstream->ch[ch].adpcm_coef[i] = read_s16be(block_offset + 0x34 + 0x2c * ch + 0x02 * i, sf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
128
src/meta/caf.c
128
src/meta/caf.c
@ -1,62 +1,66 @@
|
|||||||
#include "meta.h"
|
#include "meta.h"
|
||||||
#include "../layout/layout.h"
|
#include "../layout/layout.h"
|
||||||
#include "../util.h"
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
/* CAF - from tri-Crescendo games [Baten Kaitos 1/2 (GC), Fragile (Wii)] */
|
/* CAF - from tri-Crescendo games [Baten Kaitos 1/2 (GC), Fragile (Wii)] */
|
||||||
VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile) {
|
VGMSTREAM* init_vgmstream_caf(STREAMFILE* sf) {
|
||||||
VGMSTREAM * vgmstream = NULL;
|
VGMSTREAM* vgmstream = NULL;
|
||||||
off_t start_offset, offset;
|
off_t start_offset;
|
||||||
size_t file_size;
|
int channels, loop_flag;
|
||||||
int channel_count, loop_flag;
|
int32_t num_samples = 0;
|
||||||
int32_t num_samples = 0;
|
|
||||||
uint32_t loop_start = -1;
|
|
||||||
|
/* checks */
|
||||||
|
if (!is_id32be(0x00,sf, "CAF "))
|
||||||
/* checks */
|
return NULL;
|
||||||
/* .caf: header id, .cfn: fake extension? , "" is accepted as files don't have extensions in the disc */
|
|
||||||
if (!check_extensions(streamFile,"caf,cfn,"))
|
/* .caf: header id
|
||||||
goto fail;
|
* (extensionless): files on disc don't have any extensions
|
||||||
if (read_32bitBE(0x00,streamFile) != 0x43414620) /* "CAF " */
|
* .cfn: fake extension */
|
||||||
goto fail;
|
if (!check_extensions(sf,"caf,cfn,"))
|
||||||
|
return NULL;
|
||||||
/* get total samples */
|
|
||||||
offset = 0;
|
/* get total samples from blocks + find loop */ //TODO reuse function calls
|
||||||
file_size = get_streamfile_size(streamFile);
|
uint32_t loop_start = -1;
|
||||||
while (offset < file_size) {
|
off_t offset = 0x00;
|
||||||
off_t next_block = read_32bitBE(offset+0x04,streamFile);
|
off_t file_size = get_streamfile_size(sf);
|
||||||
num_samples += read_32bitBE(offset+0x14,streamFile)/8*14;
|
while (offset < file_size) {
|
||||||
|
// see blocked layout for block info
|
||||||
if(read_32bitBE(offset+0x20,streamFile)==read_32bitBE(offset+0x08,streamFile)) {
|
off_t next_block = read_u32be(offset+0x04,sf);
|
||||||
loop_start = num_samples - read_32bitBE(offset+0x14,streamFile)/8*14;
|
off_t channel_bytes = read_u32be(offset+0x14,sf);
|
||||||
}
|
int channel_samples = dsp_bytes_to_samples(channel_bytes, 1);
|
||||||
offset += next_block;
|
|
||||||
}
|
if (read_u32be(offset+0x08,sf) == read_u32be(offset+0x20,sf) && loop_start < 0) {
|
||||||
|
loop_start = num_samples;
|
||||||
start_offset = 0x00;
|
}
|
||||||
channel_count = 2; /* always stereo */
|
|
||||||
loop_flag = (loop_start!=-1);
|
num_samples += channel_samples;
|
||||||
|
offset += next_block;
|
||||||
|
}
|
||||||
/* build the VGMSTREAM */
|
|
||||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
start_offset = 0x00;
|
||||||
if (!vgmstream) goto fail;
|
channels = 2; /* always stereo */
|
||||||
|
loop_flag = (loop_start != -1);
|
||||||
vgmstream->sample_rate = 32000;
|
|
||||||
vgmstream->num_samples = num_samples;
|
|
||||||
if (loop_flag) {
|
/* build the VGMSTREAM */
|
||||||
vgmstream->loop_start_sample = loop_start;
|
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||||
vgmstream->loop_end_sample = num_samples;
|
if (!vgmstream) goto fail;
|
||||||
}
|
|
||||||
|
vgmstream->sample_rate = 32000;
|
||||||
vgmstream->meta_type = meta_CAF;
|
vgmstream->num_samples = num_samples;
|
||||||
vgmstream->coding_type = coding_NGC_DSP;
|
vgmstream->loop_start_sample = loop_start;
|
||||||
vgmstream->layout_type = layout_blocked_caf;
|
vgmstream->loop_end_sample = num_samples;
|
||||||
|
|
||||||
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) )
|
vgmstream->meta_type = meta_CAF;
|
||||||
goto fail;
|
vgmstream->coding_type = coding_NGC_DSP;
|
||||||
return vgmstream;
|
vgmstream->layout_type = layout_blocked_caf;
|
||||||
|
|
||||||
fail:
|
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||||
close_vgmstream(vgmstream);
|
goto fail;
|
||||||
return NULL;
|
return vgmstream;
|
||||||
}
|
|
||||||
|
fail:
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -2,49 +2,47 @@
|
|||||||
#include "../coding/coding.h"
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
/* VPK - from SCE America second party devs [God of War (PS2), NBA 08 (PS3)] */
|
/* VPK - from SCE America second party devs [God of War (PS2), NBA 08 (PS3)] */
|
||||||
VGMSTREAM * init_vgmstream_vpk(STREAMFILE *streamFile) {
|
VGMSTREAM* init_vgmstream_vpk(STREAMFILE* sf) {
|
||||||
VGMSTREAM * vgmstream = NULL;
|
VGMSTREAM* vgmstream = NULL;
|
||||||
int loop_flag, channel_count;
|
int loop_flag, channels;
|
||||||
off_t start_offset, loop_channel_offset;
|
off_t start_offset, loop_channel_offset;
|
||||||
size_t channel_size;
|
|
||||||
|
|
||||||
|
|
||||||
/* checks */
|
/* checks */
|
||||||
if (!check_extensions(streamFile, "vpk"))
|
if (!is_id32be(0x00,sf, " KPV"))
|
||||||
goto fail;
|
return NULL;
|
||||||
|
if (!check_extensions(sf, "vpk"))
|
||||||
if (read_32bitBE(0x00,streamFile) != 0x204B5056) /* " KPV" */
|
return NULL;
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* files are padded with garbage/silent 0xC00000..00 frames, and channel_size sometimes
|
/* files are padded with garbage/silent 0xC00000..00 frames, and channel_size sometimes
|
||||||
* has extra size into the padding: +0x10 (NBA08), +0x20 (GoW), or none (Sly 2, loops ok).
|
* has extra size into the padding: +0x10 (NBA08), +0x20 (GoW), or none (Sly 2, loops ok).
|
||||||
* Could detect and remove to slightly improve full loops, but maybe this is just how the game works */
|
* Could detect and remove to slightly improve full loops, but maybe this is just how the game works */
|
||||||
channel_size = read_32bitLE(0x04,streamFile);
|
size_t channel_size = read_u32le(0x04,sf);
|
||||||
|
|
||||||
start_offset = read_32bitLE(0x08,streamFile);
|
start_offset = read_u32le(0x08,sf);
|
||||||
channel_count = read_32bitLE(0x14,streamFile);
|
channels = read_s32le(0x14,sf);
|
||||||
/* 0x18+: channel config(?), 0x04 per channel */
|
/* 0x18+: channel config(?), 0x04 per channel */
|
||||||
loop_channel_offset = read_32bitLE(0x7FC,streamFile);
|
loop_channel_offset = read_u32le(0x7FC,sf);
|
||||||
loop_flag = (loop_channel_offset != 0); /* found in Sly 2/3 */
|
loop_flag = (loop_channel_offset != 0); /* found in Sly 2/3 */
|
||||||
|
|
||||||
|
|
||||||
/* build the VGMSTREAM */
|
/* build the VGMSTREAM */
|
||||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||||
if (!vgmstream) goto fail;
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
|
vgmstream->sample_rate = read_s32le(0x10,sf);
|
||||||
vgmstream->num_samples = ps_bytes_to_samples(channel_size*vgmstream->channels,vgmstream->channels);
|
vgmstream->num_samples = ps_bytes_to_samples(channel_size * channels, channels);
|
||||||
if (vgmstream->loop_flag) {
|
if (vgmstream->loop_flag) {
|
||||||
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_channel_offset*vgmstream->channels,vgmstream->channels);
|
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_channel_offset * channels, channels);
|
||||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
vgmstream->meta_type = meta_VPK;
|
vgmstream->meta_type = meta_VPK;
|
||||||
vgmstream->coding_type = coding_PSX;
|
vgmstream->coding_type = coding_PSX;
|
||||||
vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile) / 2; /* even in >2ch */
|
vgmstream->interleave_block_size = read_u32le(0x0C,sf) / 2; /* even in >2ch */
|
||||||
vgmstream->layout_type = layout_interleave;
|
vgmstream->layout_type = layout_interleave;
|
||||||
|
|
||||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||||
goto fail;
|
goto fail;
|
||||||
return vgmstream;
|
return vgmstream;
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ typedef struct {
|
|||||||
int fix_xma_loop_samples;
|
int fix_xma_loop_samples;
|
||||||
} xwb_header;
|
} xwb_header;
|
||||||
|
|
||||||
static void get_name(char* buf, size_t maxsize, int target_subsong, xwb_header* xwb, STREAMFILE* sf);
|
static void get_name(char* buf, size_t buf_size, int target_subsong, xwb_header* xwb, STREAMFILE* sf);
|
||||||
|
|
||||||
|
|
||||||
/* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */
|
/* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */
|
||||||
@ -638,10 +638,10 @@ fail:
|
|||||||
|
|
||||||
/* ****************************************************************************** */
|
/* ****************************************************************************** */
|
||||||
|
|
||||||
static int get_xwb_name(char* buf, size_t maxsize, int target_subsong, xwb_header* xwb, STREAMFILE* sf) {
|
static int get_xwb_name(char* buf, size_t buf_size, int target_subsong, xwb_header* xwb, STREAMFILE* sf) {
|
||||||
size_t read;
|
size_t read;
|
||||||
|
|
||||||
if (!xwb->names_offset || !xwb->names_size || xwb->names_entry_size > maxsize)
|
if (!xwb->names_offset || !xwb->names_size || xwb->names_entry_size > buf_size)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
read = read_string(buf,xwb->names_entry_size, xwb->names_offset + xwb->names_entry_size*(target_subsong-1),sf);
|
read = read_string(buf,xwb->names_entry_size, xwb->names_offset + xwb->names_entry_size*(target_subsong-1),sf);
|
||||||
@ -653,7 +653,7 @@ fail:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_xsb_name(char* buf, size_t maxsize, int target_subsong, xwb_header* xwb, STREAMFILE* sf) {
|
static int get_xsb_name(char* buf, size_t buf_size, int target_subsong, xwb_header* xwb, STREAMFILE* sf) {
|
||||||
xsb_header xsb = {0};
|
xsb_header xsb = {0};
|
||||||
|
|
||||||
xsb.selected_stream = target_subsong - 1;
|
xsb.selected_stream = target_subsong - 1;
|
||||||
@ -670,8 +670,7 @@ static int get_xsb_name(char* buf, size_t maxsize, int target_subsong, xwb_heade
|
|||||||
if (!xsb.name_len || xsb.name[0] == '\0')
|
if (!xsb.name_len || xsb.name[0] == '\0')
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
strncpy(buf,xsb.name,maxsize);
|
snprintf(buf, buf_size, "%s", xsb.name);
|
||||||
buf[maxsize-1] = '\0';
|
|
||||||
return 1;
|
return 1;
|
||||||
fail:
|
fail:
|
||||||
return 0;
|
return 0;
|
||||||
@ -715,12 +714,12 @@ fail:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_name(char* buf, size_t maxsize, int target_subsong, xwb_header* xwb, STREAMFILE* sf_xwb) {
|
static void get_name(char* buf, size_t buf_size, int target_subsong, xwb_header* xwb, STREAMFILE* sf_xwb) {
|
||||||
STREAMFILE* sf_name = NULL;
|
STREAMFILE* sf_name = NULL;
|
||||||
int name_found;
|
int name_found;
|
||||||
|
|
||||||
/* try to get the stream name in the .xwb, though they are very rarely included */
|
/* try to get the stream name in the .xwb, though they are very rarely included */
|
||||||
name_found = get_xwb_name(buf, maxsize, target_subsong, xwb, sf_xwb);
|
name_found = get_xwb_name(buf, buf_size, target_subsong, xwb, sf_xwb);
|
||||||
if (name_found) return;
|
if (name_found) return;
|
||||||
|
|
||||||
/* try again in a companion files */
|
/* try again in a companion files */
|
||||||
@ -730,7 +729,7 @@ static void get_name(char* buf, size_t maxsize, int target_subsong, xwb_header*
|
|||||||
sf_name = open_streamfile_by_ext(sf_xwb, "wbh");
|
sf_name = open_streamfile_by_ext(sf_xwb, "wbh");
|
||||||
if (!sf_name) goto fail; /* rarely found [Pac-Man World 2 (Xbox)] */
|
if (!sf_name) goto fail; /* rarely found [Pac-Man World 2 (Xbox)] */
|
||||||
|
|
||||||
name_found = get_wbh_name(buf, maxsize, target_subsong, xwb, sf_name);
|
name_found = get_wbh_name(buf, buf_size, target_subsong, xwb, sf_name);
|
||||||
close_streamfile(sf_name);
|
close_streamfile(sf_name);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -738,7 +737,7 @@ static void get_name(char* buf, size_t maxsize, int target_subsong, xwb_header*
|
|||||||
sf_name = open_xsb_filename_pair(sf_xwb);
|
sf_name = open_xsb_filename_pair(sf_xwb);
|
||||||
if (!sf_name) goto fail; /* not all xwb have xsb though */
|
if (!sf_name) goto fail; /* not all xwb have xsb though */
|
||||||
|
|
||||||
name_found = get_xsb_name(buf, maxsize, target_subsong, xwb, sf_name);
|
name_found = get_xsb_name(buf, buf_size, target_subsong, xwb, sf_name);
|
||||||
close_streamfile(sf_name);
|
close_streamfile(sf_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,6 +242,9 @@ static STREAMFILE* open_stdio_streamfile_buffer_by_file(FILE* infile, const char
|
|||||||
uint8_t* buf = NULL;
|
uint8_t* buf = NULL;
|
||||||
STDIO_STREAMFILE* this_sf = NULL;
|
STDIO_STREAMFILE* this_sf = NULL;
|
||||||
|
|
||||||
|
if (buf_size <= 0)
|
||||||
|
buf_size = STREAMFILE_DEFAULT_BUFFER_SIZE;
|
||||||
|
|
||||||
buf = calloc(buf_size, sizeof(uint8_t));
|
buf = calloc(buf_size, sizeof(uint8_t));
|
||||||
if (!buf) goto fail;
|
if (!buf) goto fail;
|
||||||
|
|
||||||
@ -326,11 +329,11 @@ static STREAMFILE* open_stdio_streamfile_buffer(const char* const filename, size
|
|||||||
}
|
}
|
||||||
|
|
||||||
STREAMFILE* open_stdio_streamfile(const char* filename) {
|
STREAMFILE* open_stdio_streamfile(const char* filename) {
|
||||||
return open_stdio_streamfile_buffer(filename, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
return open_stdio_streamfile_buffer(filename, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
STREAMFILE* open_stdio_streamfile_by_file(FILE* file, const char* filename) {
|
STREAMFILE* open_stdio_streamfile_by_file(FILE* file, const char* filename) {
|
||||||
return open_stdio_streamfile_buffer_by_file(file, filename, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
return open_stdio_streamfile_buffer_by_file(file, filename, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* **************************************************** */
|
/* **************************************************** */
|
||||||
|
@ -1,43 +1,43 @@
|
|||||||
#ifndef _TEXT_READER_H_
|
#ifndef _TEXT_READER_H_
|
||||||
#define _TEXT_READER_H_
|
#define _TEXT_READER_H_
|
||||||
|
|
||||||
|
|
||||||
/* Reader tuned for whole text files, reading chunks to minimize I/O with a single buffer.
|
/* Reader tuned for whole text files, reading chunks to minimize I/O with a single buffer.
|
||||||
* For short lines read_line may be more appropriate (reads up to line end, while this reads bigger chunks),
|
* For short lines read_line may be more appropriate (reads up to line end, while this reads bigger chunks),
|
||||||
* which also allow \0 (this reader returns an error).
|
* which also allow \0 (this reader returns an error).
|
||||||
* NOTE: modifies passed buffer (lines are forced to end with \0 rather than \n).
|
* NOTE: modifies passed buffer (lines are forced to end with \0 rather than \n).
|
||||||
*
|
*
|
||||||
* Usage: set text_reader_t and defaults with text_reader_init, call text_reader_get_line(...) to get lines.
|
* Usage: set text_reader_t and defaults with text_reader_init, call text_reader_get_line(...) to get lines.
|
||||||
* buf may be size+1 to allow 2^N chunk reads + trailing \0 (better performance?).
|
* buf may be size+1 to allow 2^N chunk reads + trailing \0 (better performance?).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../streamfile.h"
|
#include "../streamfile.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* init */
|
/* init */
|
||||||
uint8_t* buf; /* where data will be read */
|
uint8_t* buf; /* where data will be read */
|
||||||
int buf_size; /* size of the struct (also max line size) */
|
int buf_size; /* size of the struct (also max line size) */
|
||||||
STREAMFILE* sf; /* used to read data */
|
STREAMFILE* sf; /* used to read data */
|
||||||
uint32_t offset; /* sf pos */
|
uint32_t offset; /* sf pos */
|
||||||
uint32_t max_offset; /* sf max */
|
uint32_t max_offset; /* sf max */
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
int filled; /* current buf bytes */
|
int filled; /* current buf bytes */
|
||||||
int pos; /* current buf pos (last line) */
|
int pos; /* current buf pos (last line) */
|
||||||
int next_pos; /* buf pos on next call, after line end */
|
int next_pos; /* buf pos on next call, after line end */
|
||||||
int line_ok; /* current line is fully correct */
|
int line_ok; /* current line is fully correct */
|
||||||
|
|
||||||
char* line;
|
char* line;
|
||||||
int line_len;
|
int line_len;
|
||||||
} text_reader_t;
|
} text_reader_t;
|
||||||
|
|
||||||
|
|
||||||
/* convenience function to init the above struct */
|
/* convenience function to init the above struct */
|
||||||
int text_reader_init(text_reader_t* tr, uint8_t* buf, int buf_size, STREAMFILE* sf, uint32_t offset, uint32_t max);
|
int text_reader_init(text_reader_t* tr, uint8_t* buf, int buf_size, STREAMFILE* sf, uint32_t offset, uint32_t max);
|
||||||
|
|
||||||
/* Reads and sets next line, or NULL if no lines are found (EOF).
|
/* Reads and sets next line, or NULL if no lines are found (EOF).
|
||||||
* returns line length (0 for empty lines), or <0 if line was too long to store in buf.
|
* returns line length (0 for empty lines), or <0 if line was too long to store in buf.
|
||||||
* Will always return a valid (null terminated) string. */
|
* Will always return a valid (null terminated) string. */
|
||||||
int text_reader_get_line(text_reader_t* tr, char** p_line);
|
int text_reader_get_line(text_reader_t* tr, char** p_line);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user