@lucaismyname/ginger 0.0.32 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/waveform/useAudioPeaks.ts","../../src/internal/fft.ts","../../src/waveform/analyzeAudioFile.ts","../../src/waveform/useAudioFileAnalysis.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport type UseAudioPeaksState = {\n peaks: number[];\n isLoading: boolean;\n error: string | null;\n};\n\nexport function useAudioPeaks(\n fileUrl: string | null | undefined,\n buckets = 64,\n): UseAudioPeaksState {\n const [state, setState] = useState<UseAudioPeaksState>({\n peaks: [],\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ peaks: [], isLoading: false, error: null });\n return;\n }\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n void (async () => {\n try {\n const response = await fetch(fileUrl);\n if (!response.ok)\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n const buffer = await response.arrayBuffer();\n const audioContext = new AudioContext();\n try {\n const audioBuffer = await audioContext.decodeAudioData(buffer);\n const channel = audioBuffer.getChannelData(0);\n const step = Math.max(1, Math.floor(channel.length / buckets));\n const peaks: number[] = [];\n for (let i = 0; i < buckets; i += 1) {\n let max = 0;\n const start = i * step;\n const end = Math.min(channel.length, start + step);\n for (let j = start; j < end; j += 1) {\n max = Math.max(max, Math.abs(channel[j] ?? 0));\n }\n peaks.push(max);\n }\n if (!cancelled) {\n setState({ peaks, isLoading: false, error: null });\n }\n } finally {\n await audioContext.close().catch(() => {});\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n peaks: [],\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to decode peaks\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [buckets, fileUrl]);\n\n return state;\n}\n","/** In-place radix-2 Cooley–Tukey FFT; `length` must be a power of 2 and >= 2. */\nexport function fftInPlace(re: Float64Array, im: Float64Array): void {\n const n = re.length;\n if (n !== im.length || n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"fftInPlace: length must be equal powers of 2 >= 2\");\n }\n\n let j = 0;\n for (let i = 0; i < n - 1; i += 1) {\n if (i < j) {\n const tr = re[i]!;\n const ti = im[i]!;\n re[i] = re[j]!;\n im[i] = im[j]!;\n re[j] = tr;\n im[j] = ti;\n }\n let k = n >> 1;\n while (k <= j) {\n j -= k;\n k >>= 1;\n }\n j += k;\n }\n\n for (let len = 2; len <= n; len <<= 1) {\n const ang = (-2 * Math.PI) / len;\n const wlenR = Math.cos(ang);\n const wlenI = Math.sin(ang);\n for (let i = 0; i < n; i += len) {\n let wr = 1;\n let wi = 0;\n const half = len >> 1;\n for (let k = 0; k < half; k += 1) {\n const u = i + k;\n const v = u + half;\n const tr = wr * re[v]! - wi * im[v]!;\n const ti = wr * im[v]! + wi * re[v]!;\n re[v] = re[u]! - tr;\n im[v] = im[u]! - ti;\n re[u] = re[u]! + tr;\n im[u] = im[u]! + ti;\n const nwr = wr * wlenR - wi * wlenI;\n const nwi = wr * wlenI + wi * wlenR;\n wr = nwr;\n wi = nwi;\n }\n }\n }\n}\n\n/** Magnitude spectrum for real input: length `n` (power of 2). Returns `n/2` magnitudes for bins 0..n/2-1. */\nexport function realFftMagnitudes(samples: Float64Array): Float64Array {\n const n = samples.length;\n if (n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"realFftMagnitudes: length must be a power of 2 >= 2\");\n }\n const re = new Float64Array(n);\n const im = new Float64Array(n);\n for (let i = 0; i < n; i += 1) re[i] = samples[i]!;\n fftInPlace(re, im);\n const out = new Float64Array(n >> 1);\n for (let k = 0; k < n >> 1; k += 1) {\n out[k] = Math.hypot(re[k]!, im[k]!);\n }\n return out;\n}\n\nexport function hanningWindow(length: number): Float64Array {\n const w = new Float64Array(length);\n if (length === 1) {\n w[0] = 1;\n return w;\n }\n const denom = length - 1;\n for (let i = 0; i < length; i += 1) {\n w[i] = 0.5 * (1 - Math.cos((2 * Math.PI * i) / denom));\n }\n return w;\n}\n\nexport function clampFftSize(n: number): number {\n const p = 2 ** Math.round(Math.log2(n));\n return Math.min(8192, Math.max(32, p));\n}\n","import { clampFftSize, hanningWindow, realFftMagnitudes } from \"../internal/fft\";\n\nexport type AnalyzeAudioFileOptions = {\n /** Number of time rows in the amplitude grid (and spectrogram if enabled). Default 128. */\n timeSlices?: number;\n /** Sub-buckets per time slice for the amplitude grid. Default 8. */\n samplesPerSlice?: number;\n /** When true, include `spectrogram` using windowed FFT per time slice. Default false. */\n spectrogram?: boolean;\n /** FFT length for spectrogram (power of 2). Default 1024. */\n fftSize?: number;\n /** Number of frequency bins to keep per row (first bins; capped by fftSize/2). Default 256. */\n frequencyBins?: number;\n /** Channel index, or `\"mix\"` for equal mix of all channels. Default 0. */\n channel?: number | \"mix\";\n};\n\nexport type AudioFileAnalysis = {\n duration: number;\n sampleRate: number;\n /** Peak amplitudes in [0, 1]: `timeSlices` rows × `samplesPerSlice` columns. */\n amplitudeGrid: number[][];\n /** Optional magnitude spectrogram rows, each length `frequencyBins`, normalized to [0, 1] globally. */\n spectrogram?: number[][];\n};\n\nfunction mixChannels(buffer: AudioBuffer): Float32Array {\n const { numberOfChannels, length } = buffer;\n if (numberOfChannels === 1) {\n return buffer.getChannelData(0);\n }\n const out = new Float32Array(length);\n const scale = 1 / numberOfChannels;\n for (let c = 0; c < numberOfChannels; c += 1) {\n const ch = buffer.getChannelData(c);\n for (let i = 0; i < length; i += 1) {\n out[i] += ch[i]! * scale;\n }\n }\n return out;\n}\n\nfunction getChannel(buffer: AudioBuffer, channel: number | \"mix\"): Float32Array {\n if (channel === \"mix\") return mixChannels(buffer);\n const idx = Math.max(0, Math.min(buffer.numberOfChannels - 1, channel));\n return buffer.getChannelData(idx);\n}\n\nfunction buildAmplitudeGrid(\n channel: Float32Array,\n timeSlices: number,\n samplesPerSlice: number,\n): number[][] {\n const grid: number[][] = [];\n const len = channel.length;\n if (len === 0) {\n for (let t = 0; t < timeSlices; t += 1) {\n grid.push(Array.from({ length: samplesPerSlice }, () => 0));\n }\n return grid;\n }\n\n const segmentLen = len / timeSlices;\n\n for (let t = 0; t < timeSlices; t += 1) {\n const row: number[] = [];\n const segStart = Math.floor(t * segmentLen);\n const segEnd = Math.floor((t + 1) * segmentLen);\n const segLen = Math.max(1, segEnd - segStart);\n const subLen = segLen / samplesPerSlice;\n\n for (let s = 0; s < samplesPerSlice; s += 1) {\n const a = Math.floor(segStart + s * subLen);\n const b = Math.min(segEnd, Math.floor(segStart + (s + 1) * subLen));\n let peak = 0;\n for (let i = a; i < b; i += 1) {\n peak = Math.max(peak, Math.abs(channel[i] ?? 0));\n }\n row.push(peak);\n }\n grid.push(row);\n }\n return grid;\n}\n\nfunction buildSpectrogram(\n channel: Float32Array,\n timeSlices: number,\n fftSize: number,\n frequencyBins: number,\n): { rows: number[][]; maxMag: number } {\n const rows: number[][] = [];\n let maxMag = 1e-12;\n const len = channel.length;\n const n = clampFftSize(fftSize);\n const half = n >> 1;\n const bins = Math.min(frequencyBins, half);\n const window = hanningWindow(n);\n\n if (len < n) {\n for (let t = 0; t < timeSlices; t += 1) {\n rows.push(Array.from({ length: bins }, () => 0));\n }\n return { rows, maxMag: 1 };\n }\n\n for (let t = 0; t < timeSlices; t += 1) {\n const start =\n timeSlices <= 1 ? 0 : Math.min(Math.floor((t * (len - n)) / (timeSlices - 1)), len - n);\n const frame = new Float64Array(n);\n for (let i = 0; i < n; i += 1) {\n frame[i] = (channel[start + i] ?? 0) * (window[i] ?? 0);\n }\n const mags = realFftMagnitudes(frame);\n const row: number[] = [];\n for (let k = 0; k < bins; k += 1) {\n const v = mags[k] ?? 0;\n row.push(v);\n maxMag = Math.max(maxMag, v);\n }\n rows.push(row);\n }\n\n return { rows, maxMag };\n}\n\n/**\n * Decodes an `AudioBuffer` into visualization-friendly grids (no network).\n */\nexport function analyzeAudioBuffer(\n buffer: AudioBuffer,\n options: AnalyzeAudioFileOptions = {},\n): AudioFileAnalysis {\n const timeSlices = Math.max(1, options.timeSlices ?? 128);\n const samplesPerSlice = Math.max(1, options.samplesPerSlice ?? 8);\n const wantSpec = Boolean(options.spectrogram);\n const fftSize = options.fftSize ?? 1024;\n const frequencyBins = Math.max(1, options.frequencyBins ?? 256);\n const channel = options.channel ?? 0;\n\n const data = getChannel(buffer, channel);\n const amplitudeGrid = buildAmplitudeGrid(data, timeSlices, samplesPerSlice);\n\n const result: AudioFileAnalysis = {\n duration: buffer.duration,\n sampleRate: buffer.sampleRate,\n amplitudeGrid,\n };\n\n if (wantSpec) {\n const { rows, maxMag } = buildSpectrogram(data, timeSlices, fftSize, frequencyBins);\n const norm = maxMag > 0 ? 1 / maxMag : 1;\n result.spectrogram = rows.map((row) => row.map((v) => v * norm));\n }\n\n return result;\n}\n\n/**\n * Fetches a URL, decodes audio to an `AudioBuffer`, runs {@link analyzeAudioBuffer}, then closes the temporary `AudioContext`.\n */\nexport async function analyzeAudioFile(\n fileUrl: string,\n options: AnalyzeAudioFileOptions = {},\n): Promise<AudioFileAnalysis> {\n const response = await fetch(fileUrl);\n if (!response.ok) {\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n }\n const raw = await response.arrayBuffer();\n const Context =\n window.AudioContext ??\n (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const audioContext = new Context();\n try {\n const buffer = await audioContext.decodeAudioData(raw.slice(0));\n return analyzeAudioBuffer(buffer, options);\n } finally {\n await audioContext.close();\n }\n}\n","import { useEffect, useState } from \"react\";\nimport {\n type AnalyzeAudioFileOptions,\n type AudioFileAnalysis,\n analyzeAudioFile,\n} from \"./analyzeAudioFile\";\n\nexport type UseAudioFileAnalysisState = {\n data: AudioFileAnalysis | null;\n isLoading: boolean;\n error: string | null;\n};\n\nexport function useAudioFileAnalysis(\n fileUrl: string | null | undefined,\n options: AnalyzeAudioFileOptions = {},\n): UseAudioFileAnalysisState {\n const [state, setState] = useState<UseAudioFileAnalysisState>({\n data: null,\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n if (typeof window === \"undefined\") {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n\n void (async () => {\n try {\n const data = await analyzeAudioFile(fileUrl, options);\n if (!cancelled) {\n setState({ data, isLoading: false, error: null });\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to analyze audio file\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [\n fileUrl,\n options.timeSlices,\n options.samplesPerSlice,\n options.spectrogram,\n options.fftSize,\n options.frequencyBins,\n options.channel,\n ]);\n\n return state;\n}\n"],"names":["useAudioPeaks","fileUrl","buckets","state","setState","useState","useEffect","cancelled","prev","response","buffer","audioContext","channel","step","peaks","i","max","start","end","j","error","fftInPlace","re","im","n","tr","ti","k","len","ang","wlenR","wlenI","wr","wi","half","u","v","nwr","nwi","realFftMagnitudes","samples","out","hanningWindow","length","w","denom","clampFftSize","p","mixChannels","numberOfChannels","scale","c","ch","getChannel","idx","buildAmplitudeGrid","timeSlices","samplesPerSlice","grid","t","segmentLen","row","segStart","segEnd","subLen","s","a","b","peak","buildSpectrogram","fftSize","frequencyBins","rows","maxMag","bins","window","frame","mags","analyzeAudioBuffer","options","wantSpec","data","amplitudeGrid","result","norm","analyzeAudioFile","raw","Context","useAudioFileAnalysis"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/waveform/getAudioContextConstructor.ts","../../src/waveform/useAudioPeaks.ts","../../src/internal/fft.ts","../../src/waveform/analyzeAudioFile.ts","../../src/waveform/useAudioFileAnalysis.ts"],"sourcesContent":["/**\n * Resolves the runtime `AudioContext` constructor, including legacy `webkitAudioContext` (Safari).\n * Returns `null` when `window` is unavailable or Web Audio is not implemented.\n */\nexport function getAudioContextConstructor():\n | (new (\n contextOptions?: AudioContextOptions,\n ) => AudioContext)\n | null {\n if (typeof window === \"undefined\") return null;\n const C =\n window.AudioContext ??\n (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n return C ?? null;\n}\n","import { useEffect, useState } from \"react\";\nimport { getAudioContextConstructor } from \"./getAudioContextConstructor\";\n\nexport type UseAudioPeaksState = {\n peaks: number[];\n isLoading: boolean;\n error: string | null;\n};\n\nexport function useAudioPeaks(\n fileUrl: string | null | undefined,\n buckets = 64,\n): UseAudioPeaksState {\n const [state, setState] = useState<UseAudioPeaksState>({\n peaks: [],\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ peaks: [], isLoading: false, error: null });\n return;\n }\n if (typeof window === \"undefined\") {\n setState({ peaks: [], isLoading: false, error: null });\n return;\n }\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n void (async () => {\n try {\n const response = await fetch(fileUrl);\n if (!response.ok)\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n const buffer = await response.arrayBuffer();\n const Context = getAudioContextConstructor();\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const audioContext = new Context();\n try {\n const audioBuffer = await audioContext.decodeAudioData(buffer);\n const channel = audioBuffer.getChannelData(0);\n const step = Math.max(1, Math.floor(channel.length / buckets));\n const peaks: number[] = [];\n for (let i = 0; i < buckets; i += 1) {\n let max = 0;\n const start = i * step;\n const end = Math.min(channel.length, start + step);\n for (let j = start; j < end; j += 1) {\n max = Math.max(max, Math.abs(channel[j] ?? 0));\n }\n peaks.push(max);\n }\n if (!cancelled) {\n setState({ peaks, isLoading: false, error: null });\n }\n } finally {\n await audioContext.close().catch(() => {});\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n peaks: [],\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to decode peaks\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [buckets, fileUrl]);\n\n return state;\n}\n","/** In-place radix-2 Cooley–Tukey FFT; `length` must be a power of 2 and >= 2. */\nexport function fftInPlace(re: Float64Array, im: Float64Array): void {\n const n = re.length;\n if (n !== im.length || n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"fftInPlace: length must be equal powers of 2 >= 2\");\n }\n\n let j = 0;\n for (let i = 0; i < n - 1; i += 1) {\n if (i < j) {\n const tr = re[i]!;\n const ti = im[i]!;\n re[i] = re[j]!;\n im[i] = im[j]!;\n re[j] = tr;\n im[j] = ti;\n }\n let k = n >> 1;\n while (k <= j) {\n j -= k;\n k >>= 1;\n }\n j += k;\n }\n\n for (let len = 2; len <= n; len <<= 1) {\n const ang = (-2 * Math.PI) / len;\n const wlenR = Math.cos(ang);\n const wlenI = Math.sin(ang);\n for (let i = 0; i < n; i += len) {\n let wr = 1;\n let wi = 0;\n const half = len >> 1;\n for (let k = 0; k < half; k += 1) {\n const u = i + k;\n const v = u + half;\n const tr = wr * re[v]! - wi * im[v]!;\n const ti = wr * im[v]! + wi * re[v]!;\n re[v] = re[u]! - tr;\n im[v] = im[u]! - ti;\n re[u] = re[u]! + tr;\n im[u] = im[u]! + ti;\n const nwr = wr * wlenR - wi * wlenI;\n const nwi = wr * wlenI + wi * wlenR;\n wr = nwr;\n wi = nwi;\n }\n }\n }\n}\n\n/** Magnitude spectrum for real input: length `n` (power of 2). Returns `n/2` magnitudes for bins 0..n/2-1. */\nexport function realFftMagnitudes(samples: Float64Array): Float64Array {\n const n = samples.length;\n if (n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"realFftMagnitudes: length must be a power of 2 >= 2\");\n }\n const re = new Float64Array(n);\n const im = new Float64Array(n);\n for (let i = 0; i < n; i += 1) re[i] = samples[i]!;\n fftInPlace(re, im);\n const out = new Float64Array(n >> 1);\n for (let k = 0; k < n >> 1; k += 1) {\n out[k] = Math.hypot(re[k]!, im[k]!);\n }\n return out;\n}\n\nexport function hanningWindow(length: number): Float64Array {\n const w = new Float64Array(length);\n if (length === 1) {\n w[0] = 1;\n return w;\n }\n const denom = length - 1;\n for (let i = 0; i < length; i += 1) {\n w[i] = 0.5 * (1 - Math.cos((2 * Math.PI * i) / denom));\n }\n return w;\n}\n\nexport function clampFftSize(n: number): number {\n const p = 2 ** Math.round(Math.log2(n));\n return Math.min(8192, Math.max(32, p));\n}\n","import { clampFftSize, hanningWindow, realFftMagnitudes } from \"../internal/fft\";\nimport { getAudioContextConstructor } from \"./getAudioContextConstructor\";\n\nexport type AnalyzeAudioFileOptions = {\n /** Number of time rows in the amplitude grid (and spectrogram if enabled). Default 128. */\n timeSlices?: number;\n /** Sub-buckets per time slice for the amplitude grid. Default 8. */\n samplesPerSlice?: number;\n /** When true, include `spectrogram` using windowed FFT per time slice. Default false. */\n spectrogram?: boolean;\n /** FFT length for spectrogram (power of 2). Default 1024. */\n fftSize?: number;\n /** Number of frequency bins to keep per row (first bins; capped by fftSize/2). Default 256. */\n frequencyBins?: number;\n /** Channel index, or `\"mix\"` for equal mix of all channels. Default 0. */\n channel?: number | \"mix\";\n};\n\nexport type AudioFileAnalysis = {\n duration: number;\n sampleRate: number;\n /** Peak amplitudes in [0, 1]: `timeSlices` rows × `samplesPerSlice` columns. */\n amplitudeGrid: number[][];\n /** Optional magnitude spectrogram rows, each length `frequencyBins`, normalized to [0, 1] globally. */\n spectrogram?: number[][];\n};\n\nfunction mixChannels(buffer: AudioBuffer): Float32Array {\n const { numberOfChannels, length } = buffer;\n if (numberOfChannels === 1) {\n return buffer.getChannelData(0);\n }\n const out = new Float32Array(length);\n const scale = 1 / numberOfChannels;\n for (let c = 0; c < numberOfChannels; c += 1) {\n const ch = buffer.getChannelData(c);\n for (let i = 0; i < length; i += 1) {\n out[i] += ch[i]! * scale;\n }\n }\n return out;\n}\n\nfunction getChannel(buffer: AudioBuffer, channel: number | \"mix\"): Float32Array {\n if (channel === \"mix\") return mixChannels(buffer);\n const idx = Math.max(0, Math.min(buffer.numberOfChannels - 1, channel));\n return buffer.getChannelData(idx);\n}\n\nfunction buildAmplitudeGrid(\n channel: Float32Array,\n timeSlices: number,\n samplesPerSlice: number,\n): number[][] {\n const grid: number[][] = [];\n const len = channel.length;\n if (len === 0) {\n for (let t = 0; t < timeSlices; t += 1) {\n grid.push(Array.from({ length: samplesPerSlice }, () => 0));\n }\n return grid;\n }\n\n const segmentLen = len / timeSlices;\n\n for (let t = 0; t < timeSlices; t += 1) {\n const row: number[] = [];\n const segStart = Math.floor(t * segmentLen);\n const segEnd = Math.floor((t + 1) * segmentLen);\n const segLen = Math.max(1, segEnd - segStart);\n const subLen = segLen / samplesPerSlice;\n\n for (let s = 0; s < samplesPerSlice; s += 1) {\n const a = Math.floor(segStart + s * subLen);\n const b = Math.min(segEnd, Math.floor(segStart + (s + 1) * subLen));\n let peak = 0;\n for (let i = a; i < b; i += 1) {\n peak = Math.max(peak, Math.abs(channel[i] ?? 0));\n }\n row.push(peak);\n }\n grid.push(row);\n }\n return grid;\n}\n\nfunction buildSpectrogram(\n channel: Float32Array,\n timeSlices: number,\n fftSize: number,\n frequencyBins: number,\n): { rows: number[][]; maxMag: number } {\n const rows: number[][] = [];\n let maxMag = 1e-12;\n const len = channel.length;\n const n = clampFftSize(fftSize);\n const half = n >> 1;\n const bins = Math.min(frequencyBins, half);\n const window = hanningWindow(n);\n\n if (len < n) {\n for (let t = 0; t < timeSlices; t += 1) {\n rows.push(Array.from({ length: bins }, () => 0));\n }\n return { rows, maxMag: 1 };\n }\n\n for (let t = 0; t < timeSlices; t += 1) {\n const start =\n timeSlices <= 1 ? 0 : Math.min(Math.floor((t * (len - n)) / (timeSlices - 1)), len - n);\n const frame = new Float64Array(n);\n for (let i = 0; i < n; i += 1) {\n frame[i] = (channel[start + i] ?? 0) * (window[i] ?? 0);\n }\n const mags = realFftMagnitudes(frame);\n const row: number[] = [];\n for (let k = 0; k < bins; k += 1) {\n const v = mags[k] ?? 0;\n row.push(v);\n maxMag = Math.max(maxMag, v);\n }\n rows.push(row);\n }\n\n return { rows, maxMag };\n}\n\n/**\n * Decodes an `AudioBuffer` into visualization-friendly grids (no network).\n */\nexport function analyzeAudioBuffer(\n buffer: AudioBuffer,\n options: AnalyzeAudioFileOptions = {},\n): AudioFileAnalysis {\n const timeSlices = Math.max(1, options.timeSlices ?? 128);\n const samplesPerSlice = Math.max(1, options.samplesPerSlice ?? 8);\n const wantSpec = Boolean(options.spectrogram);\n const fftSize = options.fftSize ?? 1024;\n const frequencyBins = Math.max(1, options.frequencyBins ?? 256);\n const channel = options.channel ?? 0;\n\n const data = getChannel(buffer, channel);\n const amplitudeGrid = buildAmplitudeGrid(data, timeSlices, samplesPerSlice);\n\n const result: AudioFileAnalysis = {\n duration: buffer.duration,\n sampleRate: buffer.sampleRate,\n amplitudeGrid,\n };\n\n if (wantSpec) {\n const { rows, maxMag } = buildSpectrogram(data, timeSlices, fftSize, frequencyBins);\n const norm = maxMag > 0 ? 1 / maxMag : 1;\n result.spectrogram = rows.map((row) => row.map((v) => v * norm));\n }\n\n return result;\n}\n\n/**\n * Fetches a URL, decodes audio to an `AudioBuffer`, runs {@link analyzeAudioBuffer}, then closes the temporary `AudioContext`.\n */\nexport async function analyzeAudioFile(\n fileUrl: string,\n options: AnalyzeAudioFileOptions = {},\n): Promise<AudioFileAnalysis> {\n const response = await fetch(fileUrl);\n if (!response.ok) {\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n }\n const raw = await response.arrayBuffer();\n const Context = getAudioContextConstructor();\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const audioContext = new Context();\n try {\n const buffer = await audioContext.decodeAudioData(raw.slice(0));\n return analyzeAudioBuffer(buffer, options);\n } finally {\n await audioContext.close();\n }\n}\n","import { useEffect, useState } from \"react\";\nimport {\n type AnalyzeAudioFileOptions,\n type AudioFileAnalysis,\n analyzeAudioFile,\n} from \"./analyzeAudioFile\";\n\nexport type UseAudioFileAnalysisState = {\n data: AudioFileAnalysis | null;\n isLoading: boolean;\n error: string | null;\n};\n\n/** When extending {@link AnalyzeAudioFileOptions}, thread new fields through the destructuring below and the effect dependency array. */\nexport function useAudioFileAnalysis(\n fileUrl: string | null | undefined,\n options: AnalyzeAudioFileOptions = {},\n): UseAudioFileAnalysisState {\n const { timeSlices, samplesPerSlice, spectrogram, fftSize, frequencyBins, channel } = options;\n\n const [state, setState] = useState<UseAudioFileAnalysisState>({\n data: null,\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n if (typeof window === \"undefined\") {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n\n void (async () => {\n try {\n const data = await analyzeAudioFile(fileUrl, {\n timeSlices,\n samplesPerSlice,\n spectrogram,\n fftSize,\n frequencyBins,\n channel,\n });\n if (!cancelled) {\n setState({ data, isLoading: false, error: null });\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to analyze audio file\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [fileUrl, timeSlices, samplesPerSlice, spectrogram, fftSize, frequencyBins, channel]);\n\n return state;\n}\n"],"names":["getAudioContextConstructor","useAudioPeaks","fileUrl","buckets","state","setState","useState","useEffect","cancelled","prev","response","buffer","Context","audioContext","channel","step","peaks","i","max","start","end","j","error","fftInPlace","re","im","n","tr","ti","k","len","ang","wlenR","wlenI","wr","wi","half","v","nwr","nwi","realFftMagnitudes","samples","out","hanningWindow","length","w","denom","clampFftSize","p","mixChannels","numberOfChannels","scale","c","ch","getChannel","idx","buildAmplitudeGrid","timeSlices","samplesPerSlice","grid","t","segmentLen","row","segStart","segEnd","subLen","s","a","b","peak","buildSpectrogram","fftSize","frequencyBins","rows","maxMag","bins","window","frame","mags","analyzeAudioBuffer","options","wantSpec","data","amplitudeGrid","result","norm","analyzeAudioFile","raw","useAudioFileAnalysis","spectrogram"],"mappings":"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"}
@@ -4,5 +4,6 @@ export type UseAudioFileAnalysisState = {
4
4
  isLoading: boolean;
5
5
  error: string | null;
6
6
  };
7
+ /** When extending {@link AnalyzeAudioFileOptions}, thread new fields through the destructuring below and the effect dependency array. */
7
8
  export declare function useAudioFileAnalysis(fileUrl: string | null | undefined, options?: AnalyzeAudioFileOptions): UseAudioFileAnalysisState;
8
9
  //# sourceMappingURL=useAudioFileAnalysis.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAudioFileAnalysis.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioFileAnalysis.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EAEvB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,OAAO,GAAE,uBAA4B,GACpC,yBAAyB,CAmD3B"}
1
+ {"version":3,"file":"useAudioFileAnalysis.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioFileAnalysis.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EAEvB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,yIAAyI;AACzI,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,OAAO,GAAE,uBAA4B,GACpC,yBAAyB,CAoD3B"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAudioPeaks.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioPeaks.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,OAAO,SAAK,GACX,kBAAkB,CA0DpB"}
1
+ {"version":3,"file":"useAudioPeaks.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioPeaks.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,OAAO,SAAK,GACX,kBAAkB,CAkEpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lucaismyname/ginger",
3
- "version": "0.0.32",
3
+ "version": "0.0.34",
4
4
  "description": "A headless & batteries-included React audio-player primitive",
5
5
  "type": "module",
6
6
  "sideEffects": false,