97 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
// js/pattern_state.js
 | 
						|
import { DEFAULT_VOLUME, DEFAULT_PAN } from "../config.js";
 | 
						|
import { getAudioContext, getMainGainNode } from "../audio.js";
 | 
						|
import { renderPatternEditor } from "./pattern_ui.js"; 
 | 
						|
import { getTotalSteps } from "../utils.js";
 | 
						|
 | 
						|
const initialState = {
 | 
						|
    tracks: [],
 | 
						|
    activeTrackId: null,
 | 
						|
    activePatternIndex: 0,
 | 
						|
};
 | 
						|
 | 
						|
export let patternState = { ...initialState };
 | 
						|
 | 
						|
export function initializePatternState() {
 | 
						|
    Object.assign(patternState, initialState, { tracks: [] });
 | 
						|
}
 | 
						|
 | 
						|
// --- FUNÇÃO CORRIGIDA ---
 | 
						|
// Agora, esta função cria e pré-carrega um Tone.Player para a faixa.
 | 
						|
export async function loadAudioForTrack(track) {
 | 
						|
  if (!track.samplePath) return track;
 | 
						|
  try {
 | 
						|
    // Se já existir um player antigo, o descartamos para liberar memória.
 | 
						|
    if (track.player) {
 | 
						|
      track.player.dispose();
 | 
						|
    }
 | 
						|
    
 | 
						|
    // Cria um novo Tone.Player e o conecta à cadeia de áudio da faixa.
 | 
						|
    // O 'await' garante que o áudio seja totalmente carregado antes de prosseguirmos.
 | 
						|
    track.player = await new Tone.Player(track.samplePath).toDestination();
 | 
						|
    track.player.chain(track.gainNode, track.pannerNode, getMainGainNode());
 | 
						|
    
 | 
						|
  } catch (error) {
 | 
						|
    console.error(`Falha ao carregar áudio para a trilha ${track.name}:`, error);
 | 
						|
    track.player = null;
 | 
						|
  }
 | 
						|
  return track;
 | 
						|
}
 | 
						|
 | 
						|
export function addTrackToState() {
 | 
						|
  const mainGainNode = getMainGainNode();
 | 
						|
  const totalSteps = getTotalSteps();
 | 
						|
  const referenceTrack = patternState.tracks[0];
 | 
						|
 | 
						|
  const newTrack = {
 | 
						|
    id: Date.now(),
 | 
						|
    name: "novo instrumento",
 | 
						|
    samplePath: null,
 | 
						|
    player: null, // <-- ADICIONADO: O player começará como nulo
 | 
						|
    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: 0,
 | 
						|
    volume: DEFAULT_VOLUME,
 | 
						|
    pan: DEFAULT_PAN,
 | 
						|
    gainNode: new Tone.Gain(Tone.gainToDb(DEFAULT_VOLUME)),
 | 
						|
    pannerNode: new Tone.Panner(DEFAULT_PAN),
 | 
						|
  };
 | 
						|
 | 
						|
  newTrack.gainNode.chain(newTrack.pannerNode, mainGainNode);
 | 
						|
 | 
						|
  patternState.tracks.push(newTrack);
 | 
						|
  renderPatternEditor();
 | 
						|
}
 | 
						|
 | 
						|
export function removeLastTrackFromState() {
 | 
						|
  if (patternState.tracks.length > 0) {
 | 
						|
    const trackToRemove = patternState.tracks[patternState.tracks.length - 1];
 | 
						|
    if (trackToRemove.player) trackToRemove.player.dispose();
 | 
						|
    if (trackToRemove.pannerNode) trackToRemove.pannerNode.dispose();
 | 
						|
    if (trackToRemove.gainNode) trackToRemove.gainNode.dispose();
 | 
						|
    
 | 
						|
    patternState.tracks.pop();
 | 
						|
    renderPatternEditor();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export async function updateTrackSample(trackId, samplePath) {
 | 
						|
  const track = patternState.tracks.find((t) => t.id == trackId);
 | 
						|
  if (track) {
 | 
						|
    track.samplePath = samplePath;
 | 
						|
    track.name = samplePath.split("/").pop();
 | 
						|
    await loadAudioForTrack(track); // Carrega o novo player
 | 
						|
    renderPatternEditor();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export function toggleStepState(trackId, stepIndex) {
 | 
						|
  const track = patternState.tracks.find((t) => t.id == trackId);
 | 
						|
  if (track && track.patterns && track.patterns.length > 0) {
 | 
						|
    const activePattern = track.patterns[track.activePatternIndex];
 | 
						|
    if (activePattern && activePattern.steps.length > stepIndex) {
 | 
						|
      activePattern.steps[stepIndex] = !activePattern.steps[stepIndex];
 | 
						|
    }
 | 
						|
  }
 | 
						|
} |