diff --git a/.gitignore b/.gitignore index 837cae3..7262e33 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ DEPLOYMENT.md *.sln *.sw? *.psd +audio-debug.html +src/audio-debug.ts diff --git a/src/components/piano-roll/PianoKeys.tsx b/src/components/piano-roll/PianoKeys.tsx index a4e8fe4..db2c123 100644 --- a/src/components/piano-roll/PianoKeys.tsx +++ b/src/components/piano-roll/PianoKeys.tsx @@ -243,4 +243,4 @@ const PianoKeys: React.FC = ({ activeRegion }) => { ); }; -export default PianoKeys; +export default PianoKeys; diff --git a/src/core/audio-interface/KGAudioBus.ts b/src/core/audio-interface/KGAudioBus.ts index eb1e499..2956fb6 100644 --- a/src/core/audio-interface/KGAudioBus.ts +++ b/src/core/audio-interface/KGAudioBus.ts @@ -4,6 +4,7 @@ import { FLUIDR3_INSTRUMENT_MAP } from '../../constants/generalMidiConstants'; import type { InstrumentType } from '../track/KGMidiTrack'; import { KGToneBuffersPool } from './KGToneBuffersPool'; import { KGToneSamplerFactory } from './KGToneSamplerFactory'; +import { createStereoTrackPanner } from './createStereoTrackPanner'; // InstrumentType is defined in KGMidiTrack and re-used here @@ -100,7 +101,7 @@ export class KGAudioBus { ]); // Create the audio bus instance - const panner = new Tone.Panner(pan); + const panner = createStereoTrackPanner(pan); sampler.connect(panner); const audioBus = new KGAudioBus(sampler, audioBuffers, instrument, panner, volume, pan, muted, solo); diff --git a/src/core/audio-interface/KGAudioInterface.ts b/src/core/audio-interface/KGAudioInterface.ts index 323c4cb..be3e55c 100644 --- a/src/core/audio-interface/KGAudioInterface.ts +++ b/src/core/audio-interface/KGAudioInterface.ts @@ -953,7 +953,7 @@ export class KGAudioInterface { const normalizedVelocity = velocity / 127; // Normalize to 0-1 const triggerTime = time ?? Tone.now(); this.applyTrackAutomationForCurrentBeat(trackId); - + // Check if track should play considering solo logic const hasSoloedTracks = this.hasSoloedTracks(); if (audioBus.shouldPlayWithSolo(hasSoloedTracks)) { diff --git a/src/core/audio-interface/KGAudioPlayerBus.ts b/src/core/audio-interface/KGAudioPlayerBus.ts index 3daacc6..2b78f72 100644 --- a/src/core/audio-interface/KGAudioPlayerBus.ts +++ b/src/core/audio-interface/KGAudioPlayerBus.ts @@ -1,5 +1,6 @@ import * as Tone from 'tone'; import { AUDIO_INTERFACE_CONSTANTS } from '../../constants/coreConstants'; +import { createStereoTrackPanner } from './createStereoTrackPanner'; /** * KGAudioPlayerBus - Represents an audio playback bus for a track. @@ -61,7 +62,7 @@ export class KGAudioPlayerBus { ): Promise { try { const gainNode = new Tone.Gain(1); - const pannerNode = new Tone.Panner(pan); + const pannerNode = createStereoTrackPanner(pan); gainNode.connect(pannerNode); const bus = new KGAudioPlayerBus(gainNode, pannerNode, volume, pan, muted, solo); console.log('KGAudioPlayerBus created successfully'); diff --git a/src/core/audio-interface/KGOfflineRenderer.ts b/src/core/audio-interface/KGOfflineRenderer.ts index a3a4a45..17c9848 100644 --- a/src/core/audio-interface/KGOfflineRenderer.ts +++ b/src/core/audio-interface/KGOfflineRenderer.ts @@ -29,6 +29,7 @@ import { beatRangeToSeconds, beatToSeconds, findGlobalTrackByType, getEffectiveB import { GlobalTrackType } from '../global-track'; import { ConfigManager } from '../config/ConfigManager'; import { Mp3Encoder } from '@breezystack/lamejs'; +import { createStereoTrackPanner } from './createStereoTrackPanner'; export interface RenderOptions { sampleRate?: number; // default 44100 @@ -332,7 +333,7 @@ export class KGOfflineRenderer { // Track volumes are stored in dB across the app, with 0 meaning unity gain. sampler.volume.value = 0; const trackGain = new Tone.Gain(getOfflineTrackGain(trackInfo.volume, trackInfo.muted)); - const trackPanner = new Tone.Panner(0); + const trackPanner = createStereoTrackPanner(0); sampler.connect(trackGain); trackGain.connect(trackPanner); trackPanner.connect(masterGain); @@ -439,7 +440,7 @@ export class KGOfflineRenderer { if (!shouldPlay(trackInfo, hasSoloedTracks)) continue; const trackGain = new Tone.Gain(getOfflineTrackGain(trackInfo.volume, trackInfo.muted)); - const trackPanner = new Tone.Panner(0); + const trackPanner = createStereoTrackPanner(0); trackGain.connect(trackPanner); trackPanner.connect(masterGain); applyOfflineTrackAutomation( diff --git a/src/core/audio-interface/createStereoTrackPanner.ts b/src/core/audio-interface/createStereoTrackPanner.ts new file mode 100644 index 0000000..0b9753e --- /dev/null +++ b/src/core/audio-interface/createStereoTrackPanner.ts @@ -0,0 +1,8 @@ +import * as Tone from 'tone'; + +export function createStereoTrackPanner(pan: number = 0): Tone.Panner { + return new Tone.Panner({ + pan, + channelCount: 2, + }); +}