From a4b4157f7eddcc9e21febf82255c61efa8462eab Mon Sep 17 00:00:00 2001 From: JotaChina Date: Thu, 25 Dec 2025 17:20:28 -0300 Subject: [PATCH] playlist funcional. inserindo loops de uma mesma faixa de pattern --- assets/js/creations/file.js | 54 +++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/assets/js/creations/file.js b/assets/js/creations/file.js index 29ea2cba..b05ddfb0 100755 --- a/assets/js/creations/file.js +++ b/assets/js/creations/file.js @@ -377,6 +377,60 @@ export async function parseMmpContent(xmlString) { 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 + 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 é 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) // Normalmente ficam dentro do primeiro container de Bassline const bbTrackNodes = Array.from(xmlDoc.querySelectorAll('track[type="1"]'));