mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-31 04:13:47 +01:00
Add .bigrp [BM Zero 2 (SW), Gunvolt 3 (SW)]
This commit is contained in:
parent
791a7de02a
commit
cbd831e658
@ -315,6 +315,7 @@ are used in few games.
|
|||||||
- Xiph CELT (FSB)
|
- Xiph CELT (FSB)
|
||||||
- Musepack
|
- Musepack
|
||||||
- FLAC
|
- FLAC
|
||||||
|
- Inti Creates' Range / DCT codecs
|
||||||
- Others
|
- Others
|
||||||
|
|
||||||
Sometimes standard codecs come in non-standard layouts that aren't normally
|
Sometimes standard codecs come in non-standard layouts that aren't normally
|
||||||
|
@ -353,6 +353,16 @@ void seek_tac(tac_codec_data* data, int32_t num_sample);
|
|||||||
void free_tac(tac_codec_data* data);
|
void free_tac(tac_codec_data* data);
|
||||||
|
|
||||||
|
|
||||||
|
/* ice_decoder */
|
||||||
|
typedef struct ice_codec_data ice_codec_data;
|
||||||
|
|
||||||
|
ice_codec_data* init_ice(STREAMFILE* sf, int subsong);
|
||||||
|
void decode_ice(ice_codec_data* data, sample_t* outbuf, int32_t samples_to_do);
|
||||||
|
void reset_ice(ice_codec_data* data);
|
||||||
|
void seek_ice(ice_codec_data* data, int32_t num_sample);
|
||||||
|
void free_ice(ice_codec_data* data);
|
||||||
|
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
/* ogg_vorbis_decoder */
|
/* ogg_vorbis_decoder */
|
||||||
typedef struct ogg_vorbis_codec_data ogg_vorbis_codec_data;
|
typedef struct ogg_vorbis_codec_data ogg_vorbis_codec_data;
|
||||||
|
138
src/coding/ice_decoder.c
Normal file
138
src/coding/ice_decoder.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#include "coding.h"
|
||||||
|
#include "ice_decoder_icelib.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
STREAMFILE* sf;
|
||||||
|
int offset;
|
||||||
|
} icelib_io_t;
|
||||||
|
|
||||||
|
struct ice_codec_data {
|
||||||
|
STREAMFILE* sf;
|
||||||
|
int channels;
|
||||||
|
icesnd_handle_t* ctx;
|
||||||
|
icelib_io_t io;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void icelib_set_callbacks(icesnd_callback_t* cb, STREAMFILE* sf, icelib_io_t* io);
|
||||||
|
|
||||||
|
ice_codec_data* init_ice(STREAMFILE* sf, int subsong) {
|
||||||
|
ice_codec_data* data = NULL;
|
||||||
|
|
||||||
|
data = calloc(1, sizeof(ice_codec_data));
|
||||||
|
if (!data) goto fail;
|
||||||
|
|
||||||
|
data->sf = reopen_streamfile(sf, 0);
|
||||||
|
if (!data->sf) goto fail;
|
||||||
|
|
||||||
|
{
|
||||||
|
icesnd_callback_t cb = {0};
|
||||||
|
icesnd_info_t info = {0};
|
||||||
|
int err;
|
||||||
|
|
||||||
|
icelib_set_callbacks(&cb, data->sf, &data->io);
|
||||||
|
|
||||||
|
data->ctx = icesnd_init(subsong, &cb);
|
||||||
|
if (!data->ctx) goto fail;
|
||||||
|
|
||||||
|
err = icesnd_info(data->ctx, &info);
|
||||||
|
if (err < ICESND_RESULT_OK) goto fail;
|
||||||
|
|
||||||
|
data->channels = info.channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
fail:
|
||||||
|
free_ice(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void decode_ice(ice_codec_data* data, sample_t* outbuf, int32_t samples_to_do) {
|
||||||
|
int channels = data->channels;
|
||||||
|
|
||||||
|
while (samples_to_do > 0) {
|
||||||
|
int done = icesnd_decode(data->ctx, outbuf, samples_to_do);
|
||||||
|
if (done <= 0) goto decode_fail;
|
||||||
|
|
||||||
|
outbuf += done * channels;
|
||||||
|
samples_to_do -= done;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
decode_fail:
|
||||||
|
VGM_LOG("ICE: decode error\n");
|
||||||
|
memset(outbuf, 0, samples_to_do * channels * sizeof(sample_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_ice(ice_codec_data* data) {
|
||||||
|
if (!data) return;
|
||||||
|
|
||||||
|
icesnd_reset(data->ctx, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void seek_ice(ice_codec_data* data, int32_t num_sample) {
|
||||||
|
if (!data) return;
|
||||||
|
|
||||||
|
//todo discard (this should only be called when looping)
|
||||||
|
icesnd_reset(data->ctx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_ice(ice_codec_data* data) {
|
||||||
|
if (!data) return;
|
||||||
|
|
||||||
|
close_streamfile(data->sf);
|
||||||
|
icesnd_free(data->ctx);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************* */
|
||||||
|
|
||||||
|
static int icelib_read(void* dst, int size, int n, void* arg) {
|
||||||
|
icelib_io_t* io = arg;
|
||||||
|
int bytes_read, items_read;
|
||||||
|
|
||||||
|
bytes_read = read_streamfile(dst, io->offset, size * n, io->sf);
|
||||||
|
items_read = bytes_read / size;
|
||||||
|
io->offset += bytes_read;
|
||||||
|
|
||||||
|
return items_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int icelib_seek(void* arg, int offset, int whence) {
|
||||||
|
icelib_io_t* io = arg;
|
||||||
|
int base_offset, new_offset;
|
||||||
|
|
||||||
|
switch (whence) {
|
||||||
|
case ICESND_SEEK_SET:
|
||||||
|
base_offset = 0;
|
||||||
|
break;
|
||||||
|
case ICESND_SEEK_CUR:
|
||||||
|
base_offset = io->offset;
|
||||||
|
break;
|
||||||
|
case ICESND_SEEK_END:
|
||||||
|
base_offset = get_streamfile_size(io->sf);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_offset = base_offset + offset;
|
||||||
|
if (new_offset < 0 /*|| new_offset > get_streamfile_size(config->sf)*/) {
|
||||||
|
return -1; /* unseekable */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
io->offset = new_offset;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void icelib_set_callbacks(icesnd_callback_t* cb, STREAMFILE* sf, icelib_io_t* io) {
|
||||||
|
io->offset = 0;
|
||||||
|
io->sf = sf;
|
||||||
|
|
||||||
|
cb->arg = io;
|
||||||
|
cb->read = icelib_read;
|
||||||
|
cb->seek = icelib_seek;
|
||||||
|
}
|
1433
src/coding/ice_decoder_icelib.c
Normal file
1433
src/coding/ice_decoder_icelib.c
Normal file
File diff suppressed because it is too large
Load Diff
67
src/coding/ice_decoder_icelib.h
Normal file
67
src/coding/ice_decoder_icelib.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#ifndef _ICELIB_H_
|
||||||
|
#define _ICELIB_H_
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Decodes Inti Creates's "ICE" engine BIGRP sounds. */
|
||||||
|
|
||||||
|
#define ICESND_CODEC_RANGE 0x00
|
||||||
|
#define ICESND_CODEC_DATA 0x01
|
||||||
|
#define ICESND_CODEC_MIDI 0x02
|
||||||
|
#define ICESND_CODEC_DCT 0x03
|
||||||
|
|
||||||
|
#define ICESND_RESULT_OK 0
|
||||||
|
#define ICESND_ERROR_HEADER -1
|
||||||
|
#define ICESND_ERROR_SETUP -2
|
||||||
|
#define ICESND_ERROR_DECODE -3
|
||||||
|
|
||||||
|
typedef struct icesnd_handle_t icesnd_handle_t;
|
||||||
|
|
||||||
|
#define ICESND_SEEK_SET 0
|
||||||
|
#define ICESND_SEEK_CUR 1
|
||||||
|
#define ICESND_SEEK_END 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* whole file in memory (for testing) */
|
||||||
|
const uint8_t* filebuf;
|
||||||
|
int filebuf_size;
|
||||||
|
|
||||||
|
/* custom IO */
|
||||||
|
void* arg;
|
||||||
|
int (*read)(void* dst, int size, int n, void* arg);
|
||||||
|
int (*seek)(void* arg, int offset, int whence);
|
||||||
|
|
||||||
|
} icesnd_callback_t;
|
||||||
|
|
||||||
|
/* Inits ICE lib with config.
|
||||||
|
* Original code expects all data in memory, but this allows setting read callbacks
|
||||||
|
* (making it feed-style was a bit complex due to how data is laid out) */
|
||||||
|
icesnd_handle_t* icesnd_init(int target_subsong, icesnd_callback_t* cb);
|
||||||
|
|
||||||
|
void icesnd_free(icesnd_handle_t* handle);
|
||||||
|
|
||||||
|
/* resets the decoder. If loop_starts and file loops and
|
||||||
|
* (format is not seekable but separated into intro+body blocks) */
|
||||||
|
void icesnd_reset(icesnd_handle_t* handle, int loop_start);
|
||||||
|
|
||||||
|
/* Decodes up to samples for N channels into sbuf (interleaved). Returns samples done,
|
||||||
|
* 0 if not possible (non-looped files past end) or negative on error.
|
||||||
|
* May return less than wanted samples on block boundaries.
|
||||||
|
*
|
||||||
|
* It's designed to decode an arbitrary number of samples, as data isn't divided into frames (original
|
||||||
|
* player does sample_rate/60.0 at a time). Codec 0 is aligned to 100 samples and codec 3 to 16 though. */
|
||||||
|
int icesnd_decode(icesnd_handle_t* handle, int16_t* sbuf, int max_samples);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int total_subsongs;
|
||||||
|
int codec;
|
||||||
|
int sample_rate;
|
||||||
|
int channels;
|
||||||
|
int loop_start;
|
||||||
|
int num_samples;
|
||||||
|
int loop_flag;
|
||||||
|
} icesnd_info_t;
|
||||||
|
|
||||||
|
/* loads info */
|
||||||
|
int icesnd_info(icesnd_handle_t* handle, icesnd_info_t* info);
|
||||||
|
|
||||||
|
#endif
|
22
src/decode.c
22
src/decode.c
@ -39,6 +39,11 @@ void free_codec(VGMSTREAM* vgmstream) {
|
|||||||
free_tac(vgmstream->codec_data);
|
free_tac(vgmstream->codec_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vgmstream->coding_type == coding_ICE_RANGE ||
|
||||||
|
vgmstream->coding_type == coding_ICE_DCT) {
|
||||||
|
free_ice(vgmstream->codec_data);
|
||||||
|
}
|
||||||
|
|
||||||
if (vgmstream->coding_type == coding_UBI_ADPCM) {
|
if (vgmstream->coding_type == coding_UBI_ADPCM) {
|
||||||
free_ubi_adpcm(vgmstream->codec_data);
|
free_ubi_adpcm(vgmstream->codec_data);
|
||||||
}
|
}
|
||||||
@ -140,6 +145,11 @@ void seek_codec(VGMSTREAM* vgmstream) {
|
|||||||
seek_tac(vgmstream->codec_data, vgmstream->loop_current_sample);
|
seek_tac(vgmstream->codec_data, vgmstream->loop_current_sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vgmstream->coding_type == coding_ICE_RANGE ||
|
||||||
|
vgmstream->coding_type == coding_ICE_DCT) {
|
||||||
|
seek_ice(vgmstream->codec_data, vgmstream->loop_current_sample);
|
||||||
|
}
|
||||||
|
|
||||||
if (vgmstream->coding_type == coding_UBI_ADPCM) {
|
if (vgmstream->coding_type == coding_UBI_ADPCM) {
|
||||||
seek_ubi_adpcm(vgmstream->codec_data, vgmstream->loop_current_sample);
|
seek_ubi_adpcm(vgmstream->codec_data, vgmstream->loop_current_sample);
|
||||||
}
|
}
|
||||||
@ -246,6 +256,11 @@ void reset_codec(VGMSTREAM* vgmstream) {
|
|||||||
reset_tac(vgmstream->codec_data);
|
reset_tac(vgmstream->codec_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vgmstream->coding_type == coding_ICE_RANGE ||
|
||||||
|
vgmstream->coding_type == coding_ICE_DCT) {
|
||||||
|
reset_ice(vgmstream->codec_data);
|
||||||
|
}
|
||||||
|
|
||||||
if (vgmstream->coding_type == coding_UBI_ADPCM) {
|
if (vgmstream->coding_type == coding_UBI_ADPCM) {
|
||||||
reset_ubi_adpcm(vgmstream->codec_data);
|
reset_ubi_adpcm(vgmstream->codec_data);
|
||||||
}
|
}
|
||||||
@ -535,6 +550,9 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) {
|
|||||||
return 0; /* 1024 - delay/padding (which can be bigger than 1024) */
|
return 0; /* 1024 - delay/padding (which can be bigger than 1024) */
|
||||||
case coding_TAC:
|
case coding_TAC:
|
||||||
return 0; /* 1024 - delay/padding */
|
return 0; /* 1024 - delay/padding */
|
||||||
|
case coding_ICE_RANGE:
|
||||||
|
case coding_ICE_DCT:
|
||||||
|
return 0; /* ~100 (range), ~16 (DCT) */
|
||||||
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
||||||
case coding_MP4_AAC:
|
case coding_MP4_AAC:
|
||||||
return ((mp4_aac_codec_data*)vgmstream->codec_data)->samples_per_frame;
|
return ((mp4_aac_codec_data*)vgmstream->codec_data)->samples_per_frame;
|
||||||
@ -1075,6 +1093,10 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
|
|||||||
case coding_TAC:
|
case coding_TAC:
|
||||||
decode_tac(vgmstream, buffer, samples_to_do);
|
decode_tac(vgmstream, buffer, samples_to_do);
|
||||||
break;
|
break;
|
||||||
|
case coding_ICE_RANGE:
|
||||||
|
case coding_ICE_DCT:
|
||||||
|
decode_ice(vgmstream->codec_data, buffer, samples_to_do);
|
||||||
|
break;
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
case coding_FFmpeg:
|
case coding_FFmpeg:
|
||||||
decode_ffmpeg(vgmstream, buffer, samples_to_do, vgmstream->channels);
|
decode_ffmpeg(vgmstream, buffer, samples_to_do, vgmstream->channels);
|
||||||
|
@ -105,6 +105,7 @@ static const char* extension_list[] = {
|
|||||||
"bgm",
|
"bgm",
|
||||||
"bgw",
|
"bgw",
|
||||||
"bh2pcm",
|
"bh2pcm",
|
||||||
|
"bigrp",
|
||||||
"bik",
|
"bik",
|
||||||
"bika", //fake extension for .bik (to be removed)
|
"bika", //fake extension for .bik (to be removed)
|
||||||
"bik2",
|
"bik2",
|
||||||
@ -861,6 +862,8 @@ static const coding_info coding_info_list[] = {
|
|||||||
{coding_RELIC, "Relic Codec"},
|
{coding_RELIC, "Relic Codec"},
|
||||||
{coding_CRI_HCA, "CRI HCA"},
|
{coding_CRI_HCA, "CRI HCA"},
|
||||||
{coding_TAC, "tri-Ace Codec"},
|
{coding_TAC, "tri-Ace Codec"},
|
||||||
|
{coding_ICE_RANGE, "Inti Creates Range Codec"},
|
||||||
|
{coding_ICE_DCT, "Inti Creates DCT Codec"},
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
{coding_OGG_VORBIS, "Ogg Vorbis"},
|
{coding_OGG_VORBIS, "Ogg Vorbis"},
|
||||||
@ -1415,6 +1418,7 @@ static const meta_info meta_info_list[] = {
|
|||||||
{meta_TT_AD, "Traveller's Tales AUDIO_DATA header"},
|
{meta_TT_AD, "Traveller's Tales AUDIO_DATA header"},
|
||||||
{meta_SNDZ, "Sony SNDZ header"},
|
{meta_SNDZ, "Sony SNDZ header"},
|
||||||
{meta_VAB, "Sony VAB header"},
|
{meta_VAB, "Sony VAB header"},
|
||||||
|
{meta_BIGRP, "Inti Creates .BIGRP header"},
|
||||||
};
|
};
|
||||||
|
|
||||||
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
|
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
|
||||||
|
@ -83,6 +83,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="coding\hca_decoder_clhca.h" />
|
<ClInclude Include="coding\hca_decoder_clhca.h" />
|
||||||
|
<ClInclude Include="coding\ice_decoder_icelib.h" />
|
||||||
<ClInclude Include="coding\mpeg_bitreader.h" />
|
<ClInclude Include="coding\mpeg_bitreader.h" />
|
||||||
<ClInclude Include="coding\mpeg_decoder.h" />
|
<ClInclude Include="coding\mpeg_decoder.h" />
|
||||||
<ClInclude Include="coding\vorbis_bitreader.h" />
|
<ClInclude Include="coding\vorbis_bitreader.h" />
|
||||||
@ -328,6 +329,7 @@
|
|||||||
<ClCompile Include="meta\baf.c" />
|
<ClCompile Include="meta\baf.c" />
|
||||||
<ClCompile Include="meta\bgw.c" />
|
<ClCompile Include="meta\bgw.c" />
|
||||||
<ClCompile Include="meta\bik.c" />
|
<ClCompile Include="meta\bik.c" />
|
||||||
|
<ClCompile Include="meta\bigrp.c" />
|
||||||
<ClCompile Include="meta\bkhd.c" />
|
<ClCompile Include="meta\bkhd.c" />
|
||||||
<ClCompile Include="meta\bmp_konami.c" />
|
<ClCompile Include="meta\bmp_konami.c" />
|
||||||
<ClCompile Include="meta\bnk_relic.c" />
|
<ClCompile Include="meta\bnk_relic.c" />
|
||||||
@ -643,6 +645,8 @@
|
|||||||
<ClCompile Include="coding\g7221_decoder_lib.c" />
|
<ClCompile Include="coding\g7221_decoder_lib.c" />
|
||||||
<ClCompile Include="coding\hca_decoder.c" />
|
<ClCompile Include="coding\hca_decoder.c" />
|
||||||
<ClCompile Include="coding\hca_decoder_clhca.c" />
|
<ClCompile Include="coding\hca_decoder_clhca.c" />
|
||||||
|
<ClCompile Include="coding\ice_decoder.c" />
|
||||||
|
<ClCompile Include="coding\ice_decoder_icelib.c" />
|
||||||
<ClCompile Include="coding\ima_decoder.c" />
|
<ClCompile Include="coding\ima_decoder.c" />
|
||||||
<ClCompile Include="coding\imuse_decoder.c" />
|
<ClCompile Include="coding\imuse_decoder.c" />
|
||||||
<ClCompile Include="coding\l5_555_decoder.c" />
|
<ClCompile Include="coding\l5_555_decoder.c" />
|
||||||
|
@ -266,6 +266,9 @@
|
|||||||
<ClInclude Include="coding\hca_decoder_clhca.h">
|
<ClInclude Include="coding\hca_decoder_clhca.h">
|
||||||
<Filter>coding\Header Files</Filter>
|
<Filter>coding\Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="coding\hca_decoder_icelib.h">
|
||||||
|
<Filter>coding\Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="coding\mpeg_bitreader.h">
|
<ClInclude Include="coding\mpeg_bitreader.h">
|
||||||
<Filter>coding\Header Files</Filter>
|
<Filter>coding\Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -1369,6 +1372,12 @@
|
|||||||
<ClCompile Include="coding\hca_decoder_clhca.c">
|
<ClCompile Include="coding\hca_decoder_clhca.c">
|
||||||
<Filter>coding\Source Files</Filter>
|
<Filter>coding\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="coding\ice_decoder.c">
|
||||||
|
<Filter>coding\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="coding\ice_decoder_icelib.c">
|
||||||
|
<Filter>coding\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="coding\ima_decoder.c">
|
<ClCompile Include="coding\ima_decoder.c">
|
||||||
<Filter>coding\Source Files</Filter>
|
<Filter>coding\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1879,6 +1888,9 @@
|
|||||||
<ClCompile Include="meta\bik.c">
|
<ClCompile Include="meta\bik.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="meta\bigrp.c">
|
||||||
|
<Filter>meta\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="meta\bkhd.c">
|
<ClCompile Include="meta\bkhd.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
110
src/meta/bigrp.c
Normal file
110
src/meta/bigrp.c
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#include "meta.h"
|
||||||
|
#include "../coding/coding.h"
|
||||||
|
#include "../coding/ice_decoder_icelib.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* .BIGRP - from Inti Creates "ICE"/"Imperial" engine [Blaster Master Zero 2 (SW), Gunvolt 3 (SW)] */
|
||||||
|
VGMSTREAM* init_vgmstream_bigrp(STREAMFILE* sf) {
|
||||||
|
VGMSTREAM* vgmstream = NULL;
|
||||||
|
uint32_t header_size, entry_size, stream_size;
|
||||||
|
int total_subsongs, target_subsong = sf->stream_index;
|
||||||
|
int codec, channels, loop_flag, sample_rate;
|
||||||
|
int32_t loop_start, num_samples;
|
||||||
|
|
||||||
|
|
||||||
|
/* checks */
|
||||||
|
|
||||||
|
/* simple checks to avoid opening the lib if possible
|
||||||
|
* early games use smaller sizes [Bloodstained COTM (Vita), Mighty Gunvolt Burst (PC)] */
|
||||||
|
header_size = read_u32le(0x00,sf);
|
||||||
|
if (read_u32le(0x00,sf) != 0x0c && read_u32le(0x00,sf) != 0x10)
|
||||||
|
goto fail;
|
||||||
|
entry_size = read_u32le(0x04,sf);
|
||||||
|
if (entry_size != 0x34 && entry_size != 0x40)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (!check_extensions(sf, "bigrp"))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (target_subsong == 0) target_subsong = 1;
|
||||||
|
total_subsongs = read_s32le(0x08,sf);
|
||||||
|
if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail;
|
||||||
|
|
||||||
|
|
||||||
|
/* could read all this from the lib, meh */
|
||||||
|
{
|
||||||
|
uint32_t offset = header_size + entry_size * (target_subsong - 1);
|
||||||
|
|
||||||
|
/* 00: hash */
|
||||||
|
/* 04: group? */
|
||||||
|
codec = read_u32le(offset + 0x08, sf);
|
||||||
|
|
||||||
|
switch(codec) {
|
||||||
|
case 0x00: /* range [BMZ2 (SW), Bloodstained COTM (Vita), BMZ1 (PS4)] */
|
||||||
|
case 0x03:
|
||||||
|
sample_rate = read_s32le(offset + 0x0c, sf);
|
||||||
|
channels = read_u8 (offset + 0x10, sf);
|
||||||
|
/* 0x11: spf */
|
||||||
|
/* 0x12: unknown (volume?) */
|
||||||
|
loop_flag = read_u32le(offset + 0x14, sf);
|
||||||
|
/* 0x18: frame codes */
|
||||||
|
loop_start = read_s32le(offset + 0x1c, sf);
|
||||||
|
stream_size = read_u32le(offset + 0x20, sf); /* intro block */
|
||||||
|
/* 0x24: intro offset */
|
||||||
|
num_samples = read_s32le(offset + 0x28, sf) + loop_start;
|
||||||
|
stream_size = read_u32le(offset + 0x2c, sf) + stream_size; /* body block */
|
||||||
|
/* 0x30: body offset */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* dummy to avoid breaking some files that mix codecs with midi */
|
||||||
|
channels = 1;
|
||||||
|
sample_rate = 48000;
|
||||||
|
loop_flag = 0;
|
||||||
|
loop_start = 0;
|
||||||
|
num_samples = sample_rate;
|
||||||
|
stream_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
vgmstream->meta_type = meta_BIGRP;
|
||||||
|
vgmstream->sample_rate = sample_rate;
|
||||||
|
vgmstream->num_samples = num_samples;
|
||||||
|
vgmstream->loop_start_sample = loop_start;
|
||||||
|
vgmstream->loop_end_sample = num_samples;
|
||||||
|
vgmstream->num_streams = total_subsongs;
|
||||||
|
vgmstream->stream_size = stream_size;
|
||||||
|
|
||||||
|
switch(codec) {
|
||||||
|
case 0x00:
|
||||||
|
case 0x03:
|
||||||
|
vgmstream->codec_data = init_ice(sf, target_subsong);
|
||||||
|
if (!vgmstream->codec_data) goto fail;
|
||||||
|
vgmstream->coding_type = codec == 0x00 ? coding_ICE_RANGE : coding_ICE_DCT;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x01:
|
||||||
|
case 0x02:
|
||||||
|
vgmstream->coding_type = coding_SILENCE;
|
||||||
|
snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "[%s]", (codec == 0x01 ? "data" : "midi"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (!vgmstream_open_stream(vgmstream, sf, 0x00))
|
||||||
|
// goto fail;
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -991,4 +991,6 @@ VGMSTREAM* init_vgmstream_sndz(STREAMFILE* sf);
|
|||||||
|
|
||||||
VGMSTREAM* init_vgmstream_vab(STREAMFILE* sf);
|
VGMSTREAM* init_vgmstream_vab(STREAMFILE* sf);
|
||||||
|
|
||||||
|
VGMSTREAM* init_vgmstream_bigrp(STREAMFILE* sf);
|
||||||
|
|
||||||
#endif /*_META_H*/
|
#endif /*_META_H*/
|
||||||
|
@ -525,6 +525,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
|
|||||||
init_vgmstream_bw_riff_mp3,
|
init_vgmstream_bw_riff_mp3,
|
||||||
init_vgmstream_sndz,
|
init_vgmstream_sndz,
|
||||||
init_vgmstream_vab,
|
init_vgmstream_vab,
|
||||||
|
init_vgmstream_bigrp,
|
||||||
|
|
||||||
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
|
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
|
||||||
init_vgmstream_agsc,
|
init_vgmstream_agsc,
|
||||||
|
@ -185,6 +185,8 @@ typedef enum {
|
|||||||
coding_RELIC, /* Relic Codec (DCT-based) */
|
coding_RELIC, /* Relic Codec (DCT-based) */
|
||||||
coding_CRI_HCA, /* CRI High Compression Audio (MDCT-based) */
|
coding_CRI_HCA, /* CRI High Compression Audio (MDCT-based) */
|
||||||
coding_TAC, /* tri-Ace Codec (MDCT-based) */
|
coding_TAC, /* tri-Ace Codec (MDCT-based) */
|
||||||
|
coding_ICE_RANGE, /* Inti Creates "range" codec */
|
||||||
|
coding_ICE_DCT, /* Inti Creates "DCT" codec */
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
coding_OGG_VORBIS, /* Xiph Vorbis with Ogg layer (MDCT-based) */
|
coding_OGG_VORBIS, /* Xiph Vorbis with Ogg layer (MDCT-based) */
|
||||||
@ -765,6 +767,7 @@ typedef enum {
|
|||||||
meta_TT_AD,
|
meta_TT_AD,
|
||||||
meta_SNDZ,
|
meta_SNDZ,
|
||||||
meta_VAB,
|
meta_VAB,
|
||||||
|
meta_BIGRP,
|
||||||
|
|
||||||
} meta_t;
|
} meta_t;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user