atualizações em tempo real para as patterns na playlist
Deploy / Deploy (push) Successful in 2m22s
Details
Deploy / Deploy (push) Successful in 2m22s
Details
This commit is contained in:
parent
46105a8fb2
commit
d003c2ccd6
|
|
@ -511,6 +511,39 @@ socket.on("action_broadcast", (payload) => {
|
||||||
const LMMS_BAR_TICKS = 192;
|
const LMMS_BAR_TICKS = 192;
|
||||||
const STEPS_PER_BAR = 16;
|
const STEPS_PER_BAR = 16;
|
||||||
|
|
||||||
|
// ticks por step (1/16) no LMMS: 192/16 = 12
|
||||||
|
const TICKS_PER_STEP = LMMS_BAR_TICKS / STEPS_PER_BAR;
|
||||||
|
|
||||||
|
function _syncNotesWithStepToggle(pattern, stepIndex, isActive) {
|
||||||
|
if (!pattern) return;
|
||||||
|
if (!Array.isArray(pattern.notes)) pattern.notes = [];
|
||||||
|
|
||||||
|
const pos = Math.round(stepIndex * TICKS_PER_STEP);
|
||||||
|
|
||||||
|
const samePos = (n) => Number(n?.pos) === pos;
|
||||||
|
|
||||||
|
if (isActive) {
|
||||||
|
// se já existe nota nesse step, não duplica
|
||||||
|
if (pattern.notes.some(samePos)) return;
|
||||||
|
|
||||||
|
// tenta reaproveitar "template" de nota pra manter key/vol/pan coerentes
|
||||||
|
const tpl = pattern.notes[0] || { vol: 100, len: TICKS_PER_STEP, pan: 0, key: 57 };
|
||||||
|
|
||||||
|
pattern.notes.push({
|
||||||
|
vol: tpl.vol ?? 100,
|
||||||
|
len: tpl.len ?? TICKS_PER_STEP,
|
||||||
|
pan: tpl.pan ?? 0,
|
||||||
|
key: tpl.key ?? 57,
|
||||||
|
pos,
|
||||||
|
});
|
||||||
|
|
||||||
|
pattern.notes.sort((a, b) => Number(a.pos) - Number(b.pos));
|
||||||
|
} else {
|
||||||
|
// remove todas as notas nesse step (útil inclusive pra "steps compostos")
|
||||||
|
pattern.notes = pattern.notes.filter((n) => !samePos(n));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _makeEmptyPattern(idx) {
|
function _makeEmptyPattern(idx) {
|
||||||
// tenta respeitar bars-input atual, mas nunca menos que 1 bar
|
// tenta respeitar bars-input atual, mas nunca menos que 1 bar
|
||||||
const bars = parseInt(document.getElementById("bars-input")?.value, 10) || 1;
|
const bars = parseInt(document.getElementById("bars-input")?.value, 10) || 1;
|
||||||
|
|
@ -1039,6 +1072,11 @@ async function handleActionBroadcast(action) {
|
||||||
|
|
||||||
t.patterns[pi].steps[si] = isActive;
|
t.patterns[pi].steps[si] = isActive;
|
||||||
|
|
||||||
|
_syncNotesWithStepToggle(t.patterns[pi], si, isActive);
|
||||||
|
|
||||||
|
// importante: se o Audio Editor estiver tocando, precisa re-schedulear
|
||||||
|
restartAudioEditorIfPlaying();
|
||||||
|
|
||||||
try { updateStepUI(ti, pi, si, isActive); } catch {}
|
try { updateStepUI(ti, pi, si, isActive); } catch {}
|
||||||
if (!isFromSelf) schedulePatternRerender();
|
if (!isFromSelf) schedulePatternRerender();
|
||||||
}
|
}
|
||||||
|
|
@ -1098,6 +1136,8 @@ async function handleActionBroadcast(action) {
|
||||||
// 5) Salva no sessionStorage
|
// 5) Salva no sessionStorage
|
||||||
saveStateToSession();
|
saveStateToSession();
|
||||||
|
|
||||||
|
restartAudioEditorIfPlaying();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Samples
|
// Samples
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue