-- v2: dmsynth: Explicitly ignore CONN_DST_EG1_SHUTDOWNTIME. dmsynth: Make voice shutdown instant. dmsynth: Set GEN_EXCLUSIVECLASS to the key group. dmsynth: Handle bipolar transform for LFO connections.
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmsynth/synth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index ba49abefc8e..86c6ffa4f53 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -164,7 +164,7 @@ static void dump_dmus_region(DMUS_REGION *region) TRACE(" - cbSize = %lu\n", region->WSMP.cbSize); TRACE(" - usUnityNote = %u\n", region->WSMP.usUnityNote); TRACE(" - sFineTune = %u\n", region->WSMP.sFineTune); - TRACE(" - lAttenuation = %lu\n", region->WSMP.lAttenuation); + TRACE(" - lAttenuation = %ld\n", region->WSMP.lAttenuation); TRACE(" - fulOptions = %#lx\n", region->WSMP.fulOptions); TRACE(" - cSampleLoops = %lu\n", region->WSMP.cSampleLoops); for (i = 0; i < region->WSMP.cSampleLoops; i++)
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmsynth/synth.c | 2 ++ dlls/dmsynth/tests/dmsynth.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index 86c6ffa4f53..69a12910647 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -1991,6 +1991,8 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui add_voice_connections(fluid_voice, &articulation->list, articulation->connections); LIST_FOR_EACH_ENTRY(articulation, ®ion->articulations, struct articulation, entry) add_voice_connections(fluid_voice, &articulation->list, articulation->connections); + fluid_voice_gen_incr(voice->fluid_voice, GEN_ATTENUATION, + region->wave_sample.lAttenuation / -65536.); /* Unlike FluidSynth, native applies the gain limit after the panning. At * least for the center pan we can replicate this by applying a panning * attenuation here. */ diff --git a/dlls/dmsynth/tests/dmsynth.c b/dlls/dmsynth/tests/dmsynth.c index 491c3701d52..9634b8f715a 100644 --- a/dlls/dmsynth/tests/dmsynth.c +++ b/dlls/dmsynth/tests/dmsynth.c @@ -2107,7 +2107,7 @@ static void test_dls(void) download.region.WSMP.lAttenuation = -120 * 65536; envelope = default_volume_envelope; envelope.gain -= 120.; - check_volume_envelope(synth, &download, &default_midi, &envelope, TRUE); + check_volume_envelope(synth, &download, &default_midi, &envelope, FALSE);
/* lfo frequency */
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmsynth/synth.c | 8 ++++++-- dlls/dmsynth/tests/dmsynth.c | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index 69a12910647..1b37e1b5318 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -44,7 +44,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmsynth); #define CONN_TRN_BIPOLAR (1<<4) #define CONN_TRN_INVERT (1<<5)
-#define CONN_TRANSFORM(src, ctrl, dst) (((src) & 0x3f) << 10) | (((ctrl) & 0x3f) << 4) | ((dst) & 0xf) +#define CONN_TRANSFORM(src, ctrl, dst) ((((src) & 0x3f) << 10) | (((ctrl) & 0x3f) << 4) | ((dst) & 0xf))
#define BASE_GAIN 60. #define CENTER_PAN_GAIN -30.10 @@ -1598,7 +1598,11 @@ static BOOL set_gen_from_connection(fluid_voice_t *fluid_voice, const CONNECTION UINT gen;
if (conn->usControl != CONN_SRC_NONE) return FALSE; - if (conn->usTransform != CONN_TRN_NONE) return FALSE; + if (conn->usTransform != CONN_TRN_NONE) + { + if (conn->usTransform != CONN_TRANSFORM(CONN_TRN_BIPOLAR, CONN_TRN_NONE, CONN_TRN_NONE)) return FALSE; + if (conn->usSource != CONN_SRC_LFO && conn->usSource != CONN_SRC_VIBRATO) return FALSE; + }
if (conn->usSource == CONN_SRC_NONE) { diff --git a/dlls/dmsynth/tests/dmsynth.c b/dlls/dmsynth/tests/dmsynth.c index 9634b8f715a..3940f28194b 100644 --- a/dlls/dmsynth/tests/dmsynth.c +++ b/dlls/dmsynth/tests/dmsynth.c @@ -2613,7 +2613,7 @@ static void test_dls(void) envelope = default_volume_envelope; envelope.lfo.freq = 2.; envelope.lfo.scale = 10.; - check_volume_envelope(synth, &download, &default_midi, &envelope, TRUE); + check_volume_envelope(synth, &download, &default_midi, &envelope, FALSE);
/* LFO x CC1 -> gain */
@@ -2793,7 +2793,7 @@ static void test_dls(void) envelope = default_pitch_envelope; envelope.lfo.freq = 2.; envelope.lfo.scale = 100.; - check_pitch_envelope(synth, &download, &default_midi, &envelope, TRUE); + check_pitch_envelope(synth, &download, &default_midi, &envelope, FALSE);
/* vibrato LFO x CC1 -> pitch */
@@ -2892,7 +2892,7 @@ static void test_dls(void) envelope = default_pitch_envelope; envelope.lfo.freq = 2.; envelope.lfo.scale = 100.; - check_pitch_envelope(synth, &download, &default_midi, &envelope, TRUE); + check_pitch_envelope(synth, &download, &default_midi, &envelope, FALSE);
/* LFO x CC1 -> pitch */
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmsynth/synth.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index 1b37e1b5318..3f31c9899ab 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -2001,6 +2001,7 @@ static int synth_preset_noteon(fluid_preset_t *fluid_preset, fluid_synth_t *flui * least for the center pan we can replicate this by applying a panning * attenuation here. */ fluid_voice_gen_incr(voice->fluid_voice, GEN_ATTENUATION, -CENTER_PAN_GAIN); + fluid_voice_gen_set(voice->fluid_voice, GEN_EXCLUSIVECLASS, region->group); fluid_synth_start_voice(synth->fluid_synth, fluid_voice);
LeaveCriticalSection(&synth->cs);
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmsynth/tests/dmsynth.c | 4 ++-- libs/fluidsynth/src/synth/fluid_voice.c | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/dlls/dmsynth/tests/dmsynth.c b/dlls/dmsynth/tests/dmsynth.c index 3940f28194b..3df6f9caf68 100644 --- a/dlls/dmsynth/tests/dmsynth.c +++ b/dlls/dmsynth/tests/dmsynth.c @@ -2254,7 +2254,7 @@ static void test_dls(void) download.connection_list.cConnections = 1; download.connections[0].usDestination = CONN_DST_EG1_RELEASETIME; download.connections[0].lScale = ABS_TIME_MS(200); - check_volume_envelope(synth, &download, &midi, &default_volume_envelope, TRUE); + check_volume_envelope(synth, &download, &midi, &default_volume_envelope, FALSE);
memset(&midi, 0, sizeof(midi)); midi.messages[0] = default_note_on; @@ -2266,7 +2266,7 @@ static void test_dls(void) download.connections[0].lScale = ABS_TIME_MS(200); download.connections[1].usDestination = CONN_DST_EG1_SHUTDOWNTIME; download.connections[1].lScale = ABS_TIME_MS(200); - check_volume_envelope(synth, &download, &midi, &default_volume_envelope, TRUE); + check_volume_envelope(synth, &download, &midi, &default_volume_envelope, FALSE);
/* velocity -> EG1 attack time */
diff --git a/libs/fluidsynth/src/synth/fluid_voice.c b/libs/fluidsynth/src/synth/fluid_voice.c index aadfc097895..c1daf3d316d 100644 --- a/libs/fluidsynth/src/synth/fluid_voice.c +++ b/libs/fluidsynth/src/synth/fluid_voice.c @@ -1398,6 +1398,7 @@ fluid_voice_kill_excl(fluid_voice_t *voice) */ fluid_voice_gen_set(voice, GEN_EXCLUSIVECLASS, 0);
+#if 0 /* unused in Wine */ /* Speed up the volume envelope */ /* The value was found through listening tests with hi-hat samples. */ fluid_voice_gen_set(voice, GEN_VOLENVRELEASE, -200); @@ -1406,6 +1407,12 @@ fluid_voice_kill_excl(fluid_voice_t *voice) /* Speed up the modulation envelope */ fluid_voice_gen_set(voice, GEN_MODENVRELEASE, -200); fluid_voice_update_param(voice, GEN_MODENVRELEASE); + gen[i].val = fluid_gen_info[i].def; +#else + /* Speed up the volume envelope */ + fluid_voice_gen_set(voice, GEN_VOLENVRELEASE, -32768); + fluid_voice_update_param(voice, GEN_VOLENVRELEASE); +#endif
at_tick = fluid_channel_get_min_note_length_ticks(voice->channel); UPDATE_RVOICE_I1(fluid_rvoice_noteoff, at_tick);
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmsynth/synth.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index 3f31c9899ab..e0fe70f264f 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -1586,6 +1586,7 @@ static BOOL gen_from_connection(const CONNECTION *conn, UINT *gen) case CONN_DST_EG1_DECAYTIME: *gen = GEN_VOLENVDECAY; return TRUE; case CONN_DST_EG1_SUSTAINLEVEL: *gen = GEN_VOLENVSUSTAIN; return TRUE; case CONN_DST_EG1_RELEASETIME: *gen = GEN_VOLENVRELEASE; return TRUE; + case CONN_DST_EG1_SHUTDOWNTIME: return FALSE; case CONN_DST_GAIN: *gen = GEN_ATTENUATION; return TRUE; case CONN_DST_PITCH: *gen = GEN_PITCH; return TRUE; default: FIXME("Unsupported connection %s\n", debugstr_connection(conn)); return FALSE; @@ -1777,7 +1778,7 @@ static void set_default_voice_connections(fluid_voice_t *fluid_voice) {.usDestination = CONN_DST_EG1_DECAYTIME, .lScale = ABS_TIME_MS(0)}, {.usDestination = CONN_DST_EG1_SUSTAINLEVEL, .lScale = 1000 * 65536}, {.usDestination = CONN_DST_EG1_RELEASETIME, .lScale = ABS_TIME_MS(0)}, - /* FIXME: {.usDestination = CONN_DST_EG1_SHUTDOWNTIME, .lScale = ABS_TIME_MS(15)}, */ + {.usDestination = CONN_DST_EG1_SHUTDOWNTIME, .lScale = ABS_TIME_MS(15)}, {.usSource = CONN_SRC_KEYONVELOCITY, .usDestination = CONN_DST_EG1_ATTACKTIME, .lScale = 0}, {.usSource = CONN_SRC_KEYNUMBER, .usDestination = CONN_DST_EG1_DECAYTIME, .lScale = 0}, {.usSource = CONN_SRC_KEYNUMBER, .usDestination = CONN_DST_EG1_HOLDTIME, .lScale = 0},
v2: - Split the transform condition into multiple `if` statements.
On Wed Nov 19 08:40:39 2025 +0000, Rémi Bernon wrote:
Can we split these conditions or align them differently so the operator precedence gets readable?
if (conn->usTransform != CONN_TRN_NONE) { if (conn->usTransform != CONN_TRANSFORM(CONN_TRN_BIPOLAR, CONN_TRN_NONE, CONN_TRN_NONE)) return FALSE; if (conn->usSource != CONN_SRC_LFO && conn->usSource != CONN_SRC_VIBRATO) return FALSE; }For instance.
Yes, of course. Done.
This merge request was approved by Rémi Bernon.
This merge request was approved by Michael Stefaniuc.