diff --git a/src/formats.c b/src/formats.c
index 5b07351f..ad468ca8 100644
--- a/src/formats.c
+++ b/src/formats.c
@@ -266,6 +266,7 @@ static const char* extension_list[] = {
"l",
"l00", //txth/reserved [Disney's Dinosaur (PS2)]
"laac", //fake extension for .aac (tri-Ace)
+ "ladpcm", //not fake
"laif", //fake extension for .aif (various)
"laiff", //fake extension for .aiff
"laifc", //fake extension for .aifc
@@ -1364,7 +1365,8 @@ static const meta_info meta_info_list[] = {
{meta_BNK_RELIC, "Relic BNK header"},
{meta_XSH_XSD_XSS, "Treyarch XSH+XSD/XSS header"},
{meta_PSB, "M2 PSB header"},
- {meta_LOPU, "French-Break LOPU header"},
+ {meta_LOPU_FB, "French-Bread LOPU header"},
+ {meta_LPCM_FB, "French-Bread LPCM header"},
};
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj
index f25dfba9..7fceeb0a 100644
--- a/src/libvgmstream.vcxproj
+++ b/src/libvgmstream.vcxproj
@@ -215,7 +215,8 @@
-
+
+
diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters
index 884630f0..c599c988 100644
--- a/src/libvgmstream.vcxproj.filters
+++ b/src/libvgmstream.vcxproj.filters
@@ -1903,7 +1903,10 @@
meta\Source Files
-
+
+ meta\Source Files
+
+
meta\Source Files
diff --git a/src/meta/lopu.c b/src/meta/lopu_fb.c
similarity index 88%
rename from src/meta/lopu.c
rename to src/meta/lopu_fb.c
index 9d896a3e..f6285319 100644
--- a/src/meta/lopu.c
+++ b/src/meta/lopu_fb.c
@@ -2,11 +2,11 @@
#include "../coding/coding.h"
-/* LOPU - French-Bread's Opus [Melty Blood: Type Lumina (Switch)] */
-VGMSTREAM* init_vgmstream_lopu(STREAMFILE* sf) {
+/* LOPU - French-Bread's Opus [Melty Blood: Type Lumina (Switch)] */
+VGMSTREAM* init_vgmstream_lopu_fb(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
- int loop_flag, channels, sample_rate;
uint32_t start_offset, data_size;
+ int loop_flag, channels, sample_rate;
int32_t num_samples, loop_start, loop_end, skip;
/* checks */
@@ -18,7 +18,7 @@ VGMSTREAM* init_vgmstream_lopu(STREAMFILE* sf) {
goto fail;
start_offset = read_u32le(0x04, sf);
- sample_rate = read_u32le(0x08, sf);
+ sample_rate = read_s32le(0x08, sf);
channels = read_s16le(0x0c, sf);
/* 0x10: ? (1984) */
num_samples = read_s32le(0x14, sf);
@@ -37,7 +37,7 @@ VGMSTREAM* init_vgmstream_lopu(STREAMFILE* sf) {
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
- vgmstream->meta_type = meta_LOPU;
+ vgmstream->meta_type = meta_LOPU_FB;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start;
diff --git a/src/meta/lpcm_fb.c b/src/meta/lpcm_fb.c
new file mode 100644
index 00000000..0907c8ee
--- /dev/null
+++ b/src/meta/lpcm_fb.c
@@ -0,0 +1,61 @@
+#include "meta.h"
+#include "../coding/coding.h"
+
+
+/* LPCM - French-Bread's DSP [Melty Blood: Type Lumina (Switch)] */
+VGMSTREAM* init_vgmstream_lpcm_fb(STREAMFILE* sf) {
+ VGMSTREAM* vgmstream = NULL;
+ uint32_t start_offset;
+ int loop_flag, channels, sample_rate;
+ int32_t num_samples;
+
+ /* checks */
+ if (!is_id32be(0x00, sf, "LPCM"))
+ goto fail;
+
+ /* .ladpcm: real extension (honest) */
+ if (!check_extensions(sf, "ladpcm"))
+ goto fail;
+
+ /* 0x04: dsp offset (0x20) */
+ if (read_u32le(0x04, sf) != 0x20)
+ goto fail;
+
+ num_samples = read_s32le(0x20, sf);
+ /* 0x24: nibbles? */
+ sample_rate = read_s32le(0x28, sf);
+ /* 0x2c: 0? */
+ /* 0x30: 2? */
+ /* 0x34: nibbles? */
+ /* 0x38: 2? */
+ if (read_u32le(0x38, sf) != 2)
+ goto fail;
+
+ channels = 1;
+ loop_flag = 0;
+
+ start_offset = 0x78; /* could be 0x80 but this is closer to num_samples */
+
+
+ /* build the VGMSTREAM */
+ vgmstream = allocate_vgmstream(channels, loop_flag);
+ if (!vgmstream) goto fail;
+
+ vgmstream->meta_type = meta_LPCM_FB;
+ vgmstream->sample_rate = sample_rate;
+ vgmstream->num_samples = num_samples;
+
+ vgmstream->coding_type = coding_NGC_DSP;
+ vgmstream->layout_type = layout_none;
+
+ dsp_read_coefs_le(vgmstream, sf, 0x3c, 0);
+ /* 0x5c: hist? */
+
+
+ if (!vgmstream_open_stream(vgmstream, sf, start_offset))
+ goto fail;
+ return vgmstream;
+fail:
+ close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/src/meta/meta.h b/src/meta/meta.h
index 5037602d..c2e097fa 100644
--- a/src/meta/meta.h
+++ b/src/meta/meta.h
@@ -964,6 +964,8 @@ VGMSTREAM* init_vgmstream_xsh_xsd_xss(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_psb(STREAMFILE* sf);
-VGMSTREAM* init_vgmstream_lopu(STREAMFILE* sf);
+VGMSTREAM* init_vgmstream_lopu_fb(STREAMFILE* sf);
+
+VGMSTREAM* init_vgmstream_lpcm_fb(STREAMFILE* sf);
#endif /*_META_H*/
diff --git a/src/vgmstream.c b/src/vgmstream.c
index 95bf6bd8..c42bced8 100644
--- a/src/vgmstream.c
+++ b/src/vgmstream.c
@@ -527,7 +527,8 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_bnk_relic,
init_vgmstream_xsh_xsd_xss,
init_vgmstream_psb,
- init_vgmstream_lopu,
+ init_vgmstream_lopu_fb,
+ init_vgmstream_lpcm_fb,
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */
diff --git a/src/vgmstream.h b/src/vgmstream.h
index 3aaf9e59..19684b64 100644
--- a/src/vgmstream.h
+++ b/src/vgmstream.h
@@ -747,7 +747,8 @@ typedef enum {
meta_BNK_RELIC,
meta_XSH_XSD_XSS,
meta_PSB,
- meta_LOPU,
+ meta_LOPU_FB,
+ meta_LPCM_FB,
} meta_t;