Simplify audio chain - bypass all effects to fix distortion

- Bypass colorizer entirely (master -> destination directly)
- Remove wave channel lowpass filter
- Clean, direct audio path with no processing
- Should eliminate all distortion artifacts
This commit is contained in:
b1rdmania
2026-01-20 19:58:54 +00:00
parent 6dec8bf7cd
commit 5b294f2e5a
2 changed files with 7 additions and 17 deletions
+4 -5
View File
@@ -77,19 +77,18 @@ export class GameBoyAPU {
this.audioContext = audioContext || new AudioContext(); this.audioContext = audioContext || new AudioContext();
this.config = { ...DEFAULT_V2_CONFIG, ...config }; this.config = { ...DEFAULT_V2_CONFIG, ...config };
// Create colorizer with DMG preset for authentic sound // Create colorizer (but don't use it for now - bypassed)
this.colorizer = new GameBoyColorizer( this.colorizer = new GameBoyColorizer(
this.audioContext, this.audioContext,
GameBoyColorizer.createPreset('dmg') GameBoyColorizer.createPreset()
); );
// Create master gain // Create master gain
this.masterGain = this.audioContext.createGain(); this.masterGain = this.audioContext.createGain();
this.masterGain.gain.value = this.config.masterVolume; this.masterGain.gain.value = this.config.masterVolume;
// Wire: master -> colorizer -> destination // SIMPLIFIED: master -> destination (bypass colorizer to avoid distortion)
this.masterGain.connect(this.colorizer.getInput()); this.masterGain.connect(this.audioContext.destination);
this.colorizer.getOutput().connect(this.audioContext.destination);
// Initialize all channels // Initialize all channels
this.initializeChannels(); this.initializeChannels();
+3 -12
View File
@@ -34,7 +34,6 @@ export class WaveChannel {
private volume: WaveVolume = 1; // Default to 100% private volume: WaveVolume = 1; // Default to 100%
private outputNode: GainNode; private outputNode: GainNode;
private currentPreset: WavePreset; private currentPreset: WavePreset;
private lowpassFilter: BiquadFilterNode;
constructor( constructor(
audioContext: AudioContext, audioContext: AudioContext,
@@ -45,14 +44,6 @@ export class WaveChannel {
this.outputNode = outputNode; this.outputNode = outputNode;
this.currentPreset = preset; this.currentPreset = preset;
// Create a low-pass filter to warm up the sound
// GB wave channel had natural rolloff from the DAC
this.lowpassFilter = audioContext.createBiquadFilter();
this.lowpassFilter.type = 'lowpass';
this.lowpassFilter.frequency.value = 2000; // Cut harsh highs
this.lowpassFilter.Q.value = 0.7;
this.lowpassFilter.connect(outputNode);
// Initialize wavetable with preset // Initialize wavetable with preset
this.waveTable = new WaveTable(); this.waveTable = new WaveTable();
this.loadPreset(preset); this.loadPreset(preset);
@@ -158,9 +149,9 @@ export class WaveChannel {
const stopTime = now + duration + releaseTime; const stopTime = now + duration + releaseTime;
gain.gain.linearRampToValueAtTime(0.001, stopTime); gain.gain.linearRampToValueAtTime(0.001, stopTime);
// Connect nodes through low-pass filter for warmer sound // Connect nodes directly to output
oscillator.connect(gain); oscillator.connect(gain);
gain.connect(this.lowpassFilter); gain.connect(this.outputNode);
// Schedule playback // Schedule playback
oscillator.start(now); oscillator.start(now);
@@ -220,7 +211,7 @@ export class WaveChannel {
gain.gain.linearRampToValueAtTime(0.001, stopTime); gain.gain.linearRampToValueAtTime(0.001, stopTime);
oscillator.connect(gain); oscillator.connect(gain);
gain.connect(this.lowpassFilter); gain.connect(this.outputNode);
oscillator.start(now); oscillator.start(now);
oscillator.stop(stopTime + 0.01); oscillator.stop(stopTime + 0.01);