From d4b348e1f0f7124bca17dfa4719f26ece74fd227 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sat, 11 Jul 2026 19:18:40 +0200 Subject: [PATCH 1/7] note-off, all-notes off and release allowance all reelease through stage 3; fixed-point division bound on tail --- src/internal_midi.c | 65 +++++++++++++++++++-------------------------- src/wildmidi_lib.c | 12 ++++++--- 2 files changed, 37 insertions(+), 40 deletions(-) diff --git a/src/internal_midi.c b/src/internal_midi.c index 82b572f0..5a87da2e 100644 --- a/src/internal_midi.c +++ b/src/internal_midi.c @@ -593,17 +593,6 @@ void _WM_do_note_off_extra(struct _note *nte) { } else if (nte->hold) { nte->hold |= HOLD_OFF; -#if 0 - } else if (nte->modes & SAMPLE_SUSTAIN) { - if (nte->env < 3) { - nte->env = 3; - if (nte->env_level > nte->sample->env_target[3]) { - nte->env_inc = -nte->sample->env_rate[3]; - } else { - nte->env_inc = nte->sample->env_rate[3]; - } - } -#endif } else if (nte->modes & SAMPLE_CLAMPED) { if (nte->env < 5) { nte->env = 5; @@ -613,12 +602,16 @@ void _WM_do_note_off_extra(struct _note *nte) { nte->env_inc = nte->sample->env_rate[5]; } } - } else if (nte->env < 4) { - nte->env = 4; - if (nte->env_level > nte->sample->env_target[4]) { - nte->env_inc = -nte->sample->env_rate[4]; + } else if (nte->env < 3) { + /* GUS/timidity release semantics: the envelope resumes at stage 3 + on note off (stages 3-5 are the release phases). Entering at 4 + skips the release entirely on patches that keep it in stage 3 + (issue #229). */ + nte->env = 3; + if (nte->env_level > nte->sample->env_target[3]) { + nte->env_inc = -nte->sample->env_rate[3]; } else { - nte->env_inc = nte->sample->env_rate[4]; + nte->env_inc = nte->sample->env_rate[3]; } } } @@ -1047,23 +1040,10 @@ void _WM_do_control_channel_notes_off(struct _mdi *mdi, if (note_data) { do { if ((note_data->noteid >> 8) == ch) { - if (!note_data->hold) { - if (note_data->modes & SAMPLE_ENVELOPE) { - if (note_data->env < 5) { - if (note_data->env_level - > note_data->sample->env_target[5]) { - note_data->env_inc = - -note_data->sample->env_rate[5]; - } else { - note_data->env_inc = - note_data->sample->env_rate[5]; - } - note_data->env = 5; - } - } - } else { - note_data->hold |= HOLD_OFF; - } + /* All Notes Off releases each note as if a note off was + received (normal release); only All Sound Off (CC 120) + silences immediately. */ + _WM_do_note_off_extra(note_data); } note_data = note_data->next; } while (note_data); @@ -1215,21 +1195,32 @@ void _WM_Release_Allowance(struct _mdi *mdi) { while (note != NULL) { if (note->modes & SAMPLE_ENVELOPE) { - /* ensure envelope isin a release state */ - if (note->env < 4) { - note->env = 4; + /* ensure envelope is in a release state; release starts at + stage 3 (see _WM_do_note_off_extra) */ + if (note->env < 3) { + note->env = 3; } /* make sure this is set */ note->env_inc = -note->sample->env_rate[note->env]; release = note->env_level / -note->env_inc; + + /* a non-looping sample can't ring longer than its + remaining data */ + if (!(note->modes & SAMPLE_LOOP) && note->sample_inc) { + uint32_t remaining = (note->sample->data_length + - note->sample_pos) / note->sample_inc; + if (remaining < release) release = remaining; + } } else { /* Sample release */ if (note->modes & SAMPLE_LOOP) { note->modes ^= SAMPLE_LOOP; } - release = note->sample->data_length - note->sample_pos; + /* data_length/sample_pos are 22.10 fixed point */ + release = (note->sample->data_length - note->sample_pos) + / (note->sample_inc ? note->sample_inc : 1024); } if (release > longest_release) longest_release = release; diff --git a/src/wildmidi_lib.c b/src/wildmidi_lib.c index 9c5ba2f9..850a0224 100644 --- a/src/wildmidi_lib.c +++ b/src/wildmidi_lib.c @@ -972,7 +972,9 @@ static int WM_GetOutput_Linear(midi * handle, int8_t *buffer, uint32_t size) { _WM_ResetToStart(mdi); event = mdi->current_event; } else { - mdi->samples_to_mix = event->samples_to_next; + /* += : keep any release allowance set by the + end-of-track event (_WM_Release_Allowance). */ + mdi->samples_to_mix += event->samples_to_next; event++; mdi->current_event = event; } @@ -1304,7 +1306,9 @@ static int WM_GetOutput_Gauss(midi * handle, int8_t *buffer, uint32_t size) { _WM_ResetToStart(mdi); event = mdi->current_event; } else { - mdi->samples_to_mix = event->samples_to_next; + /* += : keep any release allowance set by the + end-of-track event (_WM_Release_Allowance). */ + mdi->samples_to_mix += event->samples_to_next; event++; mdi->current_event = event; } @@ -2246,7 +2250,9 @@ static int WM_GetOutput_SF2(midi * handle, int8_t *buffer, uint32_t size) { _WM_ResetToStart(mdi); event = mdi->current_event; } else { - mdi->samples_to_mix = event->samples_to_next; + /* += : keep any release allowance set by the + end-of-track event (_WM_Release_Allowance). */ + mdi->samples_to_mix += event->samples_to_next; event++; mdi->current_event = event; } From df586c5203e7b990e2e0fa8238e21a4da22fb1f7 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sat, 11 Jul 2026 19:26:20 +0200 Subject: [PATCH 2/7] better time estimation; handles note off/release fading --- include/internal_midi.h | 1 + src/internal_midi.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/internal_midi.h b/include/internal_midi.h index 682cecdf..2adeccbd 100644 --- a/include/internal_midi.h +++ b/include/internal_midi.h @@ -133,6 +133,7 @@ struct _event { struct _mdi { int lock; uint32_t samples_to_mix; + uint32_t tail_allowance; /* release tail already counted in approx_total_samples */ struct _event *events; struct _event *current_event; uint32_t event_count; diff --git a/src/internal_midi.c b/src/internal_midi.c index 5a87da2e..aacd7913 100644 --- a/src/internal_midi.c +++ b/src/internal_midi.c @@ -1230,6 +1230,12 @@ void _WM_Release_Allowance(struct _mdi *mdi) { mdi->samples_to_mix = longest_release; + /* Keep the reported length in sync with the tail we are about to + render. Delta against what was already added so repeated end of + track events (looping, seeks) don't inflate the total. */ + mdi->extra_info.approx_total_samples += longest_release - mdi->tail_allowance; + mdi->tail_allowance = longest_release; + return; } From 7e414af26c6e4094daaf48049e37300095ba5780 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sat, 11 Jul 2026 19:30:50 +0200 Subject: [PATCH 3/7] All Notes Off: defer release for notes still in attack, same as note off --- src/internal_midi.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/internal_midi.c b/src/internal_midi.c index aacd7913..c139be2e 100644 --- a/src/internal_midi.c +++ b/src/internal_midi.c @@ -1043,7 +1043,14 @@ void _WM_do_control_channel_notes_off(struct _mdi *mdi, /* All Notes Off releases each note as if a note off was received (normal release); only All Sound Off (CC 120) silences immediately. */ - _WM_do_note_off_extra(note_data); + if ((note_data->modes & SAMPLE_ENVELOPE) + && (note_data->env == 0)) { + /* defer release until the initial envelope step has + completed, same as _WM_do_note_off */ + note_data->is_off = 1; + } else { + _WM_do_note_off_extra(note_data); + } } note_data = note_data->next; } while (note_data); From 43c36272af6a8befb09cafcf26dfdb2b0663c702 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sat, 11 Jul 2026 21:18:26 +0200 Subject: [PATCH 4/7] do not exaggerate; A linear envelope-to-amplitude mapping left releasing notes ~12 dB too loud mid-decay. --- src/wildmidi_lib.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/wildmidi_lib.c b/src/wildmidi_lib.c index 850a0224..248cbc16 100644 --- a/src/wildmidi_lib.c +++ b/src/wildmidi_lib.c @@ -106,6 +106,13 @@ struct _mdi_patches { #define FPBITS 10 #define FPMASK ((1L<> 12]) + /* Gauss Interpolation code adapted from code supplied by Eric. A. Welsh */ static double newt_coeffs[58][58]; /* for start/end of samples */ @@ -1017,7 +1024,7 @@ static int WM_GetOutput_Linear(midi * handle, int8_t *buffer, uint32_t size) { * =================== */ data_pos = note_data->sample_pos >> FPBITS; - premix = ((note_data->sample->data[data_pos] + (((note_data->sample->data[data_pos + 1] - note_data->sample->data[data_pos]) * (int32_t)(note_data->sample_pos & FPMASK)) / 1024)) * (note_data->env_level >> 12)) / 1024; + premix = ((note_data->sample->data[data_pos] + (((note_data->sample->data[data_pos + 1] - note_data->sample->data[data_pos]) * (int32_t)(note_data->sample_pos & FPMASK)) / 1024)) * ENV_AMP(note_data->env_level)) / 1024; left_mix += (premix * (int32_t)note_data->left_mix_volume) / 1024; right_mix += (premix * (int32_t)note_data->right_mix_volume) / 1024; @@ -1388,7 +1395,7 @@ static int WM_GetOutput_Gauss(midi * handle, int8_t *buffer, uint32_t size) { } while (gptr <= gend); } - premix = (int32_t)((y * (note_data->env_level >> 12)) / 1024); + premix = (int32_t)((y * ENV_AMP(note_data->env_level)) / 1024); left_mix += (premix * (int32_t)note_data->left_mix_volume) / 1024; right_mix += (premix * (int32_t)note_data->right_mix_volume) / 1024; @@ -1797,6 +1804,13 @@ static int _WM_Init(const struct _WM_VIO *callbacks, gauss_lock = 0; _WM_patch_lock = 0; _WM_MasterVolume = 948; + { + int i; + for (i = 0; i < 1024; i++) { + env_amp_table[i] = (int32_t)(1024.0 + * pow(2.0, ((double)i / 1023.0 - 1.0) * 6.0) + 0.5); + } + } WM_Initialized = 1; return (0); From 14c7149a1079d33eb4c6ce644dd1760e795fee2c Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sun, 12 Jul 2026 08:46:33 +0200 Subject: [PATCH 5/7] avoid mid-render approx_total_samples growth; cap player display at 100; cmake: propagate libm on libwildmidi-static INTERFACE --- include/internal_midi.h | 1 - src/CMakeLists.txt | 4 ++++ src/internal_midi.c | 10 +++++----- src/player/wildmidi.c | 2 ++ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/internal_midi.h b/include/internal_midi.h index 2adeccbd..682cecdf 100644 --- a/include/internal_midi.h +++ b/include/internal_midi.h @@ -133,7 +133,6 @@ struct _event { struct _mdi { int lock; uint32_t samples_to_mix; - uint32_t tail_allowance; /* release tail already counted in approx_total_samples */ struct _event *events; struct _event *current_event; uint32_t event_count; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8636e0bf..1b80af09 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -82,6 +82,10 @@ TARGET_INCLUDE_DIRECTORIES(libwildmidi-static INTERFACE $ $ ) +# Consumers of the static archive need libm (pow/log10 etc.) +IF (M_LIBRARY) + TARGET_LINK_LIBRARIES(libwildmidi-static INTERFACE ${M_LIBRARY}) +ENDIF() # If the static library was not requested, we do not add it to the "all" & "install" targets IF (WANT_STATIC) diff --git a/src/internal_midi.c b/src/internal_midi.c index c139be2e..87b58b17 100644 --- a/src/internal_midi.c +++ b/src/internal_midi.c @@ -1237,11 +1237,11 @@ void _WM_Release_Allowance(struct _mdi *mdi) { mdi->samples_to_mix = longest_release; - /* Keep the reported length in sync with the tail we are about to - render. Delta against what was already added so repeated end of - track events (looping, seeks) don't inflate the total. */ - mdi->extra_info.approx_total_samples += longest_release - mdi->tail_allowance; - mdi->tail_allowance = longest_release; + /* Don't retroactively grow approx_total_samples: current_sample is + already at (or very near) the parse-time total by the time EOT + fires, so extending would make the reported percentage regress. + samples_to_mix keeps the tail rendering (see the `+= samples_to_next` + in the GetOutput event loops); the player caps its display at 100. */ return; } diff --git a/src/player/wildmidi.c b/src/player/wildmidi.c index c2668c2c..b1fd3ab2 100644 --- a/src/player/wildmidi.c +++ b/src/player/wildmidi.c @@ -762,6 +762,7 @@ int main(int argc, char **argv) { wm_info = WildMidi_GetInfo(midi_ptr); perc_play = (wm_info->current_sample * 100) / wm_info->approx_total_samples; + if (perc_play > 100) perc_play = 100; pro_mins = wm_info->current_sample / (rate * 60); pro_secs = (wm_info->current_sample % (rate * 60)) / rate; fprintf(stderr, @@ -813,6 +814,7 @@ int main(int argc, char **argv) { perc_play = (wm_info->current_sample * 100) / wm_info->approx_total_samples; + if (perc_play > 100) perc_play = 100; pro_mins = wm_info->current_sample / (rate * 60); pro_secs = (wm_info->current_sample % (rate * 60)) / rate; fprintf(stderr, From 613398367e17af20a0b21464a41091acf25ebf98 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sun, 12 Jul 2026 09:48:20 +0200 Subject: [PATCH 6/7] cfg: bound reverb_listener_posy by room length, not width; cfg: bound reverb_listener_posy by room length, not width --- docs/man/man1/wildmidi.1 | 26 ++++++++++++++++++++++---- docs/man/man3/WildMidi_Init.3 | 6 +++--- docs/man/man5/wildmidi.cfg.5 | 19 ++++++++++++++----- src/wildmidi_lib.c | 2 +- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/docs/man/man1/wildmidi.1 b/docs/man/man1/wildmidi.1 index 8ac0ee43..07ecc1bc 100644 --- a/docs/man/man1/wildmidi.1 +++ b/docs/man/man1/wildmidi.1 @@ -1,4 +1,4 @@ -.TH wildmidi 1 "21 November 2020" "" "WildMidi Player" +.TH wildmidi 1 "12 July 2026" "" "WildMidi Player" .SH NAME wildmidi \- example player for libWildMidi .PP @@ -9,7 +9,7 @@ wildmidi \- example player for libWildMidi .B /etc/wildmidi/wildmidi.cfg .PP .SH SYNOPSIS -.B wildmidi [\-bhlvwnst] [\-c \fIconfig\-file\fB] [\-d \fIaudiodev\fB] [\-m \fIvolume\-level\fB] [\-P \fIplayback\-output\fB] [\-o \fIfile\fB] [\-f \fIfrequency\-Hz(MUS)\fB] [\-r \fIsample-rate\fB] [\-g \fIconvert-xmi-type\fB] \fImidifile ... +.B wildmidi [\-0abehlnstvO] [\-c \fIconfig\-file\fB] [\-d \fIaudiodev\fB] [\-m \fIvolume\-level\fB] [\-P \fIplayback\-output\fB] [\-o \fIfile\fB] [\-f \fIfrequency\-Hz(MUS)\fB] [\-r \fIsample-rate\fB] [\-g \fIconvert-xmi-type\fB] [\-i \fIseconds\fB] [\-j \fIseconds\fB] \fImidifile ... .PP .SH DESCRIPTION This is a demonstration program to show the capabilities of libWildMidi. @@ -19,11 +19,17 @@ This is a demonstration program to show the capabilities of libWildMidi. You can have more than one \fImidifile\fP on the command line and \fBwildmidi\fP will pass them to libWildMidi for processing, one after the other. You can also use wildcards, for example: \fBwildmidi *.mid\fP .PP .SH OPTIONS +.IP "\fB\-0\fP" +When converting with \fB\-x\fP, save files detected as type 2 MIDI compatible as type 0 files. +.PP +.IP "\fB\-a\fP | \fB\-\-textaslyric\fP" +Some files store their lyrics in text meta events. Read lyrics from there instead of lyric meta events. +.PP .IP "\fB\-b\fP | \fB\-\-reverb\fP" Turns on an 8 point reverb engine that adds depth to the final mix. .P .IP "\fB\-c\fP \fIconfig\-file\fP | \fB\-\-config\fP \fIconfig\-file\fP" -Uses the configuration file stated by \fIconfig\-file\fP instead of /etc/wildmidi/wildmidi.cfg +Uses the configuration file stated by \fIconfig\-file\fP instead of /etc/wildmidi/wildmidi.cfg. \fIconfig\-file\fP may also be a SoundFont2 (.sf2) file, or a timidity.cfg style file using the \fBsoundfont\fP directive; the file type is detected by content, not extension. .PP .IP "\fB\-d\fP \fIaudiodev\fP | \fB\-\-device=\fIaudiodev\fP" Send audio to \fIaudiodev\fP instead of the default device. @@ -32,6 +38,9 @@ Send audio to \fIaudiodev\fP instead of the default device. netbsd : defaults to "/dev/audio" Other environments do not support this option. .PP +.IP "\fB\-e\fP | \fB\-\-enhanced\fP" +Use enhanced (Gauss) resampling for a richer sound at the cost of extra CPU usage. +.PP .IP "\fB\-h\fP | \fB\-\-help\fP" Displays command line options. .PP @@ -43,6 +52,12 @@ Convert XMI: 0 - No Conversion (default) 1 - MT32 to GM 2 - MT32 to GS .PP +.IP "\fB\-i\fP \fIseconds\fP | \fB\-\-playfrom=\fIseconds\fP" +Begin playback at \fIseconds\fP (fractions allowed) into the file. +.PP +.IP "\fB\-j\fP \fIseconds\fP | \fB\-\-playto=\fIseconds\fP" +Stop playback at \fIseconds\fP (fractions allowed) into the file. +.PP .IP "\fB\-l\fP | \fB\-\-log_vol\fP" Some MIDI files have been recorded on hardware that uses a volume curve, making them sound really badly mixed on other MIDI devices. Use this option to use volume curves. .PP @@ -55,6 +70,9 @@ Set \fIplayback\-output\fP as playback output. See \fB\--help\fP output for avai .IP "\fB\-o\fP \fIfile\fP | \fB\-\-wavout=\fIfile\fP" Records output to a signed 16 bit stereo format \fIwav file\fP. Implies: \fB\-P wave\fP .PP +.IP "\fB\-O\fP | \fB\-\-opl3\fP" +Use the built\-in OPL3 FM synthesizer. No configuration file, GUS patch set or SoundFont is needed. +.PP .IP "\fB\-r\fP \fIsndrate\fP | \fB\-\-rate=\fIsndrate\fP" Set the audio output rate to \fIsndrate\fP. The default rate is 32072. .PP @@ -128,7 +146,7 @@ Chris Ison Bret Curtis .PP .SH COPYRIGHT -Copyright (C) WildMidi Developers 2001\-2024 +Copyright (C) WildMidi Developers 2001\-2026 .PP This file is part of WildMIDI. .PP diff --git a/docs/man/man3/WildMidi_Init.3 b/docs/man/man3/WildMidi_Init.3 index d27a43e4..aeb5e4ca 100644 --- a/docs/man/man3/WildMidi_Init.3 +++ b/docs/man/man3/WildMidi_Init.3 @@ -1,4 +1,4 @@ -.TH WildMidi_Init 3 "10 March 2016" "" "WildMidi Programmer's Manual" +.TH WildMidi_Init 3 "12 July 2026" "" "WildMidi Programmer's Manual" .SH NAME WildMidi_Init \- Initialize the library .PP @@ -14,7 +14,7 @@ WildMidi_Init \- Initialize the library Initializes libWildMidi in preparation for playback. This function only needs to be called once by the program using libWildMidi. .PP .IP \fIconfig-file\fP -The file that contains the instrument configuration for the library. +The file that contains the instrument configuration for the library. This may be a Gravis Ultrasound patch configuration (see \fBwildmidi.cfg\fP(5)), a SoundFont2 (.sf2) file, or a timidity.cfg style file naming a SoundFont via the \fBsoundfont\fP directive; the file type is detected by content, not extension. Passing the string \fB"@opl3"\fP selects the built\-in OPL3 FM synthesizer, which needs no configuration file at all. .PP .IP \fIrate\fP The sound rate you want the the audio data output at. Rates accepted by libWildMidi are 11025 \- 65000. @@ -58,7 +58,7 @@ Chris Ison Bret Curtis .PP .SH COPYRIGHT -Copyright (C) WildMidi Developers 2001\-2016 +Copyright (C) WildMidi Developers 2001\-2026 .PP This file is part of WildMIDI. .PP diff --git a/docs/man/man5/wildmidi.cfg.5 b/docs/man/man5/wildmidi.cfg.5 index f192f7e6..ed5b63bb 100644 --- a/docs/man/man5/wildmidi.cfg.5 +++ b/docs/man/man5/wildmidi.cfg.5 @@ -1,4 +1,4 @@ -.TH wildmidi.cfg 5 "10 March 2016" "" "WildMidi Config File" +.TH wildmidi.cfg 5 "12 July 2026" "" "WildMidi Config File" .SH NAME wildmidi.cfg \- Config file for libWildMidi .PP @@ -8,6 +8,8 @@ wildmidi.cfg \- Config file for libWildMidi .SH DESCRIPTION Contains the patch configuration for libWildMidi and location of Gravis Ultrasound compatible patch files. .PP +Instead of a patch configuration, the file given to libWildMidi may also be a SoundFont2 (.sf2) file, or a timidity.cfg style file that names one via the \fBsoundfont\fP directive. The file type is detected by content, not by extension. +.PP .nf dir ~/guspats/ @@ -24,9 +26,7 @@ drumset 0 .PP .SH SYNTAX .IP "\fBguspat_editor_author_cant_read_so_fix_release_time_for_me\fP" -Some patch file editors switch the 4th and 5th envelopes around making the sound play much longer than intended in players that stuck to the Gravis Ultrasound patch standard. Including this option in the config enables a fix that detects this oversight, playing the sound samples as if they were correct. -.IP -NOTE: This is a global setting. If it is found to affect good patch samples it will be moved to a per patch setting in a future version. +Some patch file editors switch the 4th and 5th envelopes around making the sound play much longer than intended in players that stuck to the Gravis Ultrasound patch standard. A fix that detects this oversight is applied automatically since WildMidi 0.4.3; this option is accepted for backwards compatibility and has no effect. .PP .IP "\fBauto_amp\fP" Forces WildMIDI to amplify samples to their maximum level ignoring the amp=% in the patch lines of the config. @@ -40,6 +40,9 @@ Change the search path for config and patch files to \fIdir\-name\fP. This is sp .IP "\fBsource\fP \fIinclude\-confg\fP" Include the settings from \fIinclude\-config\fP. Any patch already set will be over\-ridden by the included config file. .PP +.IP "\fBsoundfont\fP \fIsf2\-file\fP" +Render using the SoundFont2 file \fIsf2\-file\fP instead of Gravis Ultrasound patches. Relative paths are resolved against the config file directory, the same as \fBsource\fP. This allows an existing timidity.cfg that names a SoundFont to be used as\-is. +.PP .IP "\fBbank\fP \fIN\fP" The patches following this setting belong to MIDI instrument bank \fIN\fP. .PP @@ -98,6 +101,12 @@ Set the room length for the reverb engine in meters. \fIfval\fP is a float value .IP Example: set room length to 40 meters \- \fBreverb_room_length 40\fP .PP +.IP "\fBreverb_listener_posx\fP \fIfval\fP" +Set the listener position across the room width for the reverb engine. \fIfval\fP is a float value in meters between 0.0 and \fBreverb_room_width\fP; values outside the room reset to the room centre. Default is half the room width. +.PP +.IP "\fBreverb_listener_posy\fP \fIfval\fP" +Set the listener position along the room length for the reverb engine. \fIfval\fP is a float value in meters between 0.0 and \fBreverb_room_length\fP; values outside the room reset to 3/4 of the room length. Default is 3/4 of the room length. +.PP .SH SEE ALSO .BR wildmidi (1) @@ -108,7 +117,7 @@ Bret Curtis .PP .SH COPYRIGHT Copyright (C) Chris Ison 2001\-2010 -Copyright (C) Bret Curtis 2013\-2016 +Copyright (C) Bret Curtis 2013\-2026 .PP This file is part of WildMIDI. .PP diff --git a/src/wildmidi_lib.c b/src/wildmidi_lib.c index 248cbc16..abd38368 100644 --- a/src/wildmidi_lib.c +++ b/src/wildmidi_lib.c @@ -659,7 +659,7 @@ static int load_config(const char *config_file, const char *conf_dir) { return (-1); } _WM_reverb_listen_posy = (float) atof(line_tokens[1]); - if ((_WM_reverb_listen_posy > _WM_reverb_room_width) + if ((_WM_reverb_listen_posy > _WM_reverb_room_length) || (_WM_reverb_listen_posy < 0.0f)) { _WM_DEBUG_MSG("%s: reverb_listen_posy set outside of room", config_file); _WM_reverb_listen_posy = _WM_reverb_room_length * 0.75f; From 1eceb68e6887312477fa9d6ca31621c0cc5eba26 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Sun, 12 Jul 2026 11:11:03 +0200 Subject: [PATCH 7/7] docs: show -x with its required file argument in wildmidi.1 synopsis and options --- docs/man/man1/wildmidi.1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/man/man1/wildmidi.1 b/docs/man/man1/wildmidi.1 index 07ecc1bc..d2202584 100644 --- a/docs/man/man1/wildmidi.1 +++ b/docs/man/man1/wildmidi.1 @@ -9,7 +9,7 @@ wildmidi \- example player for libWildMidi .B /etc/wildmidi/wildmidi.cfg .PP .SH SYNOPSIS -.B wildmidi [\-0abehlnstvO] [\-c \fIconfig\-file\fB] [\-d \fIaudiodev\fB] [\-m \fIvolume\-level\fB] [\-P \fIplayback\-output\fB] [\-o \fIfile\fB] [\-f \fIfrequency\-Hz(MUS)\fB] [\-r \fIsample-rate\fB] [\-g \fIconvert-xmi-type\fB] [\-i \fIseconds\fB] [\-j \fIseconds\fB] \fImidifile ... +.B wildmidi [\-0abehlnstvO] [\-c \fIconfig\-file\fB] [\-d \fIaudiodev\fB] [\-m \fIvolume\-level\fB] [\-P \fIplayback\-output\fB] [\-o \fIfile\fB] [\-f \fIfrequency\-Hz(MUS)\fB] [\-r \fIsample-rate\fB] [\-g \fIconvert-xmi-type\fB] [\-x \fIfile\fB] [\-i \fIseconds\fB] [\-j \fIseconds\fB] \fImidifile ... .PP .SH DESCRIPTION This is a demonstration program to show the capabilities of libWildMidi. @@ -85,8 +85,8 @@ Skips any silence at the start of playback. .IP "\fB\-v\fP | \fB\-\-version\fP" Display version and copyright information. .PP -.IP "\fB\-x\fP | \fB\-\-tomidi\fP" -Convert a MUS, XMI, HMP or HMI file to midi and save to file. +.IP "\fB\-x\fP \fIfile\fP | \fB\-\-tomidi=\fIfile\fP" +Convert a MUS, XMI, HMP or HMI file to midi and save it as \fIfile\fP. .PP .SH TEST OPTIONS These options are not designed for general use. Instead these options are designed to make it easier to listen to specific sound samples.