diff --git a/assets/js/creations/pattern/pattern_audio.js b/assets/js/creations/pattern/pattern_audio.js index 03515757..46670274 100755 --- a/assets/js/creations/pattern/pattern_audio.js +++ b/assets/js/creations/pattern/pattern_audio.js @@ -591,11 +591,23 @@ export function startSongPatternPlaybackOnTransport() { if (patt.steps[hit.localStep]) { // SAMPLER if (track.type === "sampler" && track.player) { - track.player.restart = true; // baterias precisam retrigger + // Tone.Player é monofônico por padrão; sem retrigger, hits rápidos "morrem". + if ("retrigger" in track.player) track.player.retrigger = true; + try { - track.player.start(time); - } catch {} + // preferível: restart() (método) retrigga sem depender do estado atual + if (typeof track.player.restart === "function") { + track.player.restart(time); + } else { + track.player.start(time); + } + } catch (e) { + // fallback (p/ versões diferentes do Tone) + try { track.player.stop(time); } catch {} + try { track.player.start(time); } catch {} + } } + // PLUGIN (step sem piano roll) else if (track.type === "plugin" && track.instrument) { const hasNotes = patt.notes && patt.notes.length > 0; diff --git a/assets/js/creations/pattern/pattern_state.js b/assets/js/creations/pattern/pattern_state.js index 8df0c194..2f134369 100755 --- a/assets/js/creations/pattern/pattern_state.js +++ b/assets/js/creations/pattern/pattern_state.js @@ -147,7 +147,10 @@ export async function loadAudioForTrack(track) { track.instrument = null; } - const player = new Tone.Player({ url: track.samplePath, autostart: false }); + const player = new Tone.Player({ url: track.samplePath, autostart: false, retrigger: true }); + // redundância segura p/ builds diferentes do Tone: + try { player.retrigger = true; } catch {} + await player.load(track.samplePath); player.connect(track.volumeNode); diff --git a/assets/js/creations/socket.js b/assets/js/creations/socket.js index 80323bbb..60609a5e 100755 --- a/assets/js/creations/socket.js +++ b/assets/js/creations/socket.js @@ -976,6 +976,19 @@ async function handleActionBroadcast(action) { track.activePatternIndex = patternIndex; }); + try { + const maxSteps = appState.pattern.tracks + .filter(t => t.type !== "bassline") + .map(t => t.patterns?.[patternIndex]?.steps?.length || 0) + .reduce((a, b) => Math.max(a, b), 0); + + const barsEl = document.getElementById("bars-input"); + if (barsEl && maxSteps > 0) { + // assumindo 16 steps por compasso (4/4 em 1/16) + barsEl.value = Math.max(1, Math.ceil(maxSteps / 16)); + } + } catch {} + // Mostra o toast (só uma vez) if (!isFromSelf) { const who = actorOf(action);