Support 32-bit integer PCM in RIFF

From masters for a Sonic Origins mod
This commit is contained in:
Adam Gashlin 2023-08-17 22:20:22 -07:00
parent 72f676e57d
commit 3a49c090a0
6 changed files with 31 additions and 0 deletions

View File

@ -367,6 +367,7 @@ int decode_get_samples_per_frame(VGMSTREAM* vgmstream) {
case coding_PCMFLOAT:
case coding_PCM24LE:
case coding_PCM24BE:
case coding_PCM32LE:
return 1;
#ifdef VGM_USE_VORBIS
case coding_OGG_VORBIS:
@ -594,6 +595,7 @@ int decode_get_frame_size(VGMSTREAM* vgmstream) {
case coding_ALAW:
return 0x01;
case coding_PCMFLOAT:
case coding_PCM32LE:
return 0x04;
case coding_PCM24LE:
case coding_PCM24BE:
@ -907,6 +909,13 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
}
break;
case coding_PCM32LE:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_pcm32le(&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
}
break;
case coding_NDS_IMA:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_nds_ima(&vgmstream->ch[ch], buffer+ch,

View File

@ -96,6 +96,7 @@ void decode_alaw(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing,
void decode_pcmfloat(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
void decode_pcm24le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm24be(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm32le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample);
int32_t pcm24_bytes_to_samples(size_t bytes, int channels);
int32_t pcm16_bytes_to_samples(size_t bytes, int channels);

View File

@ -238,11 +238,26 @@ void decode_pcm24le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspaci
}
}
void decode_pcm32le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t offset = stream->offset + i * 0x04;
int32_t v = read_s32le(offset, stream->streamfile);
outbuf[sample_count] = (v >> 16);
}
}
int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample) {
if (channels <= 0 || bits_per_sample <= 0) return 0;
return ((int64_t)bytes * 8) / channels / bits_per_sample;
}
int32_t pcm32_bytes_to_samples(size_t bytes, int channels) {
return pcm_bytes_to_samples(bytes, channels, 32);
}
int32_t pcm24_bytes_to_samples(size_t bytes, int channels) {
return pcm_bytes_to_samples(bytes, channels, 24);
}

View File

@ -765,6 +765,7 @@ static const coding_info coding_info_list[] = {
{coding_PCMFLOAT, "32-bit float PCM"},
{coding_PCM24LE, "24-bit Little Endian PCM"},
{coding_PCM24BE, "24-bit Big Endian PCM"},
{coding_PCM32LE, "32-bit Little Endian PCM"},
{coding_CRI_ADX, "CRI ADX 4-bit ADPCM"},
{coding_CRI_ADX_fixed, "CRI ADX 4-bit ADPCM (fixed coefficients)"},

View File

@ -146,6 +146,9 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk
case 0x0001: /* PCM */
switch (fmt->bps) {
case 32:
fmt->coding_type = coding_PCM32LE;
break;
case 24: /* Omori (PC) */
fmt->coding_type = coding_PCM24LE;
break;
@ -701,6 +704,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
/* samples, codec init (after setting coding to ensure proper close on failure) */
switch (fmt.coding_type) {
case coding_PCM32LE:
case coding_PCM24LE:
case coding_PCM16LE:
case coding_PCM8_U:

View File

@ -26,6 +26,7 @@ typedef enum {
coding_PCMFLOAT, /* 32-bit float PCM */
coding_PCM24LE, /* little endian 24-bit PCM */
coding_PCM24BE, /* big endian 24-bit PCM */
coding_PCM32LE, /* little endian 32-bit PCM */
/* ADPCM */
coding_CRI_ADX, /* CRI ADX */