sync mode on
This commit is contained in:
1 parent
1818932244
commit
1174b328e5
415 files changed
+44294
-1182
No files matched your search
@@ -1,4 +1,6 @@
|
||||
// js/pattern_audio.js
|
||||
import * as Tone from "https://esm.sh/tone";
|
||||
|
||||
import { appState } from "../state.js";
|
||||
import { highlightStep } from "./pattern_ui.js";
|
||||
import { getTotalSteps } from "../utils.js";
|
||||
@@ -21,24 +23,39 @@ export function playMetronomeSound(isDownbeat) {
|
||||
synth.triggerAttackRelease(freq, "8n", Tone.now());
|
||||
}
|
||||
|
||||
// --- FUNÇÃO CORRIGIDA E EFICIENTE ---
|
||||
// Dispara o sample de uma track, garantindo que o player esteja roteado corretamente
|
||||
export function playSample(filePath, trackId) {
|
||||
initializeAudioContext();
|
||||
const track = trackId ? appState.pattern.tracks.find((t) => t.id == trackId) : null;
|
||||
|
||||
// Se a faixa existe e tem um player pré-carregado, apenas o dispara.
|
||||
// Se a faixa existe e tem um player pré-carregado
|
||||
if (track && track.player) {
|
||||
// Atualiza o volume/pan caso tenham sido alterados
|
||||
track.gainNode.gain.value = Tone.gainToDb(track.volume);
|
||||
track.pannerNode.pan.value = track.pan;
|
||||
|
||||
// Dispara o som imediatamente. Esta operação é instantânea.
|
||||
track.player.start(Tone.now());
|
||||
}
|
||||
// Fallback para preview de samples no navegador (sem trackId)
|
||||
if (track.player.loaded) {
|
||||
// Ajusta volume/pan sempre que tocar (robustez a alterações em tempo real)
|
||||
if (track.volumeNode) {
|
||||
track.volumeNode.volume.value =
|
||||
track.volume === 0 ? -Infinity : Tone.gainToDb(track.volume);
|
||||
}
|
||||
if (track.pannerNode) {
|
||||
track.pannerNode.pan.value = track.pan ?? 0;
|
||||
}
|
||||
|
||||
// Garante conexão: player -> volumeNode (não usar mais gainNode)
|
||||
try { track.player.disconnect(); } catch {}
|
||||
if (track.volumeNode) {
|
||||
track.player.connect(track.volumeNode);
|
||||
}
|
||||
|
||||
// Dispara imediatamente
|
||||
track.player.start(Tone.now());
|
||||
} else {
|
||||
console.warn(`Player da trilha "${track.name}" ainda não carregado — pulando este tick.`);
|
||||
}
|
||||
}
|
||||
// Fallback para preview de sample sem trackId
|
||||
else if (!trackId && filePath) {
|
||||
const previewPlayer = new Tone.Player(filePath).toDestination();
|
||||
previewPlayer.autostart = true;
|
||||
const previewPlayer = new Tone.Player(filePath).toDestination();
|
||||
previewPlayer.autostart = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +76,7 @@ function tick() {
|
||||
timerDisplay.textContent = formatTime(currentTime);
|
||||
}
|
||||
|
||||
// Metrônomo
|
||||
if (appState.global.metronomeEnabled) {
|
||||
const noteValue = parseInt(document.getElementById("compasso-b-input").value, 10) || 4;
|
||||
const stepsPerBeat = 16 / noteValue;
|
||||
@@ -67,12 +85,16 @@ function tick() {
|
||||
}
|
||||
}
|
||||
|
||||
// Percorre tracks e toca o step atual se ativo
|
||||
appState.pattern.tracks.forEach((track) => {
|
||||
if (!track.patterns || track.patterns.length === 0) return;
|
||||
|
||||
const activePattern = track.patterns[appState.pattern.activePatternIndex];
|
||||
|
||||
if (activePattern && activePattern.steps[appState.global.currentStep] && track.samplePath) {
|
||||
// IMPORTANTE: usar o pattern ativo da PRÓPRIA TRILHA
|
||||
const activePattern = track.patterns[track.activePatternIndex];
|
||||
|
||||
if (activePattern &&
|
||||
activePattern.steps[appState.global.currentStep] &&
|
||||
track.samplePath) {
|
||||
playSample(track.samplePath, track.id);
|
||||
}
|
||||
});
|
||||
@@ -84,9 +106,9 @@ function tick() {
|
||||
export function startPlayback() {
|
||||
if (appState.global.isPlaying || appState.pattern.tracks.length === 0) return;
|
||||
initializeAudioContext();
|
||||
|
||||
|
||||
if (appState.global.currentStep === 0) {
|
||||
rewindPlayback();
|
||||
rewindPlayback();
|
||||
}
|
||||
|
||||
const bpm = parseInt(document.getElementById("bpm-input").value, 10) || 120;
|
||||
@@ -96,15 +118,18 @@ export function startPlayback() {
|
||||
if (appState.global.playbackIntervalId) clearInterval(appState.global.playbackIntervalId);
|
||||
|
||||
appState.global.isPlaying = true;
|
||||
document.getElementById("play-btn").classList.remove("fa-play");
|
||||
document.getElementById("play-btn").classList.add("fa-pause");
|
||||
const playBtn = document.getElementById("play-btn");
|
||||
if (playBtn) {
|
||||
playBtn.classList.remove("fa-play");
|
||||
playBtn.classList.add("fa-pause");
|
||||
}
|
||||
|
||||
tick();
|
||||
appState.global.playbackIntervalId = setInterval(tick, stepInterval);
|
||||
}
|
||||
|
||||
export function stopPlayback() {
|
||||
if(appState.global.playbackIntervalId) {
|
||||
if (appState.global.playbackIntervalId) {
|
||||
clearInterval(appState.global.playbackIntervalId);
|
||||
}
|
||||
appState.global.playbackIntervalId = null;
|
||||
@@ -138,4 +163,4 @@ export function togglePlayback() {
|
||||
appState.global.currentStep = 0;
|
||||
startPlayback();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user