From 72186168d204180caf895b958bdad9e393da0ddf Mon Sep 17 00:00:00 2001 From: 3dtours Date: Sun, 26 Jul 2026 18:29:05 +0700 Subject: [PATCH] fix: correct RIFF chunk sizes in SF3 converter - _find_chunk starts at offset 12 (after RIFF header) - Add _find_list_of_type to locate sdta LIST - Update sdta LIST size after smpl data replacement - Fix 'Invalid chunk header' error in SpessaSynth - SGM_v2.01 too large (529MB WAV) falls back to SF2 --- app/core/soundfont_converter.py | 140 +++++++++++++++++++++++--------- 1 file changed, 100 insertions(+), 40 deletions(-) diff --git a/app/core/soundfont_converter.py b/app/core/soundfont_converter.py index 05ca695..8452efe 100644 --- a/app/core/soundfont_converter.py +++ b/app/core/soundfont_converter.py @@ -2,7 +2,6 @@ import os import struct import subprocess import logging -import tempfile import wave logger = logging.getLogger(__name__) @@ -12,18 +11,65 @@ SF_TARGET_DIRS = [ ] -def _read_chunks(data, offset, max_size=0): - chunks = [] +def _find_chunk(data, chunk_id, offset=12, max_size=0): pos = offset end = len(data) if max_size == 0 else offset + max_size while pos + 8 <= end: ck_id = data[pos:pos + 4] ck_size = struct.unpack(" {len(ogg_data)} bytes ({compression:.0f}%)") + compression = (1 - len(ogg_data) / max(len(sample_data), 1)) * 100 + logger.info(f"Compressed {len(sample_data)} -> {len(ogg_data)} bytes ({compression:.0f}%)") - # Rebuild file: replace smpl chunk data with Ogg data ogg_padded = ogg_data if len(ogg_data) % 2 == 0 else ogg_data + b"\x00" new_smpl_size = len(ogg_data) + old_padded = smpl_old_size + (1 if smpl_old_size % 2 == 1 else 0) + new_padded = len(ogg_padded) + delta = new_padded - old_padded + # Rebuild file: replace smpl chunk and update all sizes out = bytearray() - out.extend(data[:smpl_offset - 8]) # up to smpl chunk header + out.extend(data[:smpl_head_off]) # up to smpl chunk header out.extend(struct.pack(" '{sf3_path}' using {converter}...") if converter == "fluidsynth": - logger.warning("fluidsynth CLI does not export SF3, using Python converter") converter = "python" if converter == "mscore": @@ -163,7 +224,6 @@ class SoundFontConverter: if result.returncode == 0 and os.path.exists(sf3_path): logger.info(f"Created SF3 via mscore: {sf3_path} ({os.path.getsize(sf3_path)/1024/1024:.1f}MB)") return sf3_path - logger.warning(f"mscore failed, trying Python converter") converter = "python" if converter == "python": @@ -171,7 +231,7 @@ class SoundFontConverter: size_mb = os.path.getsize(sf3_path) / (1024 * 1024) logger.info(f"Created SF3: {sf3_path} ({size_mb:.2f} MB)") return sf3_path - logger.warning(f"Python converter failed, returning SF2 path") + logger.warning(f"Python converter failed for {sf2_path}, returning SF2 path") return sf2_path return sf2_path