playlist funcional. inserindo loops de uma mesma faixa de pattern
Deploy / Deploy (push) Successful in 2m5s
Details
Deploy / Deploy (push) Successful in 2m5s
Details
This commit is contained in:
parent
37c7fa006f
commit
a4b4157f7e
|
|
@ -377,6 +377,60 @@ export async function parseMmpContent(xmlString) {
|
||||||
|
|
||||||
const pathMap = getSamplePathMap();
|
const pathMap = getSamplePathMap();
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// 2.1) EXTRAÇÃO DE SAMPLETRACKS DO SONG EDITOR (track[type="2"])
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
const secondsPerStep = getSecondsPerStep(); // já é usado no JSON parser :contentReference[oaicite:3]{index=3}
|
||||||
|
const sampleTrackNodes = Array.from(
|
||||||
|
xmlDoc.querySelectorAll('song > trackcontainer > track[type="2"]')
|
||||||
|
);
|
||||||
|
|
||||||
|
sampleTrackNodes.forEach((node, idx) => {
|
||||||
|
const trackName = node.getAttribute("name") || `Áudio ${idx + 1}`;
|
||||||
|
|
||||||
|
// cria lane de áudio
|
||||||
|
const trackId = `sample_lane_${Date.now()}_${idx}`;
|
||||||
|
appState.audio.tracks.push({ id: trackId, name: trackName });
|
||||||
|
|
||||||
|
// pan/vol defaults do <sampletrack>
|
||||||
|
const st = node.querySelector("sampletrack");
|
||||||
|
const laneVol = st ? Number(st.getAttribute("vol") ?? 100) / 100 : 1;
|
||||||
|
const lanePan = st ? Number(st.getAttribute("pan") ?? 0) / 100 : 0;
|
||||||
|
|
||||||
|
// cada <sampletco> é um clip
|
||||||
|
const clips = Array.from(node.querySelectorAll(":scope > sampletco"));
|
||||||
|
clips.forEach((c, cidx) => {
|
||||||
|
const src = c.getAttribute("src") || "";
|
||||||
|
const fileName = src.split(/[\\/]/).pop(); // "#2.wav"
|
||||||
|
|
||||||
|
// resolve caminho via manifest; fallback para /samples
|
||||||
|
const resolvedUrl =
|
||||||
|
(fileName && pathMap[fileName]) ||
|
||||||
|
(fileName ? `${SAMPLE_SRC}/${fileName}` : null);
|
||||||
|
|
||||||
|
if (!resolvedUrl) return;
|
||||||
|
|
||||||
|
const posTicks = Number(c.getAttribute("pos") || 0);
|
||||||
|
const lenTicks = Number(c.getAttribute("len") || 0);
|
||||||
|
|
||||||
|
const startSec = ((posTicks / 12) * secondsPerStep);
|
||||||
|
const durSec = ((lenTicks / 12) * secondsPerStep);
|
||||||
|
|
||||||
|
const clipId = `clip_${trackId}_${cidx}`;
|
||||||
|
|
||||||
|
addAudioClipToTimeline(resolvedUrl, trackId, startSec, clipId, fileName);
|
||||||
|
|
||||||
|
const muted = String(c.getAttribute("muted") ?? "0") === "1";
|
||||||
|
|
||||||
|
updateAudioClipProperties(clipId, {
|
||||||
|
durationInSeconds: durSec || 0,
|
||||||
|
volume: muted ? 0 : laneVol,
|
||||||
|
pan: isNaN(lanePan) ? 0 : lanePan,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// 1. Identifica colunas de beat/patterns (usado para mapear steps)
|
// 1. Identifica colunas de beat/patterns (usado para mapear steps)
|
||||||
// Normalmente ficam dentro do primeiro container de Bassline
|
// Normalmente ficam dentro do primeiro container de Bassline
|
||||||
const bbTrackNodes = Array.from(xmlDoc.querySelectorAll('track[type="1"]'));
|
const bbTrackNodes = Array.from(xmlDoc.querySelectorAll('track[type="1"]'));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue