From 059d3f709b468428acff71be33990fdfe8237d1a Mon Sep 17 00:00:00 2001
From: Eric Rosenbaum <eric.rosenbaum@gmail.com>
Date: Wed, 4 Sep 2019 11:01:10 -0400
Subject: [PATCH] Use a waveshaper to hard limit samples

---
 src/lib/audio/effects/volume-effect.js | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/lib/audio/effects/volume-effect.js b/src/lib/audio/effects/volume-effect.js
index 0cfcd6415..a5d12a987 100644
--- a/src/lib/audio/effects/volume-effect.js
+++ b/src/lib/audio/effects/volume-effect.js
@@ -14,8 +14,16 @@ class VolumeEffect {
         this.gain.gain.setValueAtTime(volume, endSeconds);
         this.gain.gain.exponentialRampToValueAtTime(1.0, endSeconds + this.rampLength);
 
+        // Use a waveshaper node to prevent sample values from exceeding -1 or 1.
+        // Without this, gain can cause samples to exceed this range, then they
+        // are clipped on save, and the sound is distorted on load.
+        this.waveShaper = this.audioContext.createWaveShaper();
+        this.waveShaper.curve = new Float32Array([-1, 1]);
+        this.waveShaper.oversample = 'none';
+
         this.input.connect(this.gain);
-        this.gain.connect(this.output);
+        this.gain.connect(this.waveShaper);
+        this.waveShaper.connect(this.output);
     }
 }
 
-- 
GitLab