@sonoscope/core
@sonoscope/core is the zero-dependency WebGL2 and WASM-accelerated rendering engine powering Sonoscope.
Core Capabilities
Section titled “Core Capabilities”- Coordinated Viewport Sync: Synchronize time and frequency zoom/pan effortlessly between multiple spectrogram, waveform, and ruler renderers.
- WASM STFT Pipeline: Rust-compiled WebAssembly engine calculating Fast Fourier Transforms with high efficiency.
- WebGL2 Tile Rendering: GPU shader-driven spectrogram tile computation with built-in colormaps (
viridis,plasma,inferno,magma,cividis,turbo,gray). - Flexible Frequency Scales: Support for
linear,log, andmelperceptual frequency scales. - Decoupled Playhead & Rulers: Customizable time and frequency rulers with responsive ticks.
- Native Navigation: First-class pan and zoom navigation on viewers and the central
Sonoscopeinstance with automatic lifecycle cleanup.
Creating a Sonoscope Instance
Section titled “Creating a Sonoscope Instance”The Sonoscope class is the central coordinator for audio playback, viewport state, and viewer creation.
import { Sonoscope } from "@sonoscope/core";
// From Audio Elementconst scope = await Sonoscope.fromAudio(audioElement, { followPlayback: "page",});
// From Blob / Fileconst fileScope = await Sonoscope.fromBlob(audioBlob);
// From URLconst urlScope = await Sonoscope.fromUrl("https://example.com/sound.mp3");Full reference: Sonoscope, ISonoscope, SonoscopeOptions.
Viewers
Section titled “Viewers”Spectrogram Viewer
Section titled “Spectrogram Viewer”Creates a SpectrogramViewer instance attached to a canvas.
const spectrogram = scope.createSpectrogram(canvas, { colorMap: "turbo", frequencyScale: "mel", minDb: -90, maxDb: 0, windowSize: 1024, hopSize: 256,});
// Attach 2D navigation (defaults to both time and frequency axes)scope.attachNavigation(canvas);Full reference: SpectrogramViewer, ISpectrogramViewer, SpectrogramConfig.
Waveform Viewer
Section titled “Waveform Viewer”Creates a WaveformViewer instance attached to a canvas.
const waveform = scope.createWaveform(canvas, { colorMap: "turbo", amplitudeScale: 1.0,});
// Attach 1D temporal navigation (defaults to time axis)scope.attachNavigation(canvas, { axis: "time" });Full reference: WaveformViewer, IWaveformViewer, WaveformConfig.
Rulers & Playheads
Section titled “Rulers & Playheads”Creates a TimeRulerViewer or FrequencyRulerViewer, and attaches playhead overlays via attachPlayheadOverlay.
import { attachPlayheadOverlay } from "@sonoscope/core";
const timeRuler = scope.createTimeRuler(timeCanvas, { program: "ticks", tickPosition: "top",});scope.attachNavigation(timeCanvas, { axis: "time" });
const freqRuler = scope.createFrequencyRuler(freqCanvas, { program: "ticks", frequencyScale: "mel", tickPosition: "right",});scope.attachNavigation(freqCanvas, { axis: "frequency" });
attachPlayheadOverlay(containerElement, scope);Full reference: TimeRulerViewer, FrequencyRulerViewer, TimeRulerConfig, FrequencyRulerConfig, attachPlayheadOverlay.
Interactive Navigation
Section titled “Interactive Navigation”Sonoscope provides coordinated navigation via scope.attachNavigation(container, options?) on the root Sonoscope instance or directly via attachNavigation.
Attaching Navigation
Section titled “Attaching Navigation”You can attach interactive pan and zoom navigation directly to any <canvas> or wrapping container element (such as a <div>):
const scope = await Sonoscope.fromUrl(audioUrl);const spec = scope.createSpectrogram(specCanvas, { frequencyScale: "mel" });
// 1. Spectrogram navigation (pans and zooms both time & frequency)const detachSpecNav = scope.attachNavigation(specCanvas);
// 2. Waveform navigation (time-only axis)const detachWaveNav = scope.attachNavigation(waveCanvas, { axis: "time" });
// 3. Time Ruler (time axis) and Frequency Ruler (frequency axis)scope.attachNavigation(timeCanvas, { axis: "time" });scope.attachNavigation(freqCanvas, { axis: "frequency" });Navigation Options & Modifiers
Section titled “Navigation Options & Modifiers”attachNavigation accepts comprehensive configuration for axes, modifier keys, sensitivities, and wheel/drag behavior:
scope.attachNavigation(specCanvas, { // Constrain navigation to a specific axis: 'both' | 'time' | 'frequency' axis: "both",
// Configure or toggle mouse wheel navigation wheel: { panSensitivity: 1.0, zoomSensitivity: 0.0015, zoomModifier: "alt", // 'ctrl' | 'shift' | 'alt' | 'meta' | 'none' frequencyModifier: "shift", },
// Configure or toggle drag navigation drag: { button: 0, // 0 = left, 1 = middle, 2 = right modifier: "none", dragThreshold: 3, cursor: true, },
onNavigate: (viewport) => { console.log("Viewport updated:", viewport); },});Full reference: attachNavigation, NavigationOptions, IViewportController.
Lifecycle & Automatic Cleanup
Section titled “Lifecycle & Automatic Cleanup”- Calling
scope.attachNavigation()returns a manualdetach: () => voidcleanup function. - All attached navigation listeners are also automatically cleaned up whenever
scope.destroy()is called.