Skip to content

Fix incorrect envelope time conversions in disting EX, 1010music and Maschine 2/3#174

Merged
git-moss merged 1 commit into
git-moss:mainfrom
douglas-carmichael:audit-envelope-fixes
Jul 8, 2026
Merged

Fix incorrect envelope time conversions in disting EX, 1010music and Maschine 2/3#174
git-moss merged 1 commit into
git-moss:mainfrom
douglas-carmichael:audit-envelope-fixes

Conversation

@douglas-carmichael

Copy link
Copy Markdown
Contributor

While auditing the creators/detectors for envelope-time conversion bugs I found three independent issues. In each case the amplitude envelope of the same format already does it correctly, so the fix is to make the affected path match that reference. Each fix is small and independent.

1. disting EX — dropped hold time in amplitude decay

DistingExCreator writes the amplitude decay as:

Math.log (Math.max (0, envelope.getHoldTime ()) + Math.max (0, envelope.getDecayTime ()) / 0.02) / 0.0521

Operator precedence makes / 0.02 bind to the decay term only, i.e. log(hold + decay/0.02) instead of the intended log((hold + decay)/0.02). Because decay/0.02 dwarfs hold, the hold time is effectively dropped from the written decay. The reader confirms the intent — it decodes with decay = 0.02 * Math.exp (0.0521 * value), whose inverse is log((hold+decay)/0.02)/0.0521. Fixed by parenthesising (hold + decay) before the division.

2. 1010music (blackbox and Bento) — decay/release write scale doesn't match read scale

The amplitude decay and release are written with a 25 s full-scale but read back with a 38 s full-scale:

Parameter Write (normalizeTime…) Read (denormalizeTime)
Attack 9.0 9.0 ✅ consistent
Decay 25.0 38.0 ❌ mismatch
Release 25.0 38.0 ❌ mismatch

normalizeTime/denormalizeTime are inverse operations, so the same full-scale constant must be used on both sides or the value doesn't round-trip — a converted blackbox/Bento preset plays its decay and release noticeably shorter than the source. Attack is already consistent at 9 s. The reader's 38 s is the device-calibrated value (it was introduced when read-back of the amp envelope was implemented), so I aligned the writer (Music1010Creator and BentoCreator) to 38 s.

3. Maschine 2/3 — modulation (filter/pitch) envelope time conversions

In MaschinePresetAccessor the modulation envelope (used for the filter and pitch envelopes) is converted differently from the amplitude envelope in the same file:

  • Reading: attack and decay are left in milliseconds (mapToAttackMillis / mapToDecayAndRelease without the / 1000.0 the amp envelope applies), so they come out a thousand times too long; the release skips mapToDecayAndRelease entirely and uses the raw normalized value.
  • Writing: the release skips decayAndReleaseMillisToInput, writing raw milliseconds into the parameter row instead of the device's encoded value.

Fixed so the modulation envelope uses the same conversion as the amplitude envelope (read: … / 1000.0; write: decayAndReleaseMillisToInput (…)). Read and write offsets (148/156/160/164) already match, so this only corrects the value mapping.


All four changed files compile. (The tree currently has an unrelated XMLUtils.escapeAttribute compile error in OmnisphereCreator at main HEAD against the vendored uitools jar; it is independent of these changes.) CHANGELOG updated with a per-format entry.

…Maschine 2/3

Three independent envelope-time conversion bugs found while auditing the
creators and detectors. Each is a self-contained fix; the amplitude
envelope of the same format is the correct reference in every case.

* disting EX: a misplaced parenthesis in the amplitude decay conversion
  divided only the decay time (not hold + decay) by the time constant, so
  any hold time was effectively dropped from the written decay.
  Now (hold + decay) is divided as a whole, matching the reader
  (decay = 0.02 * exp(0.0521 * value)).

* 1010music (blackbox and Bento): the amplitude decay and release were
  written with a 25 s full-scale but read back with a 38 s full-scale, so
  a decay/release did not round-trip and played noticeably shorter than
  the source. The attack already used 9 s on both sides; decay and
  release now use the 38 s read scale as well.

* Maschine 2/3: the modulation (filter/pitch) envelope times were
  converted incorrectly. When reading, the attack and decay stayed in
  milliseconds instead of seconds (a thousand times too long) and the
  release skipped the time-curve mapping entirely; when writing, the
  release skipped that mapping as well. The modulation envelope now uses
  the same conversion as the amplitude envelope in the same file.
@git-moss git-moss merged commit a83dca3 into git-moss:main Jul 8, 2026
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.

2 participants