ao trocar de pattern, troca o áudio tocado. (play na variável global de pattern ativa).
Deploy / Deploy (push) Successful in 1m6s Details

This commit is contained in:
JotaChina 2025-10-04 15:12:18 -03:00
parent e415093a74
commit de55c93b74
1 changed files with 21 additions and 26 deletions

View File

@ -63,7 +63,7 @@ export function playMetronomeSound(isDownbeat) {
audioContext.currentTime + 0.05 audioContext.currentTime + 0.05
); );
oscillator.connect(gainNode); oscillator.connect(gainNode);
gainNode.connect(audioContext.destination); gainNode.connect(mainGainNode);
oscillator.start(audioContext.currentTime); oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 0.05); oscillator.stop(audioContext.currentTime + 0.05);
} }
@ -75,7 +75,6 @@ export function playSample(filePath, trackId) {
const track = trackId ? appState.tracks.find((t) => t.id == trackId) : null; const track = trackId ? appState.tracks.find((t) => t.id == trackId) : null;
if (!track || !track.audioBuffer) { if (!track || !track.audioBuffer) {
// Se não houver buffer (ex: preview do sample browser), toca como um áudio simples
const audio = new Audio(filePath); const audio = new Audio(filePath);
audio.play(); audio.play();
return; return;
@ -95,12 +94,12 @@ export function playSample(filePath, trackId) {
function tick() { function tick() {
const totalSteps = getTotalSteps(); const totalSteps = getTotalSteps();
if (totalSteps === 0) { if (totalSteps === 0 || !appState.isPlaying) {
stopPlayback(); stopPlayback();
return; return;
} }
const lastStepIndex =
appState.currentStep === 0 ? totalSteps - 1 : appState.currentStep - 1; const lastStepIndex = appState.currentStep === 0 ? totalSteps - 1 : appState.currentStep - 1;
highlightStep(lastStepIndex, false); highlightStep(lastStepIndex, false);
const bpm = parseInt(document.getElementById("bpm-input").value, 10) || 120; const bpm = parseInt(document.getElementById("bpm-input").value, 10) || 120;
@ -111,28 +110,23 @@ function tick() {
} }
if (appState.metronomeEnabled) { if (appState.metronomeEnabled) {
const noteValue = const noteValue = parseInt(document.getElementById("compasso-b-input").value, 10) || 4;
parseInt(document.getElementById("compasso-b-input").value, 10) || 4;
const stepsPerBeat = 16 / noteValue; const stepsPerBeat = 16 / noteValue;
if (appState.currentStep % stepsPerBeat === 0) { if (appState.currentStep % stepsPerBeat === 0) {
playMetronomeSound(appState.currentStep === 0); playMetronomeSound(appState.currentStep % (stepsPerBeat * 4) === 0);
} }
} }
// --- INÍCIO DA CORREÇÃO ---
appState.tracks.forEach((track) => { appState.tracks.forEach((track) => {
// 1. Verifica se a faixa tem patterns
if (!track.patterns || track.patterns.length === 0) return; if (!track.patterns || track.patterns.length === 0) return;
// 2. Pega o pattern que está ativo para esta faixa // Usa o índice GLOBAL para saber qual pattern tocar, sincronizando com a UI.
const activePattern = track.patterns[track.activePatternIndex]; const activePattern = track.patterns[appState.activePatternIndex];
// 3. Verifica se o pattern existe e se o step atual está ativo NELE
if (activePattern && activePattern.steps[appState.currentStep] && track.samplePath) { if (activePattern && activePattern.steps[appState.currentStep] && track.samplePath) {
playSample(track.samplePath, track.id); playSample(track.samplePath, track.id);
} }
}); });
// --- FIM DA CORREÇÃO ---
highlightStep(appState.currentStep, true); highlightStep(appState.currentStep, true);
appState.currentStep = (appState.currentStep + 1) % totalSteps; appState.currentStep = (appState.currentStep + 1) % totalSteps;
@ -141,6 +135,11 @@ function tick() {
export function startPlayback() { export function startPlayback() {
if (appState.isPlaying || appState.tracks.length === 0) return; if (appState.isPlaying || appState.tracks.length === 0) return;
initializeAudioContext(); initializeAudioContext();
if (appState.currentStep === 0) {
rewindPlayback();
}
const bpm = parseInt(document.getElementById("bpm-input").value, 10) || 120; const bpm = parseInt(document.getElementById("bpm-input").value, 10) || 120;
const stepInterval = (60 * 1000) / (bpm * 4); const stepInterval = (60 * 1000) / (bpm * 4);
@ -160,8 +159,9 @@ export function stopPlayback() {
} }
appState.playbackIntervalId = null; appState.playbackIntervalId = null;
appState.isPlaying = false; appState.isPlaying = false;
highlightStep(appState.currentStep - 1, false);
highlightStep(appState.currentStep, false); // Garante que o último step "playing" seja limpo document.querySelectorAll('.step.playing').forEach(s => s.classList.remove('playing'));
appState.currentStep = 0; appState.currentStep = 0;
if (timerDisplay) timerDisplay.textContent = '00:00:00'; if (timerDisplay) timerDisplay.textContent = '00:00:00';
@ -174,25 +174,20 @@ export function stopPlayback() {
} }
export function rewindPlayback() { export function rewindPlayback() {
const previousStep = appState.currentStep; const lastStep = appState.currentStep > 0 ? appState.currentStep - 1 : getTotalSteps() - 1;
appState.currentStep = 0; appState.currentStep = 0;
if (!appState.isPlaying) { if (!appState.isPlaying) {
if (timerDisplay) timerDisplay.textContent = '00:00:00'; if (timerDisplay) timerDisplay.textContent = '00:00:00';
highlightStep(previousStep - 1, false); highlightStep(lastStep, false);
highlightStep(previousStep, false);
} }
} }
export function togglePlayback() { export function togglePlayback() {
initializeAudioContext(); // Garante que o contexto de áudio foi iniciado por um gesto do usuário initializeAudioContext();
if (appState.isPlaying) { if (appState.isPlaying) {
// Pausa a reprodução, mas não reseta stopPlayback();
clearInterval(appState.playbackIntervalId);
appState.playbackIntervalId = null;
appState.isPlaying = false;
document.getElementById("play-btn").classList.remove("fa-pause");
document.getElementById("play-btn").classList.add("fa-play");
} else { } else {
appState.currentStep = 0;
startPlayback(); startPlayback();
} }
} }