Skip to content

Add sf2 (soundfont) support to wildmidi - #270

Merged
psi29a merged 20 commits into
masterfrom
sf2-support
Jul 7, 2026
Merged

Add sf2 (soundfont) support to wildmidi#270
psi29a merged 20 commits into
masterfrom
sf2-support

Conversation

@psi29a

@psi29a psi29a commented Jul 6, 2026

Copy link
Copy Markdown
Member
Screenshot 2026-07-06 at 16 33 10

The existing -c / --config option accepts the soundfont directly, because detection happens by file magic (RIFF/sfbk), not extension or option:

# soundfont straight on the CLI
wildmidi -c ~/soundfonts/FluidR3_GM.sf2 song.mid

# or via a config file containing a soundfont line
wildmidi -c /etc/timidity/fluidr3_gm.cfg song.mid

Shouldu close #8

Summary by CodeRabbit

  • New Features
    • Added optional SoundFont2 (SF2) playback via TinySoundFont, including SF2 detection/loading, SF2-backed MIDI rendering, and bounded “release tail” continuation.
    • Introduced WANT_SF2 build option and a soundfont configuration directive to load an SF2.
  • Bug Fixes
    • Improved allocation safety using overflow-checked resizing and more consistent ENOMEM-style error handling; strengthened initialization and shutdown cleanup when SF2 is enabled.
  • Documentation
    • Added SF2.md plus vendoring/licensing and setup guidance for TinySoundFont; updated README and changelog to version 0.5.0.
  • Chores
    • Version bumped to 0.5.0.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cf3ef5ea-d0a7-4310-a3f1-e4d2b7426d78

📥 Commits

Reviewing files that changed from the base of the PR and between 36a3a9d and 74fb978.

📒 Files selected for processing (13)
  • CMakeLists.txt
  • README.md
  • amiga/config.h
  • android/jni/config.h
  • djgpp/config.h
  • extern/TinySoundFont/tsf.h
  • include/wildmidi_lib.h
  • macosx/config.h
  • mingw/config.h
  • msvc/config.h
  • os2/config.h
  • src/internal_midi.c
  • src/sf2.c
💤 Files with no reviewable changes (1)
  • src/sf2.c
✅ Files skipped from review due to trivial changes (5)
  • os2/config.h
  • amiga/config.h
  • README.md
  • mingw/config.h
  • android/jni/config.h
🚧 Files skipped from review as they are similar to previous changes (2)
  • extern/TinySoundFont/tsf.h
  • src/internal_midi.c

📝 Walkthrough

Walkthrough

This PR adds optional SF2 playback support via TinySoundFont, gated by a new build option. It introduces the SF2 API and implementation, wires SF2 synth instances into MIDI handling and output, hardens several realloc-based paths, and updates version metadata and documentation.

Changes

SF2 Support

Layer / File(s) Summary
Build configuration for WANT_SF2
CMakeLists.txt, include/config.h.cmake, src/CMakeLists.txt
Adds the WANT_SF2 option, defines WILDMIDI_SF2, checks for vendored tsf.h, and conditionally builds SF2 sources.
Vendored TinySoundFont dependency
extern/TinySoundFont/*
Adds the vendored TinySoundFont header, license, and README with the full embedded implementation.
SF2 public API and struct field
include/sf2.h, include/internal_midi.h
Declares the SF2 interface and adds an SF2 synth pointer to struct _mdi.
Core SF2 synth implementation
src/sf2.c
Implements SF2 load/unload, synth lifecycle, event translation, voice counting, and rendering.
MDI lifecycle wiring for SF2 synth
src/internal_midi.c
Creates and frees per-handle SF2 synth instances and updates MIDI event-buffer/copyright growth checks.
Library init, config, output routing, and shutdown
src/wildmidi_lib.c
Adds soundfont config parsing, SF2-aware init and shutdown, an SF2 output path, routing, and realloc hardening.
Allocation failure handling in event/patch paths
src/internal_midi.c, src/patches.c
Reworks realloc-based patch, event-pool, and copyright buffer growth to fail safely.
SF2 documentation
docs/SF2.md
Documents the SF2 design, flow, mapping, build notes, and non-goals.
Version metadata updates
README.md, include/wildmidi_lib.h, amiga/config.h, android/jni/config.h, djgpp/config.h, macosx/config.h, mingw/config.h, msvc/config.h, os2/config.h
Bumps the project/library version and platform package version strings to 0.5.0.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant WildMidi
  participant SF2
  participant TinySoundFont

  App->>WildMidi: WildMidi_Init(config_file)
  WildMidi->>SF2: _WM_SF2_Load(data)
  SF2->>TinySoundFont: tsf_load_memory / tsf_copy
  App->>WildMidi: WildMidi_GetOutput()
  WildMidi->>SF2: WM_GetOutput_SF2()
  loop per event
    WildMidi->>SF2: _WM_SF2_Event(synth, mdi, event)
    SF2->>TinySoundFont: tsf_channel_* / tsf_note_on/off
  end
  WildMidi->>SF2: _WM_SF2_Render(synth, out, frames)
  SF2->>TinySoundFont: tsf_render_short(chunked)
  App->>WildMidi: WildMidi_Shutdown()
  WildMidi->>SF2: _WM_SF2_Unload()
Loading

Related Issues: #8 — Soundfont2 support

Suggested labels: enhancement, build

Suggested reviewers: none

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly states the main change: adding SF2 support to WildMIDI.
Linked Issues check ✅ Passed The PR implements SF2 playback and config-file loading, satisfying issue #8's SoundFont2 support requirement.
Out of Scope Changes check ✅ Passed The changes are largely in service of SF2 support, with version bumps and vendored TinySoundFont being relevant support work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sf2-support

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@psi29a

psi29a commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

@sezero should I include the lib in /extern or just leave it to cmake to fetch it for us?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (1)
CMakeLists.txt (1)

308-318: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

WANT_SF2 defaults to ON, making a network fetch mandatory for default builds.

With WANT_SF2 defaulting ON, every default configure now performs a FetchContent git clone of TinySoundFont from GitHub. This silently introduces a hard network dependency for a build that previously worked fully offline, which breaks sandboxed CI, air-gapped builds, and distro packaging pipelines (Debian/Fedora and similar policies explicitly forbid network access during package builds). All of the project's other optional audio backends (WANT_ALSA, WANT_OSS, etc.) rely on FIND_PACKAGE(... REQUIRED) against locally installed dependencies rather than fetching source over the network, so this is a new class of build dependency for the project.

Consider defaulting WANT_SF2 to OFF, or at least trying find_package/an existing local checkout first and falling back to FetchContent only when explicitly requested.

♻️ Suggested default change
-OPTION(WANT_SF2 "SoundFont2 (SF2) support via TinySoundFont" ON)
+OPTION(WANT_SF2 "SoundFont2 (SF2) support via TinySoundFont" OFF)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CMakeLists.txt` around lines 308 - 318, The default SF2 backend setup in the
CMake configuration currently forces a network FetchContent download through
WANT_SF2, which should not happen in default builds. Update the WANT_SF2
handling in the CMakeLists logic around FetchContent_Declare(tinysoundfont) and
FetchContent_MakeAvailable so default configuration does not require GitHub
access; either switch WANT_SF2 to OFF by default or make the download path
conditional on an explicit opt-in and prefer a local find_package or existing
source checkout first.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/sf2.c`:
- Around line 70-72: _WM_SF2_Active is reading the shared WM_sf2 pointer without
the WM_sf2_lock used by _WM_SF2_Load, _WM_SF2_Unload, and _WM_SF2_NewSynth.
Update _WM_SF2_Active to take the same lock around the WM_sf2 NULL check, then
release it before returning, so the active-state check follows the file’s
existing locking discipline and cannot race with unload.
- Around line 47-59: Reject oversized soundfont buffers in _WM_SF2_Load before
passing the length to tsf_load_memory(). Add a check on the uint32_t size
argument to ensure it does not exceed INT_MAX, and return an error if it does,
then only cast to int after that guard. Keep the fix localized to _WM_SF2_Load
in src/sf2.c so the tsf_load_memory call never receives a wrapped negative
length.

In `@src/wildmidi_lib.c`:
- Around line 543-552: The config parsing failure path in the soundfont load
flow leaves the global SF2 state active after a successful _WM_SF2_Load(), so
add _WM_SF2_Unload() before returning from the failure cleanup in the config
loader logic. Update the failure branch around the _WM_SF2_Load call in the
config parsing routine so any later directive parse error also unloads the SF2
font, alongside the existing frees for sf2_buffer, sf2_path, patches,
config_dir, line_tokens, and config_buffer.
- Around line 2079-2084: Read mutable handle state only after acquiring the MIDI
lock in the output path. In the code around the current_event handling, move the
assignment from mdi->current_event to event so it happens after
_WM_Lock(&mdi->lock), keeping the state access inside the protected section and
preventing races with WildMidi_GetOutput() and seek-style operations.
- Around line 2088-2095: The realloc handling in the mix-buffer growth logic can
lose the original buffer if allocation fails. Update the `wildmidi` mix buffer
resize path around `mdi->mix_buffer` to store `realloc()` in a temporary
pointer, check for failure, and avoid overwriting the existing buffer when
allocation returns null. If the resize fails, unlock any held state and return
an error before any later use of `tmp_buffer` or `memset`, so the existing
buffer remains valid.
- Around line 1648-1667: The SF2 initialization path in WM_InitPatches() returns
early on _WM_BufferFile(), _WM_SF2_Load(), and WM_LoadConfig() failures without
cleaning up globals initialized earlier. Update the SF2 branch to perform the
same teardown on every failure path: free patch state initialized by
WM_InitPatches(), unload any SF2 data already loaded from a prior soundfont
directive, and release cfg_buffer before returning. Keep the cleanup centralized
around the WM_InitPatches()/WM_LoadConfig() flow and the _WM_SF2_Load() error
handling so all exit paths leave the library in a consistent state.

---

Nitpick comments:
In `@CMakeLists.txt`:
- Around line 308-318: The default SF2 backend setup in the CMake configuration
currently forces a network FetchContent download through WANT_SF2, which should
not happen in default builds. Update the WANT_SF2 handling in the CMakeLists
logic around FetchContent_Declare(tinysoundfont) and FetchContent_MakeAvailable
so default configuration does not require GitHub access; either switch WANT_SF2
to OFF by default or make the download path conditional on an explicit opt-in
and prefer a local find_package or existing source checkout first.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1650a9a1-93b9-41be-8558-3e23c70b8b6a

📥 Commits

Reviewing files that changed from the base of the PR and between e51ffa3 and b39488d.

📒 Files selected for processing (11)
  • CMakeLists.txt
  • docs/SF2.md
  • include/config.h.cmake
  • include/internal_midi.h
  • include/sf2.h
  • src/CMakeLists.txt
  • src/internal_midi.c
  • src/sf2.c
  • src/wildmidi_lib.c
  • test/CMakeLists.txt
  • test/test_sf2.c

Comment thread src/sf2.c
Comment thread src/sf2.c
Comment on lines +70 to +72
int _WM_SF2_Active(void) {
return (WM_sf2 != NULL);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

_WM_SF2_Active reads the shared WM_sf2 pointer without the lock used everywhere else.

_WM_SF2_Load/_WM_SF2_Unload/_WM_SF2_NewSynth all guard access to WM_sf2 with WM_sf2_lock, but _WM_SF2_Active reads it unguarded. This is inconsistent with the locking discipline established in this same file and can race with a concurrent _WM_SF2_Unload, yielding a stale/torn read of the "is SF2 active" status.

🔒 Suggested fix
 int _WM_SF2_Active(void) {
-    return (WM_sf2 != NULL);
+    int active;
+    _WM_Lock(&WM_sf2_lock);
+    active = (WM_sf2 != NULL);
+    _WM_Unlock(&WM_sf2_lock);
+    return active;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
int _WM_SF2_Active(void) {
return (WM_sf2 != NULL);
}
int _WM_SF2_Active(void) {
int active;
_WM_Lock(&WM_sf2_lock);
active = (WM_sf2 != NULL);
_WM_Unlock(&WM_sf2_lock);
return active;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/sf2.c` around lines 70 - 72, _WM_SF2_Active is reading the shared WM_sf2
pointer without the WM_sf2_lock used by _WM_SF2_Load, _WM_SF2_Unload, and
_WM_SF2_NewSynth. Update _WM_SF2_Active to take the same lock around the WM_sf2
NULL check, then release it before returning, so the active-state check follows
the file’s existing locking discipline and cannot race with unload.

Comment thread src/wildmidi_lib.c
Comment on lines +543 to +552
sf2_buffer = (uint8_t *) _WM_BufferFile(sf2_path, &sf2_size);
if ((sf2_buffer == NULL) || (_WM_SF2_Load(sf2_buffer, sf2_size) == -1)) {
_WM_GLOBAL_ERROR(WM_ERR_INVALID_ARG, "(unable to load soundfont)", 0);
_WM_FreeBufferFile(sf2_buffer);
free(sf2_path);
WM_FreePatches();
free(config_dir);
free(line_tokens);
_WM_FreeBufferFile(config_buffer);
return (-1);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Unload SF2 state when config parsing fails after loading a soundfont.

A config can load a soundfont successfully, then fail on a later directive. The failure paths free patches/config buffers but leave the global SF2 font active, which can leak state into a subsequent init attempt. Add _WM_SF2_Unload() on config-load failure paths that occur after _WM_SF2_Load() may have succeeded.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/wildmidi_lib.c` around lines 543 - 552, The config parsing failure path
in the soundfont load flow leaves the global SF2 state active after a successful
_WM_SF2_Load(), so add _WM_SF2_Unload() before returning from the failure
cleanup in the config loader logic. Update the failure branch around the
_WM_SF2_Load call in the config parsing routine so any later directive parse
error also unloads the SF2 font, alongside the existing frees for sf2_buffer,
sf2_path, patches, config_dir, line_tokens, and config_buffer.

Comment thread src/wildmidi_lib.c
Comment thread src/wildmidi_lib.c Outdated
Comment thread src/wildmidi_lib.c

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.github/workflows/bsd.yml (1)

27-37: 🧹 Nitpick | 🔵 Trivial

Correctly adds git for FetchContent, but note new network dependency in CI.

Adding git alongside cmake is necessary since WANT_SF2 defaults to ON and TinySoundFont is fetched via FetchContent_Declare(... GIT_REPOSITORY ...). Without git, these BSD builds would fail to configure.

One operational note: this makes previously self-contained BSD CI jobs depend on outbound network access to github.com during the build step (cloning TinySoundFont inside the cross-platform-actions VM). If those sandboxed BSD VMs have restricted or flaky egress, this could introduce new CI flakiness/timeouts that didn't exist before.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/bsd.yml around lines 27 - 37, The BSD workflow change for
the OpenBSD and NetBSD matrix jobs now introduces a runtime dependency on
outbound GitHub access because WANT_SF2 pulls TinySoundFont via
FetchContent_Declare using a GIT_REPOSITORY. Keep git installed, and update the
BSD CI setup around the matrix entries so this network requirement is explicitly
handled or mitigated (for example by prefetching or caching the dependency in
the workflow) to avoid flaky configure-time failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In @.github/workflows/bsd.yml:
- Around line 27-37: The BSD workflow change for the OpenBSD and NetBSD matrix
jobs now introduces a runtime dependency on outbound GitHub access because
WANT_SF2 pulls TinySoundFont via FetchContent_Declare using a GIT_REPOSITORY.
Keep git installed, and update the BSD CI setup around the matrix entries so
this network requirement is explicitly handled or mitigated (for example by
prefetching or caching the dependency in the workflow) to avoid flaky
configure-time failures.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9bc82341-17f2-4193-815a-25ff1e06361c

📥 Commits

Reviewing files that changed from the base of the PR and between b39488d and 76b4d8a.

📒 Files selected for processing (1)
  • .github/workflows/bsd.yml

@sezero

sezero commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

@sezero should I include the lib

yes: that way, we can customize it as we see fit as necessary

or just leave it to cmake to fetch it for us?

please no

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/internal_midi.c`:
- Around line 552-565: The event allocation failure handling in
_WM_CheckEventMemoryPool is currently local-only and lets the setup path
continue with stale capacity, so thread the failure back through the event
creation flow instead of just returning. Update the midi_setup_* call chain and
any helper that writes into mdi->events so they can detect a failed resize from
_WM_CheckEventMemoryPool, stop advancing event_count, and abort the current
setup cleanly before any write occurs. Ensure the failure is propagated from the
allocation check through the event-setup helpers that consume it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3c3b6eda-e3e3-4f2a-b88e-1426d81fd2f5

📥 Commits

Reviewing files that changed from the base of the PR and between 76b4d8a and 164b71b.

📒 Files selected for processing (4)
  • src/internal_midi.c
  • src/patches.c
  • src/sf2.c
  • src/wildmidi_lib.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/sf2.c

Comment thread src/internal_midi.c Outdated
@psi29a

psi29a commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

@sezero should I include the lib

yes: that way, we can customize it as we see fit as necessary

Okay, vendered in /extern

I think this is worthy of a version bump; 0.5.0 or 1.0 or 1.5 ? :P

Comment thread src/internal_midi.c Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/internal_midi.c (1)

2172-2174: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Check the realloc length math before appending copyright data. old_len + 1 + tmp_length + 1 can wrap size_t, which would under-allocate the buffer before the later memcpy.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/internal_midi.c` around lines 2172 - 2174, The copyright append logic in
the internal MIDI handling path should guard against size_t overflow before
calling realloc. In the code that computes the new buffer size using old_len,
tmp_length, and the extra separator/terminator space, add an explicit overflow
check before the realloc on mdi->extra_info.copyright so the allocation cannot
wrap and under-allocate. Keep the fix localized to the copyright append block
and preserve the existing memcpy flow after the safe allocation succeeds.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CMakeLists.txt`:
- Around line 304-310: Guard the WANT_SF2 branch in CMakeLists.txt so
WILDMIDI_SF2 is only enabled on little-endian targets; this SF2 path uses
TinySoundFont via tsf.h and will misparse data on WORDS_BIGENDIAN builds. Update
the IF block around WANT_SF2 to check endianness before setting WILDMIDI_SF2,
and either disable SF2 with a fatal configuration error on big-endian systems or
add the required byte-swapping support in the TinySoundFont integration.

In `@src/internal_midi.c`:
- Line 1430: The terminal-event write in _WM_CheckEventMemoryPool is using the
growth helper too early, which blocks a valid final write when only the spare
terminator slot is missing. Update this path so it only requires
events[event_count] to be available, and preserve the existing valid slot when
event_count == events_size - 1 instead of returning early; keep the fix
localized around the _WM_CheckEventMemoryPool check in the terminal-event append
logic.
- Around line 555-558: The event pool growth in the internal MIDI path needs
overflow guards before resizing. In the `mdi->event_count`/`mdi->events_size`
expansion block inside the MIDI event handling code, check that `event_count +
1`, `events_size + MEM_CHUNK`, and the `realloc` byte-size calculation cannot
wrap before using them. If any arithmetic would overflow, fail safely instead of
allocating a smaller buffer and then writing to `mdi->events[mdi->event_count]`.

---

Outside diff comments:
In `@src/internal_midi.c`:
- Around line 2172-2174: The copyright append logic in the internal MIDI
handling path should guard against size_t overflow before calling realloc. In
the code that computes the new buffer size using old_len, tmp_length, and the
extra separator/terminator space, add an explicit overflow check before the
realloc on mdi->extra_info.copyright so the allocation cannot wrap and
under-allocate. Keep the fix localized to the copyright append block and
preserve the existing memcpy flow after the safe allocation succeeds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7b6da9af-116b-46bd-a2fd-92ce6fe8ef71

📥 Commits

Reviewing files that changed from the base of the PR and between 164b71b and 49a0c49.

📒 Files selected for processing (7)
  • CMakeLists.txt
  • docs/SF2.md
  • extern/TinySoundFont/LICENSE
  • extern/TinySoundFont/README.md
  • extern/TinySoundFont/tsf.h
  • src/internal_midi.c
  • test/CMakeLists.txt
✅ Files skipped from review due to trivial changes (3)
  • extern/TinySoundFont/README.md
  • extern/TinySoundFont/LICENSE
  • docs/SF2.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/CMakeLists.txt

Comment thread CMakeLists.txt
Comment thread extern/TinySoundFont/tsf.h Outdated
Comment thread src/internal_midi.c Outdated
Comment thread src/internal_midi.c Outdated
@psi29a

psi29a commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

@sezero please create a PR for this PR? :D

I wasn't done working on this branch ;)

@sezero

sezero commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

@sezero please create a PR for this PR? :D

I wasn't done working on this branch ;)

OK, sorry.

Here are four patches (in git am format) for clean compilation: patches.zip

Comment thread extern/TinySoundFont/tsf.h Dismissed
@psi29a

psi29a commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

@sezero please create a PR for this PR? :D
I wasn't done working on this branch ;)

OK, sorry.

Here are four patches (in git am format) for clean compilation: patches.zip

Strange, I thought you could open a PR to merge into sf2-support branch; that would have worked too.
Anyway, thank you! I applied the patches 1 at a time and marked you as author.

What do you think of a major or minor version bump?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
CMakeLists.txt (1)

71-71: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Consider defaulting WANT_SF2 to OFF.

This enables a brand-new, untrusted-binary-parsing feature (TinySoundFont/SF2) by default. Given the multiple portability/robustness fixes already needed for this vendored parser (per the commit history: missing SIZE_MAX, TSF_SQRTF check, array address-of misuse, missing powf/expf/sqrtf), it may be safer to ship this as opt-in until it has more field exposure, especially since it also introduces a new mandatory FATAL_ERROR dependency check (Line 322) for builds that previously had none.

diff
-OPTION(WANT_SF2 "SoundFont2 (SF2) support via TinySoundFont" ON)
+OPTION(WANT_SF2 "SoundFont2 (SF2) support via TinySoundFont" OFF)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CMakeLists.txt` at line 71, Default the WANT_SF2 option to OFF in the
CMakeLists.txt configuration so TinySoundFont/SF2 support is opt-in rather than
enabled by default. Update the OPTION declaration for WANT_SF2 accordingly, and
make sure any SF2-related enablement paths still work when users explicitly turn
it on, including the existing fatal dependency check tied to the SF2 build path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@CMakeLists.txt`:
- Line 71: Default the WANT_SF2 option to OFF in the CMakeLists.txt
configuration so TinySoundFont/SF2 support is opt-in rather than enabled by
default. Update the OPTION declaration for WANT_SF2 accordingly, and make sure
any SF2-related enablement paths still work when users explicitly turn it on,
including the existing fatal dependency check tied to the SF2 build path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 159724fe-42f6-4b09-9cef-51b97e0e43ab

📥 Commits

Reviewing files that changed from the base of the PR and between 74d6b85 and 36a3a9d.

📒 Files selected for processing (5)
  • CMakeLists.txt
  • extern/TinySoundFont/tsf.h
  • include/config.h.cmake
  • src/internal_midi.c
  • src/sf2.c
🚧 Files skipped from review as they are similar to previous changes (3)
  • extern/TinySoundFont/tsf.h
  • src/sf2.c
  • src/internal_midi.c

@sezero

sezero commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Here is the second set of patches, again in git am format, to fix build errors and add big endian support: patches2.zip

@sezero

sezero commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What do you think of a major or minor version bump?

0.5.0 seems reasonable to me. (Even 6c40712 (PR/254) might be considered enough of a behavior change..)

@psi29a

psi29a commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

Here is the second set of patches, again in git am format, to fix build errors and add big endian support: patches2.zip

Do you plan on upstreaming these to the project?

@sezero

sezero commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Do you plan on upstreaming these to the project?

Haven't considered it. Should I do it?

@psi29a

psi29a commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

Do you plan on upstreaming these to the project?

Haven't considered it. Should I do it?

Yes please :)

Let's be good neighbours.

@psi29a

psi29a commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

Ready for merge?

@sezero

sezero commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Ready for merge?

I guess.

I can update standalone makefiles+configs later.

@psi29a
psi29a merged commit b6a4290 into master Jul 7, 2026
12 checks passed
@psi29a

psi29a commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

Cheers @sezero ! :)

We can do a few more cleanups, then launch 0.5 when ready

@sezero
sezero deleted the sf2-support branch July 7, 2026 19:48
#else
#define _TSFREGIONOFFSET(TYPE, FIELD) (unsigned char)(offsetof(struct tsf_region,FIELD) / sizeof(TYPE))
#define _TSFREGIONENVOFFSET(TYPE, ENV, FIELD) (unsigned char)((offsetof(struct tsf_region,ENV) + offsetof(struct tsf_envelope,FIELD)) / sizeof(TYPE))
#endif

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@psi29a (and any others): I'm not 100.000% certain of this fix: Can you think of any cases where it can output different offsets compared to original code?

This was referenced Jul 9, 2026
@sezero sezero added this to the 0.5.0 milestone Jul 10, 2026
@sezero

sezero commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

@psi29a: Do we want schellingb/TinySoundFont#110 and maybe schellingb/TinySoundFont#118 from among mainstream tsf P/Rs?

@psi29a

psi29a commented Jul 11, 2026

Copy link
Copy Markdown
Member Author

Do we want schellingb/TinySoundFont#110 and maybe schellingb/TinySoundFont#118 from among mainstream tsf P/Rs?

Yes of course. I had hoped to let cmake handle this, but now we have to manually keep things up to date. 😬

@sezero

sezero commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Do you plan on upstreaming these to the project?

Our changes submitted to mainstream as schellingb/TinySoundFont#125

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Soundfont2 (SF2) support

3 participants