ativar/desativar tracks de áudio, knobs funcionais
This commit is contained in:
1 parent
d3e209d8e8
commit
73a5257aec
5 files changed
+260
-28
No files matched your search
@@ -16,6 +16,82 @@ const DEFAULT_KICKER_XML = `<kicker>
|
||||
<env amt="0" attack="0.01" hold="0.1" decay="0.1" release="0.1" sustain="0.5" sync_mode="0"/>
|
||||
</kicker>`;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// MIX / MUTE HELPERS (Volume, Pan)
|
||||
// ------------------------------------------------------------
|
||||
const MAX_TRACK_VOLUME = 1.5;
|
||||
|
||||
function _clamp(n, min, max) {
|
||||
const x = Number(n);
|
||||
if (!Number.isFinite(x)) return min;
|
||||
return Math.min(max, Math.max(min, x));
|
||||
}
|
||||
|
||||
function _ensureMuteFields(track) {
|
||||
if (!track) return;
|
||||
if (track.isMuted == null) track.isMuted = !!track.muted;
|
||||
if (track.muted == null) track.muted = !!track.isMuted;
|
||||
}
|
||||
|
||||
function applyTrackMix(track) {
|
||||
if (!track) return;
|
||||
|
||||
_ensureMuteFields(track);
|
||||
|
||||
const vol = _clamp(track.volume ?? DEFAULT_VOLUME, 0, MAX_TRACK_VOLUME);
|
||||
const pan = _clamp(track.pan ?? DEFAULT_PAN, -1, 1);
|
||||
const isMuted = !!(track.isMuted || track.muted);
|
||||
|
||||
// Volume (dB): mute => -Infinity
|
||||
if (!track.volumeNode) {
|
||||
track.volumeNode = new Tone.Volume(
|
||||
isMuted || vol === 0 ? -Infinity : Tone.gainToDb(vol)
|
||||
);
|
||||
} else {
|
||||
track.volumeNode.volume.value =
|
||||
isMuted || vol === 0 ? -Infinity : Tone.gainToDb(vol);
|
||||
}
|
||||
|
||||
// Pan
|
||||
if (!track.pannerNode) {
|
||||
track.pannerNode = new Tone.Panner(pan);
|
||||
} else {
|
||||
track.pannerNode.pan.value = pan;
|
||||
}
|
||||
|
||||
// reconecta cadeia base (idempotente)
|
||||
try { track.volumeNode.disconnect(); } catch {}
|
||||
try { track.pannerNode.disconnect(); } catch {}
|
||||
track.volumeNode.connect(track.pannerNode);
|
||||
track.pannerNode.connect(getMainGainNode());
|
||||
}
|
||||
|
||||
// API pública (usada pelo UI/socket)
|
||||
export function setPatternTrackMute(trackId, isMuted) {
|
||||
const t = (appState.pattern.tracks || []).find((x) => String(x.id) === String(trackId));
|
||||
if (!t) return false;
|
||||
t.isMuted = !!isMuted;
|
||||
t.muted = !!isMuted;
|
||||
applyTrackMix(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
export function setPatternTrackVolume(trackId, volume) {
|
||||
const t = (appState.pattern.tracks || []).find((x) => String(x.id) === String(trackId));
|
||||
if (!t) return false;
|
||||
t.volume = _clamp(volume, 0, MAX_TRACK_VOLUME);
|
||||
applyTrackMix(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
export function setPatternTrackPan(trackId, pan) {
|
||||
const t = (appState.pattern.tracks || []).find((x) => String(x.id) === String(trackId));
|
||||
if (!t) return false;
|
||||
t.pan = _clamp(pan, -1, 1);
|
||||
applyTrackMix(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
export function initializePatternState() {
|
||||
appState.pattern.tracks.forEach(track => {
|
||||
try { track.player?.dispose(); } catch {}
|
||||
@@ -30,33 +106,14 @@ export function initializePatternState() {
|
||||
}
|
||||
|
||||
export async function loadAudioForTrack(track) {
|
||||
// 1) Garante Volume/Pan
|
||||
// 1) Garante Volume/Pan/Mute e reconecta a cadeia base
|
||||
try {
|
||||
if (!track.volumeNode) {
|
||||
track.volumeNode = new Tone.Volume(
|
||||
track.volume === 0 ? -Infinity : Tone.gainToDb(track.volume)
|
||||
);
|
||||
} else {
|
||||
track.volumeNode.volume.value =
|
||||
track.volume === 0 ? -Infinity : Tone.gainToDb(track.volume);
|
||||
}
|
||||
applyTrackMix(track);
|
||||
|
||||
if (!track.pannerNode) {
|
||||
track.pannerNode = new Tone.Panner(track.pan ?? 0);
|
||||
} else {
|
||||
track.pannerNode.pan.value = track.pan ?? 0;
|
||||
}
|
||||
|
||||
// Desconecta o que existir
|
||||
// desconecta o que existir (para reconectar sem duplicar rotas)
|
||||
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);
|
||||
}
|
||||
@@ -257,6 +314,8 @@ export function addTrackToState() {
|
||||
patterns,
|
||||
activePatternIndex: appState.pattern.activePatternIndex ?? 0,
|
||||
|
||||
isMuted: false,
|
||||
muted: false,
|
||||
volume: DEFAULT_VOLUME,
|
||||
pan: DEFAULT_PAN,
|
||||
volumeNode: new Tone.Volume(Tone.gainToDb(DEFAULT_VOLUME)),
|
||||
|
||||
Reference in new issue
Block a user