// js/waveform.js /** * Desenha a forma de onda de um AudioBuffer em um elemento Canvas. * Pode desenhar apenas um segmento específico do buffer. * @param {HTMLCanvasElement} canvas - O elemento canvas onde o desenho será feito. * @param {AudioBuffer} audioBuffer - O buffer de áudio decodificado da faixa. * @param {string} color - A cor da forma de onda (ex: '#2ecc71'). * @param {number} [offset=0] - O tempo em segundos de onde começar a desenhar no AudioBuffer. * @param {number} [duration] - A duração em segundos do segmento a ser desenhado. */ export function drawWaveform(canvas, audioBuffer, color, offset = 0, duration) { if (!canvas || !audioBuffer) return; const ctx = canvas.getContext('2d'); const width = canvas.width; const height = canvas.height; const channelData = audioBuffer.getChannelData(0); const sampleRate = audioBuffer.sampleRate; // Se a duração não for fornecida, usa a duração total a partir do offset const finalDuration = duration || (audioBuffer.duration - offset); // Calcula os índices de início e fim no array de dados do áudio const startIndex = Math.floor(offset * sampleRate); const endIndex = Math.floor((offset + finalDuration) * sampleRate); const totalSamplesInSegment = endIndex - startIndex; const step = Math.ceil(totalSamplesInSegment / width); const amp = height / 2; ctx.clearRect(0, 0, width, height); ctx.strokeStyle = color; ctx.lineWidth = 1; ctx.beginPath(); // Desenha a linha do meio (zero amplitude) ctx.moveTo(0, amp); ctx.lineTo(width, amp); for (let i = 0; i < width; i++) { let min = 1.0; let max = -1.0; for (let j = 0; j < step; j++) { // --- CORREÇÃO CRÍTICA AQUI --- // Calcula o índice da amostra considerando o startIndex do segmento const sampleIndex = startIndex + (i * step) + j; if (sampleIndex < channelData.length) { const datum = channelData[sampleIndex]; if (datum < min) min = datum; if (datum > max) max = datum; } } const x = i; // Ajusta o desenho para ser centrado verticalmente const y_max = (1 - max) * amp; const y_min = (1 - min) * amp; ctx.moveTo(x, y_max); ctx.lineTo(x, y_min); } ctx.stroke(); }