//#region src/gui/timeline/tracks/waveformUtils.ts
/** Samples per second for waveform data - balances resolution vs. data size */
const WAVEFORM_SAMPLES_PER_SECOND = 100;
/** Simple cache for waveform data keyed by audio URL */
const waveformCache = /* @__PURE__ */ new Map();
/**
* Extract waveform peak data from a media element.
* Fetches audio through the media engine's transcoding pipeline,
* then decodes with Web Audio API.
* Results are cached by src URL.
*/
async function extractWaveformData(element, signal) {
	const src = element.src;
	if (!src) return null;
	const cached = waveformCache.get(src);
	if (cached) return cached;
	try {
		const mediaEngine = await element.getMediaEngine(signal);
		signal?.throwIfAborted();
		if (!mediaEngine?.tracks.audio) return null;
		const durationMs = mediaEngine.durationMs;
		if (!durationMs || durationMs <= 0) return null;
		const abortSignal = signal ?? new AbortController().signal;
		const audioSpan = await element.fetchAudioSpanningTime(0, durationMs, abortSignal);
		signal?.throwIfAborted();
		if (!audioSpan) return null;
		const arrayBuffer = await audioSpan.blob.arrayBuffer();
		signal?.throwIfAborted();
		const audioContext = new OfflineAudioContext(1, 1, 44100);
		let audioBuffer;
		try {
			audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
		} catch (decodeError) {
			console.warn("Failed to decode audio for waveform:", decodeError);
			return null;
		}
		signal?.throwIfAborted();
		const waveformData = {
			peaks: extractPeaksFromBuffer(audioBuffer, WAVEFORM_SAMPLES_PER_SECOND),
			durationMs: audioBuffer.duration * 1e3,
			samplesPerSecond: WAVEFORM_SAMPLES_PER_SECOND
		};
		waveformCache.set(src, waveformData);
		return waveformData;
	} catch (error) {
		if (error instanceof DOMException && error.name === "AbortError") throw error;
		console.warn("Error extracting waveform data:", error);
		return null;
	}
}
/**
* Extract min/max peaks from an AudioBuffer.
* Returns Float32Array with alternating [min, max, min, max, ...] values.
*/
function extractPeaksFromBuffer(buffer, samplesPerSecond) {
	const channelData = buffer.getChannelData(0);
	const sampleRate = buffer.sampleRate;
	const duration = buffer.duration;
	const outputSamples = Math.ceil(duration * samplesPerSecond);
	const peaks = new Float32Array(outputSamples * 2);
	const samplesPerWindow = Math.floor(sampleRate / samplesPerSecond);
	for (let i = 0; i < outputSamples; i++) {
		const startSample = i * samplesPerWindow;
		const endSample = Math.min(startSample + samplesPerWindow, channelData.length);
		let min = 0;
		let max = 0;
		for (let j = startSample; j < endSample; j++) {
			const sample = channelData[j] ?? 0;
			if (sample < min) min = sample;
			if (sample > max) max = sample;
		}
		peaks[i * 2] = min;
		peaks[i * 2 + 1] = max;
	}
	return peaks;
}

//#endregion
export { extractWaveformData };
//# sourceMappingURL=waveformUtils.js.map