From 6642607d0e304258d50c7177ba6fe46c0fe4bfaa Mon Sep 17 00:00:00 2001 From: bnnm Date: Fri, 18 Aug 2017 18:54:21 +0200 Subject: [PATCH] Add FSB5 PCMFLOAT + decoder [Anima Gate of Memories (PC)] --- src/coding/coding.h | 1 + src/coding/pcm_decoder.c | 16 ++++++++++++++++ src/formats.c | 1 + src/meta/fsb5.c | 9 ++++++--- src/vgmstream.c | 13 +++++++++++++ src/vgmstream.h | 8 +++++--- 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/coding/coding.h b/src/coding/coding.h index b6f5b761..baf35d17 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -63,6 +63,7 @@ void decode_pcm8_sb_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels void decode_pcm8_unsigned_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_pcm8_unsigned(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_ulaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_pcmfloat(VGMSTREAM *vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample); /* psx_decoder */ diff --git a/src/coding/pcm_decoder.c b/src/coding/pcm_decoder.c index 2342582f..db3914e2 100644 --- a/src/coding/pcm_decoder.c +++ b/src/coding/pcm_decoder.c @@ -118,6 +118,22 @@ void decode_ulaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, } } +void decode_pcmfloat(VGMSTREAM *vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i, sample_count; + int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE; + + for (i=first_sample,sample_count=0; ioffset+i*4,stream->streamfile); + float sample_float; + int sample_pcm; + + memcpy(&sample_float, &sample_int, 4); /* maybe unorthodox but simplest */ + sample_pcm = floor(sample_float * 32767.f + .5f); + + outbuf[sample_count] = clamp16(sample_pcm); + } +} + size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample) { return bytes / channels / (bits_per_sample/8); } diff --git a/src/formats.c b/src/formats.c index 68cb7e3a..02c6d8b6 100644 --- a/src/formats.c +++ b/src/formats.c @@ -404,6 +404,7 @@ static const coding_info coding_info_list[] = { {coding_PCM8_int, "8-bit PCM with 1 byte interleave"}, {coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave"}, {coding_ULAW, "8-bit u-Law"}, + {coding_PCMFLOAT, "32-bit float PCM"}, {coding_CRI_ADX, "CRI ADX 4-bit ADPCM"}, {coding_CRI_ADX_exp, "CRI ADX 4-bit ADPCM with exponential scale"}, {coding_CRI_ADX_fixed, "CRI ADX 4-bit ADPCM with fixed coefficients"}, diff --git a/src/meta/fsb5.c b/src/meta/fsb5.c index ebf7b7cd..8d0c5ba7 100644 --- a/src/meta/fsb5.c +++ b/src/meta/fsb5.c @@ -212,10 +212,13 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { case 0x04: /* FMOD_SOUND_FORMAT_PCM32 */ goto fail; - case 0x05: /* FMOD_SOUND_FORMAT_PCMFLOAT */ - goto fail; + case 0x05: /* FMOD_SOUND_FORMAT_PCMFLOAT [Anima - Gate of Memories (PC)]*/ + vgmstream->coding_type = coding_PCMFLOAT; + vgmstream->layout_type = (ChannelCount == 1) ? layout_none : layout_interleave; + vgmstream->interleave_block_size = 0x04; + break; - case 0x06: /* FMOD_SOUND_FORMAT_GCADPCM */ + case 0x06: /* FMOD_SOUND_FORMAT_GCADPCM [Sonic Boom - Fire and Ice (3DS)] */ if (ChannelCount == 1) { vgmstream->layout_type = layout_none; } else { diff --git a/src/vgmstream.c b/src/vgmstream.c index 7e7f34b9..b064776e 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -975,6 +975,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_PCM8_SB_int: case coding_PCM8_U_int: case coding_ULAW: + case coding_PCMFLOAT: + return 1; #ifdef VGM_USE_VORBIS case coding_ogg_vorbis: case coding_VORBIS_custom: @@ -1128,6 +1130,9 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_PCM8_SB_int: case coding_PCM8_U_int: case coding_ULAW: + return 1; + case coding_PCMFLOAT: + return 4; case coding_SDX2: case coding_SDX2_int: case coding_CBD2: @@ -1358,6 +1363,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do); } break; + case coding_PCMFLOAT: + for (chan=0;chanchannels;chan++) { + decode_pcmfloat(vgmstream, &vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_NDS_IMA: for (chan=0;chanchannels;chan++) { decode_nds_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, diff --git a/src/vgmstream.h b/src/vgmstream.h index 7bc85e0e..59930df2 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -72,21 +72,23 @@ enum { STREAM_NAME_SIZE = 255 }; /* reasonable max */ /* The encoding type specifies the format the sound data itself takes */ typedef enum { - /* 16-bit PCM */ + /* PCM */ coding_PCM16LE, /* little endian 16-bit PCM */ coding_PCM16LE_int, /* little endian 16-bit PCM with sample-level interleave */ coding_PCM16LE_XOR_int, /* little endian 16-bit PCM with sample-level xor */ coding_PCM16BE, /* big endian 16-bit PCM */ - /* 8-bit PCM */ coding_PCM8, /* 8-bit PCM */ coding_PCM8_int, /* 8-Bit PCM with sample-level interleave */ coding_PCM8_U, /* 8-bit PCM, unsigned (0x80 = 0) */ coding_PCM8_U_int, /* 8-bit PCM, unsigned (0x80 = 0) with sample-level interleave */ coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement) with sample-level interleave */ + coding_ULAW, /* 8-bit u-Law (non-linear PCM) */ - /* 4-bit ADPCM */ + coding_PCMFLOAT, /* 32 bit float PCM */ + + /* ADPCM */ coding_CRI_ADX, /* CRI ADX */ coding_CRI_ADX_fixed, /* CRI ADX, encoding type 2 with fixed coefficients */ coding_CRI_ADX_exp, /* CRI ADX, encoding type 4 with exponential scale */