melhorando a leitura de projetos no mmpCreator
Deploy / Deploy (push) Successful in 2m12s
Details
Deploy / Deploy (push) Successful in 2m12s
Details
This commit is contained in:
parent
c384a4a92f
commit
3727ac7b13
|
|
@ -1059,58 +1059,13 @@ tracks:
|
|||
plugin_name: audiofileprocessor
|
||||
usemasterpitch: '1'
|
||||
vol: '100'
|
||||
playlist_clips:
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 0
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 768
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 1536
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 2304
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 3072
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 3840
|
||||
tags: audiofileprocessor
|
||||
track_name: Caixa
|
||||
type: bassline
|
||||
- bassline_name: Kick
|
||||
instruments: []
|
||||
playlist_clips:
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 0
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 768
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 1536
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 2304
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 3072
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 3840
|
||||
tags: ''
|
||||
track_name: Kick
|
||||
type: bassline
|
||||
- bassline_name: Batida/Linha de Baixo 2
|
||||
instruments: []
|
||||
playlist_clips:
|
||||
- len: 4608
|
||||
name: Batida/Linha de Baixo 2
|
||||
pos: 0
|
||||
tags: ''
|
||||
track_name: Batida/Linha de Baixo 2
|
||||
type: bassline
|
||||
|
|
|
|||
|
|
@ -514151,60 +514151,15 @@
|
|||
plugin_name: audiofileprocessor
|
||||
usemasterpitch: '1'
|
||||
vol: '100'
|
||||
playlist_clips:
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 0
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 768
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 1536
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 2304
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 3072
|
||||
- len: 768
|
||||
name: Caixa
|
||||
pos: 3840
|
||||
tags: audiofileprocessor
|
||||
track_name: Caixa
|
||||
type: bassline
|
||||
- bassline_name: Kick
|
||||
instruments: []
|
||||
playlist_clips:
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 0
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 768
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 1536
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 2304
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 3072
|
||||
- len: 768
|
||||
name: Kick
|
||||
pos: 3840
|
||||
tags: ''
|
||||
track_name: Kick
|
||||
type: bassline
|
||||
- bassline_name: Batida/Linha de Baixo 2
|
||||
instruments: []
|
||||
playlist_clips:
|
||||
- len: 4608
|
||||
name: Batida/Linha de Baixo 2
|
||||
pos: 0
|
||||
tags: ''
|
||||
track_name: Batida/Linha de Baixo 2
|
||||
type: bassline
|
||||
- bpm: '150'
|
||||
file: hybrid-trap-vespertine-fck-you
|
||||
|
|
|
|||
BIN
_data/users.db
BIN
_data/users.db
Binary file not shown.
|
|
@ -45,6 +45,13 @@ function resolveSamplePath(sampleName, pathMap) {
|
|||
return null;
|
||||
}
|
||||
|
||||
// helper: LMMS ticks -> seconds (1 beat = 192 ticks)
|
||||
function ticksToSeconds(ticks, bpm) {
|
||||
const t = Number(ticks || 0);
|
||||
const b = Number(bpm || 120);
|
||||
return (t * 60) / (b * 192);
|
||||
}
|
||||
|
||||
export async function parseBeatIndexJson(data) {
|
||||
resetProjectState();
|
||||
initializeAudioContext();
|
||||
|
|
@ -88,64 +95,48 @@ export async function parseBeatIndexJson(data) {
|
|||
appState.pattern.tracks = newPatternTracks;
|
||||
|
||||
// 2) cria lanes/clips de áudio a partir dos sample-tracks
|
||||
const sampleTracks = (data.tracks || []).filter((t) => t.type === "sample");
|
||||
const sampleTracks = (project?.tracks || []).filter((t) => t?.type === "sample");
|
||||
|
||||
for (const st of sampleTracks) {
|
||||
const laneId = st.id || safeId("audioTrack");
|
||||
const laneName = st.track_name || "Áudio";
|
||||
for (let i = 0; i < sampleTracks.length; i++) {
|
||||
const t = sampleTracks[i];
|
||||
|
||||
// lane (pista)
|
||||
addAudioTrackLane({
|
||||
id: laneId,
|
||||
name: laneName,
|
||||
volume: Number(st.sample_info?.vol ?? 100) / 100,
|
||||
pan: Number(st.sample_info?.pan ?? 0) / 100,
|
||||
// 1) cria lane de áudio
|
||||
const trackId = `sample_lane_${Date.now()}_${i}`;
|
||||
appState.audio.tracks.push({
|
||||
id: trackId,
|
||||
name: t.track_name || "Áudio",
|
||||
});
|
||||
|
||||
// arquivo
|
||||
const sampleName =
|
||||
st.sample_name ||
|
||||
basename(st.sample_info?.src) || // só pra extrair "#2.wav"
|
||||
null;
|
||||
// 2) resolve URL do arquivo
|
||||
const fileName = t.sample_name || basename(t.sample_info?.src) || `${sample_info.src}.wav`;
|
||||
|
||||
const filePath = resolveSamplePath(sampleName, pathMap);
|
||||
if (!filePath) continue;
|
||||
// tenta achar pelo filename no manifest do browser
|
||||
// (se o seu manifest tiver duplicados com mesmo nome, aqui pode colidir)
|
||||
const resolvedUrl =
|
||||
pathMap[fileName] ||
|
||||
// fallback bem simples (ajuste pro seu servidor)
|
||||
`/src_mmpSearch/samples/samples/${project?.file || project?.original_title || ""}/${fileName}`;
|
||||
|
||||
// seus dados podem vir num único sample_info, OU você pode evoluir pra playlist_clips também
|
||||
const clipDefs =
|
||||
Array.isArray(st.playlist_clips) && st.playlist_clips.length
|
||||
? st.playlist_clips
|
||||
: [
|
||||
{
|
||||
pos: Number(st.sample_info?.pos ?? 0),
|
||||
len: Number(st.sample_info?.len ?? 0),
|
||||
name: sampleName,
|
||||
},
|
||||
];
|
||||
// 3) converte pos/len (ticks) -> seconds
|
||||
const startSec = ticksToSeconds(t.sample_info?.pos, bpm);
|
||||
const durSec = ticksToSeconds(t.sample_info?.len, bpm);
|
||||
|
||||
for (const c of clipDefs) {
|
||||
const startTimeInSeconds = (Number(c.pos || 0) / TICKS_PER_STEP) * secondsPerStep;
|
||||
const durationInSeconds = (Number(c.len || 0) / TICKS_PER_STEP) * secondsPerStep;
|
||||
// 4) cria clip
|
||||
const clipId = `clip_${trackId}_0`;
|
||||
addAudioClipToTimeline(resolvedUrl, trackId, startSec, clipId, fileName);
|
||||
|
||||
const clipId = safeId("clip");
|
||||
// 5) aplica propriedades (duração/vol/pan) pra largura não ficar 0
|
||||
const vol = Number(t.sample_info?.vol ?? 100) / 100;
|
||||
const pan = Number(t.sample_info?.pan ?? 0) / 100;
|
||||
const muted = String(t.sample_info?.muted ?? "0") === "1";
|
||||
|
||||
// isso decodifica e já deixa pronto pra desenhar waveform (clip.buffer) :contentReference[oaicite:7]{index=7}
|
||||
await addAudioClipToTimeline(filePath, laneId, startTimeInSeconds, clipId, c.name || sampleName);
|
||||
|
||||
// garante que o “tamanho na playlist” respeita seu len do beat-index
|
||||
if (durationInSeconds > 0) {
|
||||
updateAudioClipProperties(clipId, { durationInSeconds, offset: 0, pitch: 0 });
|
||||
}
|
||||
}
|
||||
updateAudioClipProperties(clipId, {
|
||||
durationInSeconds: durSec || 0,
|
||||
volume: muted ? 0 : vol,
|
||||
pan: isNaN(pan) ? 0 : pan,
|
||||
});
|
||||
}
|
||||
|
||||
// escolha de track ativa no pattern editor
|
||||
const firstInst = newPatternTracks.find((t) => t.type !== "bassline");
|
||||
appState.pattern.activeTrackId = firstInst ? firstInst.id : null;
|
||||
appState.pattern.activePatternIndex = 0;
|
||||
|
||||
// mantém seu comportamento atual
|
||||
await loadStateFromSession(); // se existir snapshot local, aplica
|
||||
renderAll();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue