corrigindo play/stop do editor de patterns
This commit is contained in:
1 parent
ba3f1befa1
commit
45ad819197
2 files changed
+189
-134
No files matched your search
@@ -21,6 +21,7 @@ export function initializePatternState() {
|
||||
try { track.player?.dispose(); } catch {}
|
||||
try { track.buffer?.dispose?.(); } catch {}
|
||||
try { track.instrument?.dispose(); } catch {}
|
||||
try { track.previewPlayer?.dispose(); } catch {}
|
||||
});
|
||||
|
||||
appState.pattern.tracks = [];
|
||||
@@ -29,7 +30,7 @@ export function initializePatternState() {
|
||||
}
|
||||
|
||||
export async function loadAudioForTrack(track) {
|
||||
// 1. Garante a criação dos nós de Volume e Pan
|
||||
// 1) Garante Volume/Pan
|
||||
try {
|
||||
if (!track.volumeNode) {
|
||||
track.volumeNode = new Tone.Volume(
|
||||
@@ -46,130 +47,157 @@ export async function loadAudioForTrack(track) {
|
||||
track.pannerNode.pan.value = track.pan ?? 0;
|
||||
}
|
||||
|
||||
try { track.instrument?.disconnect(); } catch {}
|
||||
try { track.player?.disconnect(); } catch {}
|
||||
// Desconecta o que existir
|
||||
try { track.instrument?.disconnect(); } catch {}
|
||||
try { track.player?.disconnect(); } catch {}
|
||||
try { track.previewPlayer?.disconnect(); } catch {}
|
||||
|
||||
// Reconecta cadeia base
|
||||
try { track.volumeNode.disconnect(); } catch {}
|
||||
try { track.pannerNode.disconnect(); } catch {}
|
||||
|
||||
track.volumeNode.connect(track.pannerNode);
|
||||
track.pannerNode.connect(getMainGainNode());
|
||||
|
||||
} catch (e) {
|
||||
console.error("Erro ao criar nós de áudio base:", e);
|
||||
}
|
||||
|
||||
// --- DETECÇÃO DE TIPO DE ARQUIVO ---
|
||||
// Verifica se é um formato de áudio que o navegador suporta
|
||||
const isStandardAudio = track.samplePath && /\.(wav|mp3|ogg|flac|m4a)$/i.test(track.samplePath);
|
||||
|
||||
// Se não for áudio padrão, assumimos Plugin (ou Kicker padrão)
|
||||
// 2) Detecta se é um arquivo de áudio suportado
|
||||
const isStandardAudio =
|
||||
track.samplePath && /\.(wav|mp3|ogg|flac|m4a)$/i.test(track.samplePath);
|
||||
|
||||
// 3) Se não for áudio padrão → Plugin (ou fallback)
|
||||
if (!track.samplePath || !isStandardAudio) {
|
||||
try {
|
||||
if (track.instrument) { try { track.instrument.dispose(); } catch {} }
|
||||
// limpa sampler/preview/buffer
|
||||
try { track.player?.dispose(); } catch {}
|
||||
try { track.previewPlayer?.dispose(); } catch {}
|
||||
try { track.buffer?.dispose?.(); } catch {}
|
||||
track.player = null;
|
||||
track.previewPlayer = null;
|
||||
track.buffer = null;
|
||||
|
||||
if (track.instrument) {
|
||||
try { track.instrument.dispose(); } catch {}
|
||||
track.instrument = null;
|
||||
}
|
||||
|
||||
let synth;
|
||||
// Normaliza o nome do instrumento. Se vazio, assume kicker.
|
||||
const name = (track.instrumentName || "kicker").toLowerCase();
|
||||
|
||||
const pluginData = {};
|
||||
const pluginData = {};
|
||||
|
||||
// SELETOR DE PLUGINS
|
||||
switch (name) {
|
||||
case "tripleoscillator":
|
||||
case "3osc":
|
||||
synth = new TripleOscillator(Tone.getContext(), pluginData);
|
||||
break;
|
||||
|
||||
case "kicker":
|
||||
synth = new Kicker(Tone.getContext(), pluginData);
|
||||
break;
|
||||
|
||||
case "lb302":
|
||||
synth = new Lb302(Tone.getContext(), pluginData);
|
||||
break;
|
||||
|
||||
case "nes":
|
||||
case "freeboy":
|
||||
case "papu":
|
||||
case "sid":
|
||||
synth = new Nes(Tone.getContext(), pluginData);
|
||||
break;
|
||||
synth = new TripleOscillator(Tone.getContext(), pluginData);
|
||||
break;
|
||||
|
||||
case "zynaddsubfx":
|
||||
case "watsyn":
|
||||
case "monstro":
|
||||
case "vibedstrings":
|
||||
case "kicker":
|
||||
synth = new Kicker(Tone.getContext(), pluginData);
|
||||
break;
|
||||
|
||||
case "lb302":
|
||||
synth = new Lb302(Tone.getContext(), pluginData);
|
||||
break;
|
||||
|
||||
case "nes":
|
||||
case "freeboy":
|
||||
case "papu":
|
||||
case "sid":
|
||||
synth = new Nes(Tone.getContext(), pluginData);
|
||||
break;
|
||||
|
||||
case "zynaddsubfx":
|
||||
case "watsyn":
|
||||
case "monstro":
|
||||
case "vibedstrings":
|
||||
case "supersaw":
|
||||
synth = new SuperSaw(Tone.getContext(), pluginData);
|
||||
break;
|
||||
|
||||
case "organic":
|
||||
synth = new Tone.PolySynth(Tone.Synth, {
|
||||
oscillator: { type: "sine", count: 8, spread: 20 }
|
||||
});
|
||||
break;
|
||||
synth = new SuperSaw(Tone.getContext(), pluginData);
|
||||
break;
|
||||
|
||||
case "organic":
|
||||
synth = new Tone.PolySynth(Tone.Synth, {
|
||||
oscillator: { type: "sine", count: 8, spread: 20 },
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn(`Plugin ${name} desconhecido, usando fallback (Kicker).`);
|
||||
// Fallback seguro: Kicker
|
||||
synth = new Kicker(Tone.getContext(), pluginData);
|
||||
console.warn(`Plugin ${name} desconhecido, usando fallback (Kicker).`);
|
||||
synth = new Kicker(Tone.getContext(), pluginData);
|
||||
}
|
||||
|
||||
if (synth.output) {
|
||||
synth.connect(track.volumeNode);
|
||||
} else {
|
||||
synth.connect(track.volumeNode);
|
||||
}
|
||||
// Conecta plugin na cadeia
|
||||
if (synth.output) synth.connect(track.volumeNode);
|
||||
else synth.connect(track.volumeNode);
|
||||
|
||||
track.instrument = synth;
|
||||
track.player = null;
|
||||
track.type = 'plugin';
|
||||
// Atualiza o nome se ele estava vazio
|
||||
if (!track.instrumentName) track.instrumentName = name;
|
||||
|
||||
console.log(`[Audio] Plugin carregado: ${name}`);
|
||||
track.type = "plugin";
|
||||
|
||||
if (!track.instrumentName) track.instrumentName = name;
|
||||
|
||||
console.log(`[Audio] Plugin carregado: ${name}`);
|
||||
return track;
|
||||
} catch (e) {
|
||||
console.error("Erro ao carregar plugin:", track.instrumentName, e);
|
||||
return track;
|
||||
}
|
||||
return track;
|
||||
}
|
||||
|
||||
// 3. Lógica para SAMPLERS
|
||||
// 4) SAMPLER (áudio)
|
||||
try {
|
||||
try { track.player?.dispose(); } catch {}
|
||||
track.player = null;
|
||||
try { track.buffer?.dispose?.(); } catch {}
|
||||
track.buffer = null;
|
||||
|
||||
// limpa plugin
|
||||
if (track.instrument) {
|
||||
try { track.instrument.dispose(); } catch {}
|
||||
track.instrument = null;
|
||||
try { track.instrument.dispose(); } catch {}
|
||||
track.instrument = null;
|
||||
}
|
||||
|
||||
const player = new Tone.Player({ url: track.samplePath, autostart: false, retrigger: true });
|
||||
// limpa players/buffer antigos
|
||||
try { track.player?.dispose(); } catch {}
|
||||
try { track.previewPlayer?.dispose(); } catch {}
|
||||
try { track.buffer?.dispose?.(); } catch {}
|
||||
track.player = null;
|
||||
track.previewPlayer = null;
|
||||
track.buffer = null;
|
||||
|
||||
// Player principal (Playlist/steps)
|
||||
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);
|
||||
|
||||
await player.load(track.samplePath);
|
||||
player.connect(track.volumeNode);
|
||||
|
||||
const buffer = new Tone.Buffer();
|
||||
await buffer.load(track.samplePath);
|
||||
|
||||
// ✅ reutiliza o MESMO buffer do player (sem segundo download)
|
||||
track.buffer = player.buffer;
|
||||
track.player = player;
|
||||
track.buffer = buffer;
|
||||
track.type = 'sampler';
|
||||
|
||||
// Preview player (Pattern Editor) — separado pra não brigar com a playlist
|
||||
const previewPlayer = new Tone.Player({
|
||||
autostart: false,
|
||||
retrigger: true,
|
||||
});
|
||||
try { previewPlayer.retrigger = true; } catch {}
|
||||
previewPlayer.buffer = track.buffer;
|
||||
previewPlayer.connect(track.volumeNode);
|
||||
|
||||
track.previewPlayer = previewPlayer;
|
||||
|
||||
track.type = "sampler";
|
||||
return track;
|
||||
} catch (error) {
|
||||
console.error('Erro ao carregar sample:', track.samplePath);
|
||||
console.error("Erro ao carregar sample:", track.samplePath, error);
|
||||
try { track.player?.dispose(); } catch {}
|
||||
try { track.previewPlayer?.dispose(); } catch {}
|
||||
try { track.buffer?.dispose?.(); } catch {}
|
||||
track.player = null;
|
||||
track.previewPlayer = null;
|
||||
track.buffer = null;
|
||||
return track;
|
||||
}
|
||||
return track;
|
||||
}
|
||||
|
||||
export function addTrackToState() {
|
||||
@@ -229,6 +257,7 @@ export function removeTrackById(trackId) {
|
||||
try { trackToRemove.instrument?.dispose(); } catch {}
|
||||
try { trackToRemove.pannerNode?.disconnect(); } catch {}
|
||||
try { trackToRemove.volumeNode?.disconnect(); } catch {}
|
||||
try { trackToRemove.previewPlayer?.dispose(); } catch {}
|
||||
|
||||
// Remove do array
|
||||
appState.pattern.tracks.splice(index, 1);
|
||||
@@ -248,6 +277,7 @@ export function removeLastTrackFromState() {
|
||||
const trackToRemove = appState.pattern.tracks[appState.pattern.tracks.length - 1];
|
||||
|
||||
try { trackToRemove.player?.dispose(); } catch {}
|
||||
try { trackToRemove.previewPlayer?.dispose(); } catch {}
|
||||
try { trackToRemove.buffer?.dispose?.(); } catch {}
|
||||
try { trackToRemove.instrument?.dispose(); } catch {}
|
||||
try { trackToRemove.pannerNode?.disconnect(); } catch {}
|
||||
@@ -260,6 +290,7 @@ export function removeLastTrackFromState() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function updateTrackSample(trackIndex, samplePath) {
|
||||
const track = appState.pattern.tracks[trackIndex];
|
||||
if (track) {
|
||||
|
||||
Reference in new issue
Block a user