patterns funcionais, alguns nomes estão ao contrário. mas o conteúdo agora está correto e fidedigno ao projeto.

This commit is contained in:
JotaChina committed 2025-10-03 18:02:36 -03:00
1 parent 1174d71518
commit 6212750429
5 files changed
+365 -214

No files matched your search

+32 -20
View File
@@ -6,10 +6,12 @@ import {
getMainGainNode,
} from "./audio.js";
import { renderApp } from "./ui.js";
import { getTotalSteps } from "./utils.js";
// O "cérebro" da aplicação
export let appState = {
tracks: [],
activeTrackId: null,
activePatternIndex: 0, // <-- VOLTOU A SER GLOBAL
isPlaying: false,
playbackIntervalId: null,
currentStep: 0,
@@ -20,19 +22,14 @@ export let appState = {
};
export async function loadAudioForTrack(track) {
if (!track.samplePath) {
console.warn("Track sem samplePath, pulando o carregamento de áudio.");
return track;
}
if (!track.samplePath) return track;
try {
const audioContext = getAudioContext();
if (!audioContext) initializeAudioContext();
const response = await fetch(track.samplePath);
if (!response.ok) throw new Error(`Erro ao buscar o sample: ${response.statusText}`);
const arrayBuffer = await response.arrayBuffer();
track.audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
console.log(`Áudio carregado para a trilha: ${track.name}`);
} catch (error) {
console.error(`Falha ao carregar áudio para a trilha ${track.name}:`, error);
track.audioBuffer = null;
@@ -44,13 +41,18 @@ export function addTrackToState() {
initializeAudioContext();
const audioContext = getAudioContext();
const mainGainNode = getMainGainNode();
const totalSteps = getTotalSteps();
const referenceTrack = appState.tracks[0];
const newTrack = {
id: Date.now(),
name: "novo instrumento",
samplePath: null,
audioBuffer: null,
steps: [],
patterns: referenceTrack
? referenceTrack.patterns.map(p => ({ name: p.name, steps: new Array(p.steps.length).fill(false), pos: p.pos }))
: [{ name: "Pattern 1", steps: new Array(totalSteps).fill(false), pos: 0 }],
// activePatternIndex foi removido daqui
volume: DEFAULT_VOLUME,
pan: DEFAULT_PAN,
gainNode: audioContext.createGain(),
@@ -62,12 +64,20 @@ export function addTrackToState() {
newTrack.pannerNode.pan.value = newTrack.pan;
appState.tracks.push(newTrack);
if (!appState.activeTrackId) {
appState.activeTrackId = newTrack.id;
}
renderApp();
}
export function removeLastTrackFromState() {
appState.tracks.pop();
renderApp();
if (appState.tracks.length > 0) {
const removedTrack = appState.tracks.pop();
if (appState.activeTrackId === removedTrack.id) {
appState.activeTrackId = appState.tracks[0]?.id || null;
}
renderApp();
}
}
export async function updateTrackSample(trackId, samplePath) {
@@ -76,41 +86,43 @@ export async function updateTrackSample(trackId, samplePath) {
track.samplePath = samplePath;
track.name = samplePath.split("/").pop();
track.audioBuffer = null;
renderApp();
await loadAudioForTrack(track);
const trackLane = document.querySelector(`.track-lane[data-track-id="${trackId}"] .track-name`);
if (trackLane) {
trackLane.textContent = track.name;
}
}
}
export function toggleStepState(trackId, stepIndex) {
const track = appState.tracks.find((t) => t.id == trackId);
if (track) {
track.steps[stepIndex] = !track.steps[stepIndex];
if (track && track.patterns && track.patterns.length > 0) {
// Usa o índice GLOBAL para saber qual pattern modificar
const activePattern = track.patterns[appState.activePatternIndex];
if (activePattern && activePattern.steps.length > stepIndex) {
activePattern.steps[stepIndex] = !activePattern.steps[stepIndex];
}
}
}
export function updateTrackVolume(trackId, volume) {
const track = appState.tracks.find((t) => t.id == trackId);
const audioContext = getAudioContext();
if (track) {
const clampedVolume = Math.max(0, Math.min(1.5, volume));
track.volume = clampedVolume;
if (track.gainNode) {
track.gainNode.gain.setValueAtTime(
clampedVolume,
audioContext.currentTime
);
track.gainNode.gain.setValueAtTime(clampedVolume, getAudioContext().currentTime);
}
}
}
export function updateTrackPan(trackId, pan) {
const track = appState.tracks.find((t) => t.id == trackId);
const audioContext = getAudioContext();
if (track) {
const clampedPan = Math.max(-1, Math.min(1, pan));
track.pan = clampedPan;
if (track.pannerNode) {
track.pannerNode.pan.setValueAtTime(clampedPan, audioContext.currentTime);
track.pannerNode.pan.setValueAtTime(clampedPan, getAudioContext().currentTime);
}
}
}