ref: 2ca5c793d6bc52ba2fda3cfe41d7adfeae20499c
parent: fd11b0e02aa921865b60048b102409ea40080429
author: ceski <[email protected]>
date: Tue Sep 6 19:36:11 EDT 2022
Configurable reverb and chorus for native MIDI (#1504)
--- a/src/i_sound.c
+++ b/src/i_sound.c
@@ -85,6 +85,10 @@
extern char *music_pack_path;
extern char *fluidsynth_sf_path;
extern char *timidity_cfg_path;
+#ifdef _WIN32
+extern int winmm_reverb_level;
+extern int winmm_chorus_level;
+#endif
// DOS-specific options: These are unused but should be maintained
// so that the config file can be shared between chocolate
@@ -513,6 +517,10 @@
M_BindStringVariable("timidity_cfg_path", &timidity_cfg_path);
M_BindStringVariable("gus_patch_path", &gus_patch_path);
M_BindIntVariable("gus_ram_kb", &gus_ram_kb);
+#ifdef _WIN32
+ M_BindIntVariable("winmm_reverb_level", &winmm_reverb_level);
+ M_BindIntVariable("winmm_chorus_level", &winmm_chorus_level);
+#endif
M_BindIntVariable("use_libsamplerate", &use_libsamplerate);
M_BindFloatVariable("libsamplerate_scale", &libsamplerate_scale);
--- a/src/i_winmusic.c
+++ b/src/i_winmusic.c
@@ -26,6 +26,16 @@
#include "m_misc.h"
#include "midifile.h"
+#define BETWEEN(l,u,x) (((l)>(x))?(l):((x)>(u))?(u):(x))
+
+#define REVERB_MIN 0
+#define REVERB_MAX 127
+#define CHORUS_MIN 0
+#define CHORUS_MAX 127
+
+int winmm_reverb_level = 40;
+int winmm_chorus_level = 0;
+
static HMIDISTRM hMidiStream;
static HANDLE hBufferReturnEvent;
static HANDLE hExitEvent;
@@ -335,6 +345,52 @@
}
}
+void ResetDevice(void)
+{
+ for (int i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i)
+ {
+ DWORD msg = 0;
+
+ // RPN sequence to adjust pitch bend range (RPN value 0x0000)
+ msg = MIDI_EVENT_CONTROLLER | i | 0x65 << 8 | 0x00 << 16;
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+ msg = MIDI_EVENT_CONTROLLER | i | 0x64 << 8 | 0x00 << 16;
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+
+ // reset pitch bend range to central tuning +/- 2 semitones and 0 cents
+ msg = MIDI_EVENT_CONTROLLER | i | 0x06 << 8 | 0x02 << 16;
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+ msg = MIDI_EVENT_CONTROLLER | i | 0x26 << 8 | 0x00 << 16;
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+
+ // end of RPN sequence
+ msg = MIDI_EVENT_CONTROLLER | i | 0x64 << 8 | 0x7F << 16;
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+ msg = MIDI_EVENT_CONTROLLER | i | 0x65 << 8 | 0x7F << 16;
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+
+ // reset all controllers
+ msg = MIDI_EVENT_CONTROLLER | i | 0x79 << 8 | 0x00 << 16;
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+
+ // reset pan to 64 (center)
+ msg = MIDI_EVENT_CONTROLLER | i | 0x0A << 8 | 0x40 << 16;
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+
+ // reset reverb and other effect controllers
+ msg = MIDI_EVENT_CONTROLLER | i | 0x5B << 8 | winmm_reverb_level << 16;
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+ msg = MIDI_EVENT_CONTROLLER | i | 0x5C << 8 | 0x00 << 16; // tremolo
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+ msg = MIDI_EVENT_CONTROLLER | i | 0x5D << 8 | winmm_chorus_level << 16;
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+ msg = MIDI_EVENT_CONTROLLER | i | 0x5E << 8 | 0x00 << 16; // detune
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+ msg = MIDI_EVENT_CONTROLLER | i | 0x5F << 8 | 0x00 << 16; // phaser
+ midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
+ }
+}
+
boolean I_WIN_InitMusic(void)
{
UINT MidiDevice = MIDI_MAPPER;
@@ -366,6 +422,10 @@
hBufferReturnEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ winmm_reverb_level = BETWEEN(REVERB_MIN, REVERB_MAX, winmm_reverb_level);
+ winmm_chorus_level = BETWEEN(CHORUS_MIN, CHORUS_MAX, winmm_chorus_level);
+ ResetDevice();
+
return true;
}
@@ -378,7 +438,6 @@
void I_WIN_StopSong(void)
{
- int i;
MMRESULT mmr;
if (hPlayerThread)
@@ -390,48 +449,7 @@
hPlayerThread = NULL;
}
- for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i)
- {
- DWORD msg = 0;
-
- // RPN sequence to adjust pitch bend range (RPN value 0x0000)
- msg = MIDI_EVENT_CONTROLLER | i | 0x65 << 8 | 0x00 << 16;
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
- msg = MIDI_EVENT_CONTROLLER | i | 0x64 << 8 | 0x00 << 16;
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
-
- // reset pitch bend range to central tuning +/- 2 semitones and 0 cents
- msg = MIDI_EVENT_CONTROLLER | i | 0x06 << 8 | 0x02 << 16;
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
- msg = MIDI_EVENT_CONTROLLER | i | 0x26 << 8 | 0x00 << 16;
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
-
- // end of RPN sequence
- msg = MIDI_EVENT_CONTROLLER | i | 0x64 << 8 | 0x7F << 16;
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
- msg = MIDI_EVENT_CONTROLLER | i | 0x65 << 8 | 0x7F << 16;
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
-
- // reset all controllers
- msg = MIDI_EVENT_CONTROLLER | i | 0x79 << 8 | 0x00 << 16;
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
-
- // reset pan to 64 (center)
- msg = MIDI_EVENT_CONTROLLER | i | 0x0A << 8 | 0x40 << 16;
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
-
- // reset reverb to 40 and other effect controllers to 0
- msg = MIDI_EVENT_CONTROLLER | i | 0x5B << 8 | 0x28 << 16; // reverb
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
- msg = MIDI_EVENT_CONTROLLER | i | 0x5C << 8 | 0x00 << 16; // tremolo
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
- msg = MIDI_EVENT_CONTROLLER | i | 0x5D << 8 | 0x00 << 16; // chorus
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
- msg = MIDI_EVENT_CONTROLLER | i | 0x5E << 8 | 0x00 << 16; // detune
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
- msg = MIDI_EVENT_CONTROLLER | i | 0x5F << 8 | 0x00 << 16; // phaser
- midiOutShortMsg((HMIDIOUT)hMidiStream, msg);
- }
+ ResetDevice();
mmr = midiStreamStop(hMidiStream);
if (mmr != MMSYSERR_NOERROR)
--- a/src/i_winmusic.h
+++ b/src/i_winmusic.h
@@ -31,6 +31,9 @@
void I_WIN_UnRegisterSong(void);
void I_WIN_ShutdownMusic(void);
+extern int winmm_reverb_level;
+extern int winmm_chorus_level;
+
#endif
#endif
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -965,6 +965,20 @@
CONFIG_VARIABLE_INT(gus_ram_kb),
+#ifdef _WIN32
+ //!
+ // Reverb level for native Windows MIDI, default 40, range 0-127.
+ //
+
+ CONFIG_VARIABLE_INT(winmm_reverb_level),
+
+ //!
+ // Chorus level for native Windows MIDI, default 0, range 0-127.
+ //
+
+ CONFIG_VARIABLE_INT(winmm_chorus_level),
+#endif
+
//!
// @game doom strife
//
--- a/src/setup/sound.c
+++ b/src/setup/sound.c
@@ -70,6 +70,10 @@
static char *fluidsynth_sf_path = NULL;
static char *gus_patch_path = NULL;
static int gus_ram_kb = 1024;
+#ifdef _WIN32
+static int winmm_reverb_level = 40;
+static int winmm_chorus_level = 0;
+#endif
// DOS specific variables: these are unused but should be maintained
// so that the config file can be shared between chocolate
@@ -225,6 +229,10 @@
M_BindStringVariable("music_pack_path", &music_pack_path);
M_BindStringVariable("timidity_cfg_path", &timidity_cfg_path);
M_BindStringVariable("fluidsynth_sf_path", &fluidsynth_sf_path);
+#ifdef _WIN32
+ M_BindIntVariable("winmm_reverb_level", &winmm_reverb_level);
+ M_BindIntVariable("winmm_chorus_level", &winmm_chorus_level);
+#endif
M_BindIntVariable("snd_sbport", &snd_sbport);
M_BindIntVariable("snd_sbirq", &snd_sbirq);