samples de áudio não reiniciavam ao fim do loop
Deploy / Deploy (push) Successful in 2m2s
Details
Deploy / Deploy (push) Successful in 2m2s
Details
This commit is contained in:
parent
d23c3aee4d
commit
39fa026e92
|
|
@ -107,11 +107,10 @@ function _scheduleClip(clip, absolutePlayTime, durationSec, overrideOffsetSec) {
|
|||
|
||||
const player = new Tone.Player(toneBuf).sync().connect(gain);
|
||||
|
||||
const rate =
|
||||
clip.pitch && clip.pitch !== 0 ? Math.pow(2, clip.pitch / 12) : 1;
|
||||
const rate = clip.pitch && clip.pitch !== 0 ? Math.pow(2, clip.pitch / 12) : 1;
|
||||
player.playbackRate = rate;
|
||||
|
||||
// --- tempo no Transport (em segundos) ---
|
||||
// tempo no Transport (em segundos)
|
||||
const occurrenceInTransportSec =
|
||||
absolutePlayTime - startTime + (appState.audio.audioEditorSeekTime || 0);
|
||||
|
||||
|
|
@ -123,14 +122,11 @@ function _scheduleClip(clip, absolutePlayTime, durationSec, overrideOffsetSec) {
|
|||
const safeOffset = Math.max(0, offset);
|
||||
const safeDur = dur == null ? undefined : Math.max(0, dur);
|
||||
|
||||
// ✅ blindagem: nunca agenda no passado (especialmente após “virada” do loop)
|
||||
let transportNow =
|
||||
Tone.Transport.getSecondsAtTime
|
||||
? Tone.Transport.getSecondsAtTime(Tone.now())
|
||||
: Tone.Transport.seconds;
|
||||
// ✅ USE O POSICIONAMENTO ATUAL (já atualizado pelo seu código)
|
||||
const transportNow = Tone.Transport.seconds;
|
||||
|
||||
// pequena folga pra não “perder” o start por alguns ms
|
||||
const EPS = 0.003;
|
||||
// folga pequena pra não “perder” start
|
||||
const EPS = 0.005;
|
||||
const startAt = Math.max(safeOccurrence, transportNow + EPS);
|
||||
|
||||
player.start(startAt, safeOffset, safeDur);
|
||||
|
|
@ -147,7 +143,6 @@ function _scheduleClip(clip, absolutePlayTime, durationSec, overrideOffsetSec) {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
function _handleClipEnd(eventId, clipId) {
|
||||
scheduledNodes.delete(eventId);
|
||||
runtimeClipState.delete(clipId);
|
||||
|
|
@ -311,30 +306,14 @@ function _animationLoop() {
|
|||
|
||||
if (isLoopActive) {
|
||||
if (newLogicalTime >= loopEndTimeSec) {
|
||||
const loopDuration = loopEndTimeSec - loopStartTimeSec;
|
||||
if (loopDuration > 0) {
|
||||
newLogicalTime =
|
||||
loopStartTimeSec +
|
||||
((newLogicalTime - loopStartTimeSec) % loopDuration);
|
||||
} else {
|
||||
newLogicalTime = loopStartTimeSec;
|
||||
}
|
||||
// ✅ volta exatamente pro início do loop (sem remainder/jitter)
|
||||
newLogicalTime = loopStartTimeSec;
|
||||
|
||||
// realinha relógio interno
|
||||
// realinha relógio interno do seu scheduler
|
||||
startTime = now;
|
||||
appState.audio.audioEditorSeekTime = newLogicalTime;
|
||||
|
||||
// ✅ força o Transport “pular” junto na virada do loop
|
||||
try {
|
||||
// (desativa loop do Transport aqui pra não brigar com a sua lógica de loop da playlist)
|
||||
Tone.Transport.loop = false;
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
Tone.Transport.seconds = newLogicalTime;
|
||||
} catch {}
|
||||
|
||||
// ✅ limpa players/estado pra permitir reagendamento limpo
|
||||
// limpa players/estado pra permitir reagendamento limpo
|
||||
runtimeClipState.clear();
|
||||
scheduledNodes.forEach(({ player }) => {
|
||||
try { player.unsync(); } catch {}
|
||||
|
|
@ -343,16 +322,27 @@ function _animationLoop() {
|
|||
});
|
||||
scheduledNodes.clear();
|
||||
|
||||
// ✅ reinicia patterns do song (seu scheduler da playlist)
|
||||
// ✅ reinicia patterns e Transport de forma confiável
|
||||
try { stopSongPatternPlaybackOnTransport(); } catch {}
|
||||
|
||||
try {
|
||||
stopSongPatternPlaybackOnTransport();
|
||||
startSongPatternPlaybackOnTransport();
|
||||
const bpm = parseFloat(document.getElementById("bpm-input")?.value) || 120;
|
||||
|
||||
Tone.Transport.stop();
|
||||
Tone.Transport.bpm.value = bpm;
|
||||
|
||||
// posiciona exatamente no loopStart
|
||||
Tone.Transport.seconds = newLogicalTime;
|
||||
|
||||
Tone.Transport.start();
|
||||
} catch {}
|
||||
|
||||
// ✅ IMPORTANTÍSSIMO: recomeça clips que atravessam o loopStart
|
||||
_scheduleOverlappingClipsAtTime(newLogicalTime);
|
||||
try { startSongPatternPlaybackOnTransport(); } catch {}
|
||||
|
||||
// e já agenda os próximos inícios sem esperar o próximo interval tick
|
||||
// ✅ recomeça clips que atravessam o loopStart (mais preciso que AtTime)
|
||||
_scheduleOverlappingClipsAtLoopStart(loopStartTimeSec, loopEndTimeSec);
|
||||
|
||||
// agenda os próximos inícios sem esperar o próximo interval tick
|
||||
_schedulerTick();
|
||||
}
|
||||
}
|
||||
|
|
@ -383,8 +373,6 @@ function _animationLoop() {
|
|||
animationFrameId = requestAnimationFrame(_animationLoop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// --- API Pública ---
|
||||
|
||||
export function updateTransportLoop() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue