versão 2.0

This commit is contained in:
JotaChina committed 2025-10-20 21:53:09 -03:00
1 parent d506332268
commit fe735bf0a6
16 files changed
+1735 -1626

No files matched your search

+33 -16
View File
@@ -2,44 +2,61 @@
/**
* 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) {
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); // Pega os dados do primeiro canal
const step = Math.ceil(channelData.length / width);
const amp = height / 2; // Amplitude máxima do desenho
const channelData = audioBuffer.getChannelData(0);
const sampleRate = audioBuffer.sampleRate;
ctx.clearRect(0, 0, width, height); // Limpa o canvas
// 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 = 2;
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;
// Encontra o valor mínimo e máximo para um bloco de amostras
for (let j = 0; j < step; j++) {
const datum = channelData[(i * step) + j];
if (datum < min) {
min = datum;
}
if (datum > max) {
max = datum;
// --- 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;
}
}
// Desenha a linha vertical para aquele ponto no tempo
const x = i;
const y_max = (1 + max) * amp;
const y_min = (1 + min) * amp;
// 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);