### Basic Example Setup Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/examples/readme.md Standard setup for running any of the provided examples. Navigate to the example directory, install dependencies, and start the development server. ```bash cd examples/ npm install npm run dev ``` -------------------------------- ### Setup and Run Project Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/contributing.md Follow these steps to fork, clone, install dependencies, run tests, and build the library. ```bash git clone https://github.com/YOUR_USERNAME/realtime-bpm-analyzer.git cd realtime-bpm-analyzer npm install npm test npm run build ``` -------------------------------- ### Install Dependencies for All Examples Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/examples/readme.md Run this command from the root of the repository to install dependencies for all example projects. ```bash npm run examples:install ``` -------------------------------- ### Install and Run Project Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/examples/01-vanilla-basic/readme.md Use these commands to install dependencies and start the local development server. Open http://localhost:3000 in your browser to access the application. ```bash npm install npm run dev ``` -------------------------------- ### Run Examples Locally Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/readme.md Instructions for setting up and running the library's examples locally. This involves installing dependencies and running specific example workspaces. ```bash # Install dependencies npm install # Run a specific example npm run dev --workspace=examples/01-vanilla-basic # Available examples: # - 01-vanilla-basic, 02-vanilla-streaming, 03-vanilla-microphone # - 04-react-basic, 05-react-streaming, 06-react-microphone # - 07-vue-basic, 08-vue-streaming, 09-vue-microphone ``` -------------------------------- ### Start All Example Servers Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/readme.md Run this command in one terminal to start all example servers for live, interactive documentation. ```bash cd docs npm run dev:examples ``` -------------------------------- ### Build All Examples Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/examples/readme.md Build all example projects from the root of the repository. ```bash npm run examples:build ``` -------------------------------- ### Run Individual Example Server Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/readme.md Navigate to a specific example's directory and run this command to test it individually. The documentation's iframe will connect to the running example. ```bash # Example: run vanilla basic example cd examples/01-vanilla-basic npm run dev ``` -------------------------------- ### Quick Start: Realtime BPM Analysis Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/readme.md A basic example demonstrating how to create a BPM analyzer instance, connect an audio source, and listen for BPM detection events. Requires an AudioContext. ```typescript import { createRealtimeBpmAnalyzer } from 'realtime-bpm-analyzer'; // Create analyzer const analyzer = await createRealtimeBpmAnalyzer(audioContext); // Connect your audio source audioSource.connect(analyzer.node); // Listen for BPM detection analyzer.on('bpm', (data) => { console.log('BPM detected:', data.bpm[0].tempo); }); ``` -------------------------------- ### Start Documentation Server Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/readme.md Run this command in a second terminal to start the main documentation server. Visit http://localhost:5173 to view. ```bash cd docs npm run dev ``` -------------------------------- ### Install realtime-bpm-analyzer Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/examples/react.md Install the realtime-bpm-analyzer package using npm. ```bash npm install realtime-bpm-analyzer ``` -------------------------------- ### Run a Specific Example Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/examples/readme.md Execute a specific example project using npm run dev with the workspace flag. ```bash npm run dev --workspace=examples/01-vanilla-basic ``` -------------------------------- ### Build Documentation for Production Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/readme.md Execute this command to generate API documentation, build the VitePress site, and compile all examples for production deployment. ```bash cd docs npm run build ``` -------------------------------- ### Content Security Policy Example Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/security.md Example Content Security Policy configuration that allows AudioContext and AudioWorklet, as well as blob URLs for worklet loading. ```csp worker-src blob:; script-src 'self' blob:; ``` -------------------------------- ### Install with pnpm Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/getting-started.md Use pnpm to add the realtime-bpm-analyzer package to your project dependencies. ```bash pnpm add realtime-bpm-analyzer ``` -------------------------------- ### Install with yarn Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/getting-started.md Use yarn to add the realtime-bpm-analyzer package to your project dependencies. ```bash yarn add realtime-bpm-analyzer ``` -------------------------------- ### Example BPM Conversion Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/core-concepts.md Demonstrates the BPM calculation using a sample interval of 500 milliseconds. ```plaintext 60,000 / 500 = 120 BPM ``` -------------------------------- ### Setup and Use Realtime BPM Analyzer in TypeScript Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/getting-started.md This snippet shows how to initialize the analyzer, connect it to an audio source, and handle BPM detection events. It uses `createRealtimeBpmAnalyzer` and `getBiquadFilter` for audio processing and event listeners for 'bpm' and 'bpmStable' events. ```typescript import { createRealtimeBpmAnalyzer, getBiquadFilter, type BpmCandidates } from 'realtime-bpm-analyzer'; async function setupBPMAnalyzer(): Promise { const audioContext = new AudioContext(); const bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext); const audioElement = document.getElementById('track') as HTMLAudioElement; const source = audioContext.createMediaElementSource(audioElement); const lowpass = getBiquadFilter(audioContext); source.connect(lowpass).connect(bpmAnalyzer.node); source.connect(audioContext.destination); bpmAnalyzer.on('bpm', (data: BpmCandidates) => { handleBPMUpdate(data, false); }); bpmAnalyzer.on('bpmStable', (data: BpmCandidates) => { handleBPMUpdate(data, true); }); } function handleBPMUpdate(data: BpmCandidates, isStable: boolean): void { if (data.bpm.length > 0) { const topCandidate = data.bpm[0]; console.log(`Detected BPM: ${topCandidate.tempo} (count: ${topCandidate.count})`); } } ``` -------------------------------- ### useBpm Hook for Real-time BPM Analysis Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/react-bpm-hook.md This hook manages the state and lifecycle for real-time BPM analysis. It handles starting and stopping the analysis, manages audio contexts and analyzers, and provides BPM and stableBpm values. Ensure 'start' is called from a user gesture. ```typescript import { useCallback, useEffect, useRef, useState } from 'react'; import { createRealtimeBpmAnalyzer, getBiquadFilter, type BpmAnalyzer, } from 'realtime-bpm-analyzer'; type Source = | { type: 'audio'; element: HTMLAudioElement } | { type: 'microphone' } | { type: 'stream'; url: string }; export type UseBpmState = 'idle' | 'starting' | 'listening' | 'error'; export interface UseBpmReturn { /** Live BPM — updates ~once per second. Null until first detection. */ bpm: number | null; /** Stable BPM — high-confidence value. Null until algorithm settles. */ stableBpm: number | null; /** Current state. Drives UI affordances. */ state: UseBpmState; /** Error from getUserMedia, audio context, or worklet load. */ error: Error | null; /** Begin analysis. Must be called from a user gesture (click, touch). */ start: () => Promise; /** Stop analysis. Releases mic, closes audio context. Idempotent. */ stop: () => void; } export function useBpm(source: Source | null): UseBpmReturn { const [bpm, setBpm] = useState(null); const [stableBpm, setStableBpm] = useState(null); const [state, setState] = useState('idle'); const [error, setError] = useState(null); // Live refs — survive re-renders, don't trigger effects. const audioContextRef = useRef(null); const analyzerRef = useRef(null); const streamRef = useRef(null); const stop = useCallback(() => { analyzerRef.current?.disconnect(); analyzerRef.current = null; streamRef.current?.getTracks().forEach((track) => track.stop()); streamRef.current = null; audioContextRef.current?.close(); audioContextRef.current = null; setState('idle'); }, []); const start = useCallback(async () => { if (!source) { setError(new Error('useBpm: no source provided')); setState('error'); return; } if (state !== 'idle') return; // already running or starting setState('starting'); setError(null); try { const audioContext = new AudioContext(); audioContextRef.current = audioContext; await audioContext.resume(); let sourceNode: AudioNode; if (source.type === 'audio') { sourceNode = audioContext.createMediaElementSource(source.element); // Audio elements need to play through the speakers too. sourceNode.connect(audioContext.destination); } else if (source.type === 'microphone') { const stream = await navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: false, noiseSuppression: false, autoGainControl: false, }, }); streamRef.current = stream; sourceNode = audioContext.createMediaStreamSource(stream); // Mic must NOT connect to destination — feedback loop. } else { // type: 'stream' const audio = new Audio(source.url); audio.crossOrigin = 'anonymous'; await audio.play(); sourceNode = audioContext.createMediaElementSource(audio); sourceNode.connect(audioContext.destination); } const analyzer = await createRealtimeBpmAnalyzer(audioContext); analyzerRef.current = analyzer; const lowpass = getBiquadFilter(audioContext); sourceNode.connect(lowpass).connect(analyzer.node); analyzer.on('bpm', ({ bpm: candidates }) => { if (candidates.length > 0) setBpm(candidates[0].tempo); }); analyzer.on('bpmStable', ({ bpm: candidates }) => { if (candidates.length > 0) setStableBpm(candidates[0].tempo); }); setState('listening'); } catch (err) { setError(err instanceof Error ? err : new Error(String(err))); setState('error'); stop(); } }, [source, state, stop]); // StrictMode-safe cleanup. The empty deps array means cleanup runs on // unmount only — but in StrictMode, React mounts twice in dev, so the // first cleanup MUST tear everything down. The refs above guarantee // idempotency: stop() can be called safely from a cleanup that runs on // a hook instance that never started anything. useEffect(() => { return () => stop(); }, [stop]); return { bpm, stableBpm, state, error, start, stop }; } ``` -------------------------------- ### Complete BPM Analyzer Pattern Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/bpm-from-microphone.md This code snippet demonstrates the complete pattern for starting and stopping BPM analysis from microphone input. It includes setting up the audio context, requesting microphone access, building the audio graph, and handling BPM updates. Ensure this code runs within a user gesture handler. ```typescript import { createRealtimeBpmAnalyzer, getBiquadFilter, BpmAnalyzer } from 'realtime-bpm-analyzer'; let audioContext: AudioContext | null = null; let mediaStream: MediaStream | null = null; let bpmAnalyzer: BpmAnalyzer | null = null; async function startListening(onBpm: (bpm: number) => void) { // 1. Build the audio context inside the user gesture. audioContext = new AudioContext(); await audioContext.resume(); // 2. Ask for microphone access. Disable noise suppression and echo // cancellation — they're tuned for voice and will eat the // rhythmic transients we want to detect. mediaStream = await navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: false, noiseSuppression: false, autoGainControl: false, }, }); // 3. Build the audio graph: mic -> lowpass -> analyzer. const source = audioContext.createMediaStreamSource(mediaStream); const lowpass = getBiquadFilter(audioContext); bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext); source.connect(lowpass).connect(bpmAnalyzer.node); // Note: do NOT connect to audioContext.destination. Feedback loop. // 4. Surface stable detections to the application. bpmAnalyzer.on('bpmStable', ({ bpm }) => { if (bpm.length > 0) { onBpm(bpm[0].tempo); } }); } async function stopListening() { bpmAnalyzer?.disconnect(); bpmAnalyzer = null; // Stop every track on the MediaStream — without this the browser // keeps the microphone open and the recording indicator on. mediaStream?.getTracks().forEach((track) => track.stop()); mediaStream = null; await audioContext?.close(); audioContext = null; } // Wire up to the UI. document.getElementById('start')?.addEventListener('click', () => { startListening((bpm) => { document.getElementById('output')!.textContent = `${bpm} BPM`; }); }); document.getElementById('stop')?.addEventListener('click', () => { stopListening(); }); ``` -------------------------------- ### Request Microphone Access and Handle Errors Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/bpm-from-microphone.md Request microphone access using navigator.mediaDevices.getUserMedia, disabling echo cancellation, noise suppression, and auto gain control. Handles 'NotAllowedError' and other exceptions, guiding the user to browser settings if access is denied. ```typescript try { mediaStream = await navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: false, noiseSuppression: false, autoGainControl: false, }, }); } catch (err) { if (err instanceof DOMException && err.name === 'NotAllowedError') { showError('Microphone access denied. Click the lock icon in the URL bar.'); } else { showError(`Microphone unavailable: ${err}`); } } ``` -------------------------------- ### Real-time Microphone BPM Analysis Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/examples/microphone-input.md This snippet demonstrates how to set up real-time BPM analysis from microphone input. It requires requesting microphone access, creating an AudioContext, initializing the BPM analyzer, connecting the microphone stream to the analyzer, and setting up event listeners for BPM updates. ```typescript import { createRealtimeBpmAnalyzer } from 'realtime-bpm-analyzer'; // 1. Request microphone access const stream = await navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: false, noiseSuppression: false, autoGainControl: false, }, }); // 2. Create audio context and analyzer const audioContext = new AudioContext(); const bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext); // 3. Connect microphone to analyzer const source = audioContext.createMediaStreamSource(stream); source.connect(bpmAnalyzer.node); // 4. Listen for BPM updates bpmAnalyzer.on('bpm', (data) => { console.log('Current BPM:', data.bpm[0].tempo); }); bpmAnalyzer.on('bpmStable', (data) => { console.log('Stable BPM detected:', data.bpm[0].tempo); }); ``` -------------------------------- ### JavaScript Implementation for BPM Analysis Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/getting-started.md This script sets up the audio context, initializes the BPM analyzer, connects the audio graph including a low-pass filter, and listens for BPM events to update the display. ```javascript import { createRealtimeBpmAnalyzer, getBiquadFilter } from 'realtime-bpm-analyzer'; async function setupBPMAnalyzer() { // Create audio context const audioContext = new AudioContext(); // Create the BPM analyzer (returns event emitter wrapping AudioWorkletNode) const bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext); // Get audio element const audioElement = document.getElementById('track'); // Create media source from audio element const source = audioContext.createMediaElementSource(audioElement); // Create and configure low-pass filter (helps isolate bass frequencies) const lowpass = getBiquadFilter(audioContext); // Connect the audio graph - use .node to connect the AudioWorkletNode source.connect(lowpass); lowpass.connect(bpmAnalyzer.node); source.connect(audioContext.destination); // Listen for BPM events using the event emitter API bpmAnalyzer.on('bpm', (data) => { // Continuous BPM updates console.log('Current BPM candidates:', data.bpm); updateDisplay(data.bpm); }); bpmAnalyzer.on('bpmStable', (data) => { // Stable BPM detected (more confident result) console.log('Stable BPM:', data.bpm); updateDisplay(data.bpm, true); }); // Start playback when user clicks play audioElement.play(); } function updateDisplay(bpmCandidates, isStable = false) { const bpmDisplay = document.getElementById('bpm'); if (bpmCandidates && bpmCandidates.length > 0) { const topBPM = bpmCandidates[0].tempo; bpmDisplay.textContent = `BPM: ${topBPM}${isStable ? ' ✓' : ''}`; bpmDisplay.style.color = isStable ? 'green' : 'orange'; } } // Initialize when page loads setupBPMAnalyzer(); ``` -------------------------------- ### Create Realtime BPM Analyzer with Configuration Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/core-concepts.md Customize the analyzer's behavior by providing configuration options during creation. Options include continuous analysis, stabilization time, mute time, and debug events. ```typescript const bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext, { // Enable continuous analysis with auto-reset continuousAnalysis: false, // Time before auto-reset (only if continuousAnalysis = true) stabilizationTime: 20000, // 20 seconds // Minimum time between peaks at same threshold (prevents double-detection) muteTimeInIndexes: 10000, // Enable debug events debug: false }); ``` -------------------------------- ### Iterative Threshold Testing for Peak Detection Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/how-it-works.md This code iterates through multiple thresholds, starting from a high value and decreasing, to find a suitable level for detecting peaks. It stops once a sufficient number of peaks are found, ensuring adaptability to different audio dynamics. ```javascript // Try thresholds from 0.9 down to 0.3 for (let threshold = 0.9; threshold >= 0.3; threshold -= 0.05) { const peaks = findPeaksAtThreshold(data, threshold); if (peaks.length >= minPeaks) { // Found enough peaks, use this threshold break; } } ``` -------------------------------- ### Initialize Real-time BPM Analyzer Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/performance.md Use this function to create an instance of the BPM analyzer for real-time analysis. It automatically utilizes AudioWorklet for better performance. ```typescript const analyzerNode = await createRealtimeBpmAnalyzer(audioContext); ``` -------------------------------- ### HTML Structure for BPM Analysis Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/getting-started.md Set up an HTML file with an audio element and a display div for BPM results. This serves as the basic structure for the JavaScript implementation. ```html BPM Analyzer Demo
BPM: --
``` -------------------------------- ### Include via CDN Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/getting-started.md Import the createRealtimeBpmAnalyzer function directly from a CDN for browser usage. ```html ``` -------------------------------- ### Create Real-Time BPM Analyzer Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/core-concepts.md Initializes the BPM analyzer for real-time audio analysis. This mode accumulates data throughout playback and provides increasingly accurate results without automatic reset. ```typescript const bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext); // Analyzes continuously, accumulates confidence ``` -------------------------------- ### Initialize AudioContext with User Gesture Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/performance.md Ensure `AudioContext` is created and resumed in response to a user gesture, which is a requirement for mobile Safari. ```typescript button.addEventListener('click', async () => { const audioContext = new AudioContext(); await audioContext.resume(); // Important for iOS // ... rest of setup }); ``` -------------------------------- ### iOS-Specific AudioContext Initialization Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/browser-compatibility.md This code provides an iOS-specific way to initialize the AudioContext, including a fallback for 'webkitAudioContext'. It also includes critical steps to resume the context after user interaction and check its state. ```typescript // iOS-specific initialization const audioContext = new (window.AudioContext || window.webkitAudioContext)(); // Always resume after user interaction await audioContext.resume(); // Check state if (audioContext.state === 'suspended') { await audioContext.resume(); } ``` -------------------------------- ### Core BPM Analyzer Integration Pattern Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/realtime-bpm-detection.md This TypeScript snippet demonstrates the fundamental pattern for integrating the BPM analyzer. It shows how to create the analyzer, set up a filter, connect the audio source, and listen for BPM events. Ensure you have an AudioContext and an AudioNode source. ```typescript import { createRealtimeBpmAnalyzer, getBiquadFilter } from 'realtime-bpm-analyzer'; const audioContext = new AudioContext(); const bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext); const lowpass = getBiquadFilter(audioContext); // Build the source — file, mic, or stream. See sections below. const source = /* an AudioNode you create */; // Wire the analysis chain. Filter into analyzer; everything is parallel. source.connect(lowpass).connect(bpmAnalyzer.node); // Listen. bpmAnalyzer.on('bpm', ({ bpm }) => console.log('candidate:', bpm[0]?.tempo)); bpmAnalyzer.on('bpmStable', ({ bpm }) => console.log('stable:', bpm[0]?.tempo)); ``` -------------------------------- ### Use State for Audio Context in React Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/examples/react.md Demonstrates how to create and store the AudioContext and BpmAnalyzer instances in React component state for reuse. ```typescript const [audioContext, setAudioContext] = useState(null); const [bpmAnalyzer, setBpmAnalyzer] = useState(null); ``` -------------------------------- ### Real-time Audio BPM Analysis Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/index.md Analyze audio in real time using the realtime-bpm-analyzer library. This snippet demonstrates setting up the audio context, connecting audio sources, and listening for BPM events. ```typescript import { createRealtimeBpmAnalyzer, getBiquadFilter } from 'realtime-bpm-analyzer'; // Create audio context const audioContext = new AudioContext(); // Create the BPM analyzer processor const bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext); // Set up audio source const track = document.getElementById('audio') as HTMLAudioElement; const source = audioContext.createMediaElementSource(track); const lowpass = getBiquadFilter(audioContext); // Connect nodes source.connect(lowpass).connect(bpmAnalyzer.node); source.connect(audioContext.destination); // Listen for BPM events bpmAnalyzer.on('bpm', (data) => console.log('Current BPM:', data.bpm)); bpmAnalyzer.on('bpmStable', (data) => console.log('Stable BPM detected:', data.bpm)); // Cleanup when done bpmAnalyzer.disconnect(); ``` -------------------------------- ### AudioContext Initialization with User Gesture Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/browser-compatibility.md On Safari (macOS & iOS), AudioContext creation must be triggered by a user interaction. Always resume the AudioContext after it's created to ensure it functions correctly, especially on iOS. ```typescript // Always create AudioContext after user interaction button.addEventListener('click', async () => { const audioContext = new AudioContext(); await audioContext.resume(); // Critical for iOS! // ... continue setup }); ``` -------------------------------- ### React Component Using useBpm Hook Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/react-bpm-hook.md Demonstrates how to integrate the `useBpm` hook into a React component to detect BPM from an audio element. It shows how to manage the audio source, control playback, and display the detected BPM and state. ```tsx function MyApp() { const audioRef = useRef(null); const { bpm, stableBpm, state, error, start, stop } = useBpm(audioRef); return (
); } ``` -------------------------------- ### Sequential File Analysis for Memory Management Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/performance.md Process multiple files sequentially using a `for...of` loop to prevent memory issues. Ensure each `AudioContext` is closed after use. ```typescript async function analyzeFiles(files) { const results = []; for (const file of files) { const audioContext = new AudioContext(); const arrayBuffer = await file.arrayBuffer(); const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); const bpm = await analyzeFullBuffer(audioBuffer); results.push({ file: file.name, bpm }); // Clean up await audioContext.close(); } return results; } ``` -------------------------------- ### Analyze Full Audio Buffer Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/examples/basic-usage.md Analyze the complete audio file at once. This approach is suitable for music library organization, DJ applications, fitness apps, and any scenario requiring the tempo of a complete song. Ensure you have imported the 'analyzeFullBuffer' function. ```typescript import { analyzeFullBuffer } from 'realtime-bpm-analyzer'; // 1. Create an audio context const audioContext = new AudioContext(); // 2. Load and decode your audio file const arrayBuffer = await file.arrayBuffer(); const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); // 3. Analyze the buffer const tempos = await analyzeFullBuffer(audioBuffer); // 4. Get the detected BPM const bpm = tempos[0].tempo; console.log(`Detected BPM: ${bpm}`); ``` -------------------------------- ### Configure Continuous Analysis Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/performance.md Enable continuous analysis for long-running applications like streams or radio. Adjust stabilizationTime based on audio complexity to balance memory usage and accuracy. ```typescript createRealtimeBpmAnalyzer(audioContext, { continuousAnalysis: true, stabilizationTime: 20000, // Adjust based on needs }); ``` -------------------------------- ### Handle Autoplay Policies Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/browser-compatibility.md This snippet demonstrates how to handle browser autoplay policies by waiting for user interaction before playing audio. Ensure AudioContext is resumed if required. ```typescript button.addEventListener('click', async () => { const audioContext = new AudioContext(); await audioContext.resume(); // May be required const audio = document.getElementById('track'); await audio.play(); // Now allowed }); ``` -------------------------------- ### Configure Real-time BPM Analyzer for Continuous Analysis Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/how-it-works.md Use this configuration to enable continuous analysis and set a stabilization time for clearing data in long-running analysis, preventing memory leaks. ```typescript createRealtimeBpmAnalyzer(audioContext, { continuousAnalysis: true, stabilizationTime: 20000 // Clear data every 20 seconds }); ``` -------------------------------- ### BPM Detection from Media Element Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/realtime-bpm-detection.md Use this pattern when you have an existing audio or video element on your page. Ensure the audio context is resumed on user gesture and connect the source to both the analyzer and the audio destination to hear the playback. ```typescript import { createRealtimeBpmAnalyzer, getBiquadFilter } from 'realtime-bpm-analyzer'; const audioContext = new AudioContext(); const audioElement = document.querySelector('audio')!; // Resume the context on user gesture. Required by autoplay policies. await audioContext.resume(); const source = audioContext.createMediaElementSource(audioElement); const lowpass = getBiquadFilter(audioContext); const bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext); // Analysis chain — into the analyzer. source.connect(lowpass).connect(bpmAnalyzer.node); // Playback chain — straight to the speakers, in parallel. source.connect(audioContext.destination); bpmAnalyzer.on('bpmStable', ({ bpm }) => { if (bpm.length > 0) { console.log(`Stable tempo: ${bpm[0].tempo} BPM`); } }); ``` -------------------------------- ### Basic React BPM Analyzer Pattern Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/examples/react.md This is the essential pattern for integrating the Realtime BPM Analyzer in a React application. It covers creating the audio context, initializing the analyzer, listening for BPM events, and handling cleanup. ```typescript import { createRealtimeBpmAnalyzer } from 'realtime-bpm-analyzer'; import { useState, useEffect } from 'react'; function BPMAnalyzer() { const [bpm, setBpm] = useState(null); const [audioContext, setAudioContext] = useState(null); const [bpmAnalyzer, setBpmAnalyzer] = useState(null); const startAnalysis = async () => { // Create audio context const ctx = new AudioContext(); setAudioContext(ctx); // Create analyzer const analyzer = await createRealtimeBpmAnalyzer(ctx); setBpmAnalyzer(analyzer); // Listen for BPM analyzer.on('bpmStable', (data) => { if (data.bpm.length > 0) { setBpm(data.bpm[0].tempo); } }); // Connect your audio source here... }; useEffect(() => { return () => { bpmAnalyzer?.disconnect(); audioContext?.close(); }; }, []); // Cleanup only on unmount return (
{bpm &&
BPM: {bpm}
}
); } ``` -------------------------------- ### BPM Detection from Microphone Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/realtime-bpm-detection.md Use this pattern to detect BPM from the user's microphone input. This requires a secure origin (HTTPS or localhost). Critically, do not connect the microphone source to the audio context destination to avoid feedback loops. ```typescript import { createRealtimeBpmAnalyzer, getBiquadFilter } from 'realtime-bpm-analyzer'; const audioContext = new AudioContext(); // HTTPS is required. getUserMedia only works on secure origins (or localhost). const stream = await navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: false, noiseSuppression: false, autoGainControl: false, }, }); const source = audioContext.createMediaStreamSource(stream); const lowpass = getBiquadFilter(audioContext); const bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext); source.connect(lowpass).connect(bpmAnalyzer.node); // Do NOT connect to destination — feedback loop. bpmAnalyzer.on('bpmStable', ({ bpm }) => { if (bpm.length > 0) { console.log(`Mic tempo: ${bpm[0].tempo} BPM`); } }); ``` -------------------------------- ### Listen to BPM Events Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/realtime-bpm-detection.md Use the 'bpm' event for live UI updates and 'bpmStable' for application state when the algorithm has high confidence. Both events provide the detected BPM value. ```typescript bpmAnalyzer.on('bpm', ({ bpm }) => { // Fires roughly every chunk (~once per second). // Always available — even early, before detection has settled. // Use for a live-updating UI display. }); bpmAnalyzer.on('bpmStable', ({ bpm }) => { // Fires when the algorithm has high confidence in a value. // Slower to fire — usually 5–15 seconds in. // Use for "the answer" — pinning the BPM into application state. }); ``` -------------------------------- ### Handle Live and Stable BPM Events Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/bpm-from-microphone.md Listen for 'bpm' events for live updates and 'bpmStable' events for high-confidence BPM readings. Use 'bpm' for immediate UI feedback and 'bpmStable' for persistent application state. ```typescript bpmAnalyzer.on('bpm', ({ bpm }) => { if (bpm.length > 0) { setDisplayBpm(bpm[0].tempo); } }); bpmAnalyzer.on('bpmStable', ({ bpm }) => { if (bpm.length > 0) { setStableBpm(bpm[0].tempo); setDisplayState('locked'); } }); ``` -------------------------------- ### Analyze BPM from an Audio Element in React Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/react-bpm-hook.md Use the `useBpm` hook with an HTML audio element. Ensure the ref is available before initializing the hook by using a conditional check. ```tsx import { useRef } from 'react'; import { useBpm } from './useBpm'; export function FileAnalyzer() { const audioRef = useRef(null); const { bpm, stableBpm, state, error, start, stop } = useBpm( audioRef.current ? { type: 'audio', element: audioRef.current } : null ); return (
); } ``` -------------------------------- ### Use bpmStable for Battery Efficiency Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/performance.md Subscribe to `bpmStable` events instead of continuous `bpm` updates to reduce processing load and conserve battery on mobile devices. ```typescript analyzerNode.on('bpmStable', (data) => { handleBPMUpdate(data.bpm); }); ``` -------------------------------- ### Create Continuous BPM Analyzer with Auto-Reset Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/core-concepts.md Initializes the BPM analyzer for continuous streams with an automatic reset feature. The analyzer resets after a specified stabilization period, preventing memory buildup in long-running scenarios. ```typescript const bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext, { continuousAnalysis: true, stabilizationTime: 20000 // Reset every 20 seconds }); ``` -------------------------------- ### Analyze Live Audio Stream BPM Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/examples/streaming-audio.md Connect an audio element to the BPM analyzer and listen for updates. Ensure the audio element is connected to the audio context destination to hear the stream. ```typescript import { createRealtimeBpmAnalyzer } from 'realtime-bpm-analyzer'; // 1. Create audio context and analyzer const audioContext = new AudioContext(); const bpmAnalyzer = await createRealtimeBpmAnalyzer(audioContext); // 2. Connect audio element to analyzer const audioElement = document.querySelector('audio'); const source = audioContext.createMediaElementSource(audioElement); source.connect(bpmAnalyzer.node); bpmAnalyzer.node.connect(audioContext.destination); // Connect to hear the audio // 3. Listen for BPM updates bpmAnalyzer.on('bpm', (data) => { console.log('Current BPM:', data.bpm[0].tempo); }); // 4. Start playing the stream audioElement.src = 'https://stream-url.com/audio'; await audioElement.play(); ``` -------------------------------- ### Configure Fast BPM Detection Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/performance.md Set a lower `stabilizationTime` for faster, less accurate BPM detection. Use when speed is critical and approximate BPM is acceptable. ```typescript createRealtimeBpmAnalyzer(audioContext, { stabilizationTime: 10000 // Faster, less accurate }); ``` -------------------------------- ### Test Browser Feature Support Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/browser-compatibility.md This TypeScript function checks for the availability of key Web Audio API features and media devices. It logs a compatibility report to the console and returns the compatibility status along with the detected features. ```typescript function checkBrowserSupport() { const report = { audioContext: !!window.AudioContext, audioWorklet: !!(window.AudioContext && AudioContext.prototype.audioWorklet), mediaDevices: !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia), webAudio: !!(window.AudioContext || window.webkitAudioContext), }; console.table(report); const isCompatible = report.audioContext && report.audioWorklet; return { compatible: isCompatible, features: report }; } // Usage const support = checkBrowserSupport(); if (support.compatible) { console.log('✅ Browser is fully compatible'); } else { console.error('❌ Browser is not compatible'); console.log('Missing features:', Object.entries(support.features) .filter(([key, value]) => !value) .map(([key]) => key) ); } ``` -------------------------------- ### Check AudioContext Buffer Size Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/performance.md Query the AudioContext's baseLatency to understand the buffer size. Lower buffer sizes reduce latency but increase CPU load, while higher buffer sizes do the opposite. ```typescript // Check the AudioContext's buffer size console.log('Buffer size:', audioContext.baseLatency); ``` -------------------------------- ### Check AudioContext State Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/browser-compatibility.md Logs the current state of the AudioContext. If the state is 'suspended', it suggests calling `audioContext.resume()`. If 'closed', a new AudioContext should be created. ```typescript console.log('AudioContext state:', audioContext.state); // Should be: 'running' // If 'suspended': call audioContext.resume() // If 'closed': create new AudioContext ``` -------------------------------- ### Feature Detection for AudioWorklet Support Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/browser-compatibility.md Use this function to check if the browser supports the necessary AudioWorklet API before initializing the analyzer. It ensures that the Web Audio API and its AudioWorklet prototype are available. ```typescript function isSupported() { return !!( window.AudioContext && AudioContext.prototype.audioWorklet ); } if (isSupported()) { // Safe to use the library const audioContext = new AudioContext(); const analyzer = await createRealtimeBpmAnalyzer(audioContext); } else { // Show error message alert('Your browser does not support BPM analysis. Please update your browser.'); } ``` -------------------------------- ### Use Refs for Reactive State in Vue Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/examples/vue.md Demonstrates how to use Vue's `ref` function to manage reactive state for BPM values and analyzer instances. This ensures that UI updates automatically when the state changes. ```typescript import { ref } from 'vue'; const bpm = ref(0); const audioContext = ref(null); const bpmAnalyzer = ref(null); ``` -------------------------------- ### Basic Vue 3 BPM Analyzer Integration Pattern Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/examples/vue.md A fundamental Vue 3 component structure using Composition API to initialize the BPM analyzer, handle events, and manage its lifecycle. Connect your audio source to `bpmAnalyzer.value.node`. ```vue ``` -------------------------------- ### Listen to BPM Events Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/how-it-works.md Subscribe to the 'bpm' event to receive continuous tempo updates during analysis. This event may fluctuate as more data is processed. ```typescript analyzer.on('bpm', (data) => { // data.bpm: Array of tempo candidates // data.threshold: Detection threshold used console.log('Current BPM:', data.bpm[0].tempo); console.log('Count:', data.bpm[0].count); }); ``` -------------------------------- ### Analyze BPM from Microphone Input in React Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/react-bpm-hook.md Integrate the `useBpm` hook to analyze BPM directly from the user's microphone. This requires no DOM element reference, only specifying the 'microphone' type. ```tsx export function MicAnalyzer() { const { bpm, stableBpm, state, error, start, stop } = useBpm({ type: 'microphone' }); return (
Live BPM: {bpm ?? '—'}
Stable BPM: {stableBpm ?? '—'}
{state === 'starting' &&
Asking for microphone…
} {error &&
{error.message}
}
); } ``` -------------------------------- ### Listen for Continuous BPM Events Source: https://github.com/dlepaux/realtime-bpm-analyzer/blob/main/docs/guide/core-concepts.md Use this snippet to log detected BPM candidates and the current detection threshold as they are continuously emitted during analysis. ```typescript analyzer.on('bpm', (data) => { // data.bpm: Array of tempo candidates // data.threshold: Current detection threshold console.log('BPM:', data.bpm[0].tempo); console.log('Threshold:', data.threshold); }); ```