From fa8d7184e25c0729163ee1b79c557b74ecde30eb Mon Sep 17 00:00:00 2001 From: Douglas Carmichael Date: Fri, 24 Jul 2026 08:06:42 -0400 Subject: [PATCH] DLS: fix the pitch scale conversions which saturated DlsDetector.normalizeEG2ToPitch clamped the raw 32-bit connection value to +-1200 and divided by 1200, but that value is a relative pitch stored as a fixed point number with 65536 representing one cent. Every non-zero value therefore saturated to full scale. * Pitch envelope depth: divided by 65536 first and normalized over the same range as every other format, so a one octave envelope is 1200 cent and not ten octaves. Measured on the Roland GS set that ships with macOS (gs_instruments.dls): 522 zones that were all written as +-12000 cent are now spread across their real -1200..1200 cent values. * Pitch tuning: converted to semi-tones (65536 per cent, 100 cent per semi-tone) instead of the saturated value. * Modulation envelope sustain: routed through the sustain level conversion like the first envelope instead of the pitch conversion. This branch is currently unreached because the envelope is only ever created for the first EG, but it removes the last use of the helper. The now unused normalizeEG2ToPitch is removed. --- .../format/dls/DlsDetector.java | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/main/java/de/mossgrabers/convertwithmoss/format/dls/DlsDetector.java b/src/main/java/de/mossgrabers/convertwithmoss/format/dls/DlsDetector.java index d0dda6e2..be36f148 100644 --- a/src/main/java/de/mossgrabers/convertwithmoss/format/dls/DlsDetector.java +++ b/src/main/java/de/mossgrabers/convertwithmoss/format/dls/DlsDetector.java @@ -235,7 +235,10 @@ private static void applyArticulations (final DlsInstrument dlsInstrument, final { final IEnvelope pitchEnvelope = createEnvelope (dlsInstrument, dlsRegion, true); final IEnvelopeModulator pitchEnvelopeModulator = zone.getPitchEnvelopeModulator (); - pitchEnvelopeModulator.setDepth (normalizeEG2ToPitch (pitchModulation.get ().getScale ())); + // The scale is a relative pitch in cent, stored as a 32-bit fixed point number with + // 65536 representing one cent + final double depthCents = pitchModulation.get ().getScale () / 65536.0; + pitchEnvelopeModulator.setDepth (Math.clamp (depthCents, -IEnvelope.MAX_ENVELOPE_DEPTH, IEnvelope.MAX_ENVELOPE_DEPTH) / IEnvelope.MAX_ENVELOPE_DEPTH); pitchEnvelopeModulator.setSource (pitchEnvelope); } @@ -243,7 +246,8 @@ private static void applyArticulations (final DlsInstrument dlsInstrument, final final Optional pitchTuning = getArticulation (dlsInstrument, dlsRegion, DlsArticulation.CONN_SRC_NONE, DlsArticulation.CONN_DST_PITCH); if (pitchTuning.isPresent ()) { - final double tuning = normalizeEG2ToPitch (pitchTuning.get ().getScale ()); + // The scale is a relative pitch in cent (65536 per cent), the tuning is in semi-tones + final double tuning = pitchTuning.get ().getScale () / 65536.0 / 100.0; zone.setTuning (zone.getTuning () + tuning); } @@ -281,10 +285,7 @@ private static IEnvelope createEnvelope (final DlsInstrument dlsInstrument, fina if (isEnvelope1) sustain = getLevel (dlsInstrument, dlsRegion, DlsArticulation.CONN_DST_EG1_SUSTAINLEVEL); else - { - final Optional articulation = getArticulation (dlsInstrument, dlsRegion, DlsArticulation.CONN_SRC_NONE, DlsArticulation.CONN_DST_EG2_SUSTAINLEVEL); - sustain = articulation.isEmpty () ? -1 : normalizeEG2ToPitch (articulation.get ().getScale ()); - } + sustain = getLevel (dlsInstrument, dlsRegion, DlsArticulation.CONN_DST_EG2_SUSTAINLEVEL); final IEnvelope envelope = new DefaultEnvelope (); if (delay >= 0) @@ -346,16 +347,4 @@ private static double normalizeKeyNumberToGain (final int scale) { return Math.clamp (scale / (655360.0 * 127.0), -1, 1); } - - - /** - * Normalizes a DLS Modulation EG to Pitch lScale value to the range 0.0..1.0. - * - * @param cents The raw 32-bit signed relative pitch value - * @return Normalized value in range [0.0, 1.0] - */ - public static double normalizeEG2ToPitch (final int cents) - { - return Math.clamp (cents, -1200, 1200) / 1200.0; - } }