--- id: Bbeierle12/Skill-MCP-Claude/audio-analysis version: "55a77101" license: MIT install: manual updated: 2026-07-27 --- # audio-analysis — audio-analysis provides tools to decompose audio signals into their frequency components using FFT algorithms, enabling detailed spectral visualization and analysis. Extract magnitude and phase data across the frequency spectrum to understand audio characteristics, detect patterns, and power advanced audio processing workflows. Publisher: Bbeierle12 · Stars: 8 · Updated: 2026-07-27 Install (manual): `git clone https://github.com/Bbeierle12/Skill-MCP-Claude` ## SKILL.md # Audio Analysis FFT, frequency extraction, and audio data analysis. ## Quick Start ```javascript import * as Tone from 'tone'; // Create analyzer const analyser = new Tone.Analyser('fft', 256); const player = new Tone.Player('/audio/music.mp3'); player.connect(analyser); player.toDestination(); // Get frequency data const frequencyData = analyser.getValue(); // Float32Array ``` ## Analyzer Types ### FFT Analyzer ```javascript // FFT (Fast Fourier Transform) - frequency spectrum const fftAnalyser = new Tone.Analyser({ type: 'fft', size: 256, // Must be power of 2: 32, 64, 128, 256, 512, 1024, 2048 smoothing: 0.8 // 0-1, higher = smoother transitions }); // Returns Float32Array of dB values (typically -100 to 0) const fftData = fftAnalyser.getValue(); ``` ### Waveform Analyzer ```javascript // Waveform - time domain data const waveformAnalyser = new Tone.Analyser({ type: 'waveform', size: 1024 }); // Returns Float32Array of amplitude values (-1 to 1) const waveformData = waveformAnalyser.getValue(); ``` ### Meter (Volume Level) ```javascript // Meter - overall volume level const meter = new Tone.Meter({ smoothing: 0.9, normalRange: false // true for 0-1, false for dB }); player.connect(meter); // Get current level const level = meter.getValue(); // dB or 0-1 ``` ### FFT Size Impact | Size | Frequency Resolution | Time Resolution | Use Case | |------|---------------------|-----------------|----------| | 32 | Low | High | Beat detection | | 128 | Medium | Medium | General visualization | | 256 | Good | Good | Balanced (default) | | 1024 | High | Low | Detailed spectrum | | 2048 | Very High | Very Low | Audio analysis tools | ## Frequency Bands ### Manual Band Extraction ```javascript const analyser = new Tone.Analyser('fft', 256); function getFrequencyBands() { const data = analyser.getValue(); const binCount = data.length; // Define frequency band ranges (approximate for 44.1kHz sample rate) // Each bin = (sampleRate / 2) / binCount Hz const bands = { sub: average(data, 0, Math.floor(binCount * 0.03)), // ~20-60 Hz bass: average(data, Math.floor(binCount * 0.03), Math.floor(binCount * 0.08)), // ~60-250 Hz lowMid: average(data, Math.floor(binCount * 0.08), Math.floor(binCount * 0.15)), // ~250-500 Hz mid: average(data, Math.floor(binCount * 0.15), Math.floor(binCount * 0.3)), // ~500-2000 Hz highMid: average(data, Math.floor(binCount * 0.3), Math.floor(binCount * 0.5)), // ~2000-4000 Hz high: average(data, Math.floor(binCount * 0.5), binCount) // ~4000+ Hz }; return bands; } function average(data, start, end) { let sum = 0; for (let i = start; i < end; i++) { sum += data[i]; } return sum / (end - start); } ``` ### Normalized Band Values ```javascript function getNormalizedBands() { const bands = getFrequencyBands(); // Convert dB to 0-1 range (assuming -100 to 0 dB range) const normalize = (db) => Math.max(0, Math.min(1, (db + 100) / 100)); return { sub: normalize(bands.sub), bass: normalize(bands.bass), lowMid: normalize(bands.lowMid), mid: normalize(bands.mid), highMid: normalize(bands.highMid), high: normalize(bands.high) }; } ``` ## Beat Detection ### Simple Peak Detection ```javascript class BeatDetector { constructor(threshold = 0.7, decay = 0.98) { this.threshold = threshold; this.decay = decay; this.peak = 0; this.lastBeat = 0; this.minInterval = 200; // Minimum ms between beats } detect(analyser) { const data = analyser.getValue(); // Focus on bass frequencies for beat detection const bassEnergy = this.getBassEnergy(data); // Decay the peak this.peak *= this.decay; // Update peak if higher if (bassEnergy > this.peak) { this.peak = bassEnergy; } // Detect beat const now = Date.now(); const threshold = this.peak * this.threshold; if (bassEnergy > threshold && now - this.lastBeat > this.minInterval) { this.lastBeat = now; return true; } return false; } getBassEnergy(data) { // Average of low frequency bins let sum = 0; const bassRange = Math.floor(data.length * 0.1); for (let i = 0; i < bassRange; i++) { // Convert dB to linear and sum sum += Math.pow(10, data[i] / 20); } return sum / bassRange; } } // Usage const beatDetector = new BeatDetector(); const analyser = new Tone.Analyser('fft', 256); function update() { if (beatDetector.detect(analyser)) { console.log('Beat!'); // Trigger visual effect } requestAnimationFrame(update); } ``` ### Energy History Beat Detection ```javascript class EnergyBeatDetector { constructor(historySize = 43, sensitivity = 1.3) { this.history = new Array(historySize).fill(0); this.sensitivity = sensitivity; this.historyIndex = 0; } detect(analyser) { const data = analyser.getValue(); const currentEnergy = this.calculateEnergy(data); // Calculate average energy from history const avgEnergy = this.history.reduce((a, b) => a + b) / this.history.length; // Update history this.history[this.historyIndex] = currentEnergy; this.historyIndex = (this.historyIndex + 1) % this.history.length; // Beat if current energy exceeds average by sensitivity factor return currentEnergy > avgEnergy * this.sensitivity; } calculateEnergy(data) { let energy = 0; for (let i = 0; i < data.length; i++) { const amplitude = Math.pow(10, data[i] / 20); energy += amplitude * amplitude; } return energy; } } ``` ## Amplitude Analysis ### RMS (Root Mean Square) ```javascript function getRMS(analyser) { const waveform = analyser.getValue(); // Waveform analyzer let sum = 0; for (let i = 0; i < waveform.length; i++) { sum += waveform[i] * waveform[i]; } return Math.sqrt(sum / waveform.length); } ``` ### Peak Amplitude ```javascript function getPeakAmplitude(analyser) { const waveform = analyser.getValue(); let peak = 0; for (let i = 0; i < waveform.length; i++) { const abs = Math.abs(waveform[i]); if (abs > peak) peak = abs; } return peak; } ``` ## Smoothing Techniques ### Exponential Smoothing ```javascript class SmoothValue { constructor(smoothing = 0.9) { this.value = 0; this.smoothing = smoothing; } update(newValue) { this.value = this.smoothing * this.value + (1 - this.smoothing) * newValue; return this.value; } } // Usage const smoothBass = new SmoothValue(0.85); const bassLevel = smoothBass.update(rawBassLevel); ``` ### Moving Average ```javascript class MovingAverage { constructor(size = 10) { this.size = size; this.values = []; } update(value) { this.values.push(value); if (this.values.length > this.size) { this.values.shift(); } return this.values.reduce((a, b) => a + b) / this.values.length; } } ``` ## Complete Analysis System ```javascript class AudioAnalysisSystem { constructor() { this.fftAnalyser = new Tone.Analyser('fft', 256); this.waveformAnalyser = new Tone.Analyser('waveform', 1024); this.meter = new Tone.Meter({ smoothing: 0.9 }); this.smoothers = { bass: new SmoothValue(0.85), mid: new SmoothValue(0.9), high: new SmoothValue(0.9), volume: new SmoothValue(0.95) }; this.beatDetector = new BeatDetector(); } connect(source) { source.connect(this.fftAnalyser); source.connect(this.waveformAnalyser); source.connect(this.meter); source.toDestination(); } getAnalysis() { const fft = this.fftAnalyser.getValue(); const waveform = this.waveformAnalyser.getValue(); const volume = this.meter.getValue(); const bands = this.extractBands(fft); return { // Raw data fft, waveform, // Smoothed bands (0-1) bass: this.smoothers.bass.update(bands.bass), mid: this.smoothers.mid.update(bands.mid), high: this.smoothers.high.update(bands.high), // Volume volume: this.smoothers.volume.update(this.normalizeDb(volume)), volumeDb: volume, // Beat isBeat: this.beatDetector.detect(this.fftAnalyser), // Waveform metrics rms: this.getRMS(waveform), peak: this.getPeak(waveform) }; } extractBands(fft) { const len = fft.length; return { bass: this.normalizeDb(this.avgRange(fft, 0, len * 0.1)), mid: this.normalizeDb(this.avgRange(fft, len * 0.1, len * 0.5)), high: this.normalizeDb(this.avgRange(fft, len * 0.5, len)) }; } avgRange(data, start, end) { let sum = 0; const s = Math.floor(start); const e = Math.floor(end); for (let i = s; i < e; i++) sum += data[i]; return sum / (e - s); } normalizeDb(db) { return Math.max(0, Math.min(1, (db + 100) / 100)); } getRMS(waveform) { let sum = 0; for (let i = 0; i < waveform.length; i++) { sum += waveform[i] * waveform[i]; } return Math.sqrt(sum / waveform.length); } getPeak(waveform) { let peak = 0; for (let i = 0; i < waveform.length; i++) { const abs = Math.abs(waveform[i]); if (abs > peak) peak = abs; } return peak; } dispose() { this.fftAnalyser.dispose(); this.waveformAnalyser.dispose(); this.meter.dispose(); } } ``` ## Temporal Collapse Usage ```javascript class TemporalAudioAnalysis extends AudioAnalysisSystem { getCountdownData() { const analysis = this.getAnalysis(); return { // For bloom intensity glowIntensity: analysis.bass * 0.5 + analysis.volume * 0.5, // For particle speed particleEnergy: analysis.mid, // For chromatic aberration distortion: analysis.high * 0.3, // For digit pulse pulse: analysis.isBeat ? 1 : 0, // For background intensity ambientLevel: analysis.rms }; } } ``` ## Performance Tips ```javascript // 1. Use appropriate FFT size const analyser = new Tone.Analyser('fft', 128); // Smaller = faster // 2. Don't analyze every frame if not needed let frameCount = 0; function update() { if (frameCount % 2 === 0) { // Every other frame const data = analyser.getValue(); } frameCount++; } // 3. Reuse arrays const dataArray = new Float32Array(256); analyser.getValue(dataArray); // Pass in array to avoid allocation // 4. Use smoothing to reduce visual jitter const smoothedValue = smoother.update(rawValue); ``` ## Reference - See `audio-playback` for loading and playing audio - See `audio-reactive` for connecting analysis to visuals - See `audio-router` for audio domain routing [View on SkillFed](https://skillfed.io/Bbeierle12/Skill-MCP-Claude/audio-analysis) · [View on GitHub](https://github.com/Bbeierle12/Skill-MCP-Claude)