UNPKG

wave-roll

Version:

JavaScript Library for Comparative MIDI Piano-Roll Visualization

167 lines 5.35 kB
/** * Sampler Manager for MIDI playback * Handles Tone.js sampler creation, loading, and playback */ import * as Tone from "tone"; import { NoteData } from "@/lib/midi/types"; export interface SamplerTrack { sampler: Tone.Sampler; delay: Tone.Delay | null; gate: Tone.Gain; panner: Tone.Panner; muted: boolean; } export declare class SamplerManager { /** Legacy single sampler (used for single-file players) */ private sampler; /** Global panner for legacy single-sampler path */ private panner; /** Hard gate for legacy single-sampler path */ private gate; /** Map of fileId -> {sampler, panner, muted} for multi-file playback */ private trackSamplers; /** Current Tone.Part for scheduling note events */ private part; /** Notes to be played */ private notes; /** MIDI manager reference */ private midiManager; /** Alignment delay in seconds to compensate downstream (e.g., WAV PitchShift) latency */ private alignmentDelaySec; constructor(notes: NoteData[], midiManager?: any); private getTrack; private applySamplerVolume; private applyPannerPan; /** Return notes filtered to intersect the [loopStart, loopEnd) window, or all if window inactive. */ private filterNotesByLoopWindow; /** Compute visual->transport scale factor. */ private computeScaleToTransport; /** Map notes to Part events without fileId. */ private notesToEvents; /** Map notes to Part events with fileId. */ private notesToEventsWithFileId; /** Build Tone.Part from events and callback, configure loop settings. */ private buildPart; /** * Initialize samplers - either multi-track or legacy single sampler */ initialize(options: { soundFont?: string; volume?: number; }): Promise<void>; /** * Set up per-track samplers for multi-file playback * @returns true if multi-file setup succeeded, false for fallback */ private setupTrackSamplers; /** * Fallback: Set up legacy single sampler */ private setupLegacySampler; /** * Create note part for Tone.js scheduling */ setupNotePart(loopStartVisual?: number | null, loopEndVisual?: number | null, options?: { repeat?: boolean; duration?: number; tempo?: number; originalTempo?: number; }): void; private setupMultiTrackPart; private setupLegacyPart; /** * Start the part at specified offset */ startPart(time: string | number, offset?: number): void; /** * Stop and cancel the part */ stopPart(): void; /** * Restart the part for seamless looping * This avoids recreating the Part which can cause gaps */ restartPartAtLoop(): void; /** * Set volume for all samplers */ setVolume(volume: number): void; /** * Set pan for all samplers */ setPan(pan: number): void; /** * Set alignment delay in seconds for all sampler outputs (compensate external FX latency). */ setAlignmentDelaySec(delaySec: number): void; /** * Set pan for a specific file */ setFilePan(fileId: string, pan: number): void; /** * Set mute state for a specific file */ setFileMute(fileId: string, mute: boolean): void; /** * Ensure the specified track is audible. If its sampler volume is effectively * silent (<= SILENT_DB), lift it to the provided masterVolume. */ ensureTrackAudible(fileId: string, masterVolume: number): void; /** * Retrigger any notes that are currently sustaining at `currentTime` for the given file. * Useful when a track is unmuted while the transport is already running so that * long-held notes become audible immediately without waiting for the next onset. */ retriggerHeldNotes(fileId: string, currentTime: number): void; /** * Retrigger held notes for all unmuted tracks at the current time * Useful after seeking to ensure long notes are audible at the new position */ retriggerAllUnmutedHeldNotes(currentTime: number): void; /** * Set volume for a specific file */ setFileVolume(fileId: string, volume: number, masterVolume: number): void; /** * Get file mute states */ getFileMuteStates(): Map<string, boolean>; /** * Get file volume states */ getFileVolumeStates(): Map<string, number>; /** * Check if all tracks have zero volume */ areAllTracksZeroVolume(): boolean; /** * Check if all tracks are muted */ areAllTracksMuted(): boolean; /** * Clean up resources */ destroy(): void; /** * Immediately stop/kill any currently sounding voices to prevent tail/bleed. * Best-effort: tries Sampler/PolySynth-specific release helpers if available. */ stopAllVoicesImmediate(): void; /** * Get the current part instance */ getPart(): Tone.Part | null; /** * Hard mute all track gates to instantly silence any residual sound. */ hardMuteAllGates(): void; /** * Unmute all track gates. */ hardUnmuteAllGates(): void; /** * Check if samplers are initialized */ isInitialized(): boolean; } //# sourceMappingURL=sampler-manager.d.ts.map