mmpSearch/assets/js/creations/audio/audio_clipboard.js

118 lines
3.8 KiB
JavaScript

// js/audio/audio_clipboard.js
import { appState } from '../state.js';
import { removeAudioClip, loadAudioForClip } from './audio_state.js';
import { renderAudioEditor } from './audio_ui.js';
import { getMainGainNode } from '../audio.js';
/**
* Copia o clipe selecionado para a área de transferência global.
*/
export function copyAudioClip() {
const clipId = appState.global.selectedClipId;
if (!clipId) return;
const clip = appState.audio.clips.find(c => c.id == clipId);
if (!clip) return;
// Remove a marca de "recortado" se houver
if (appState.global.clipboard?.cutSourceId) {
appState.global.clipboard.cutSourceId = null;
}
// Cria uma cópia limpa dos dados do clipe
const clipData = { ...clip };
// Remove referências a nós de áudio, que devem ser únicos
delete clipData.gainNode;
delete clipData.pannerNode;
delete clipData.player;
appState.global.clipboard = {
type: 'audio',
clip: clipData,
cutSourceId: null
};
console.log("Clipe copiado:", appState.global.clipboard.clip.name);
renderAudioEditor(); // Re-renderiza para remover o visual "cut"
}
/**
* Recorta o clipe selecionado para a área de transferência global.
*/
export function cutAudioClip() {
const clipId = appState.global.selectedClipId;
if (!clipId) return;
// Limpa o "cut" anterior
if (appState.global.clipboard?.cutSourceId) {
appState.global.clipboard.cutSourceId = null;
}
const clip = appState.audio.clips.find(c => c.id == clipId);
if (!clip) return;
// Cria uma cópia limpa dos dados do clipe
const clipData = { ...clip };
delete clipData.gainNode;
delete clipData.pannerNode;
delete clipData.player;
appState.global.clipboard = {
type: 'audio',
clip: clipData,
cutSourceId: clipId // Marca o ID original para exclusão
};
console.log("Clipe recortado:", appState.global.clipboard.clip.name);
renderAudioEditor(); // Re-renderiza para adicionar o visual "cut"
}
/**
* Cola o clipe da área de transferência na timeline.
* @param {number} targetTrackId - O ID da pista onde colar.
* @param {number} targetTimeInSeconds - O tempo (em segundos) onde colar.
*/
export function pasteAudioClip(targetTrackId, targetTimeInSeconds) {
const clipboard = appState.global.clipboard;
if (!clipboard || clipboard.type !== 'audio' || !clipboard.clip) {
console.warn("Área de transferência vazia ou inválida para colar áudio.");
return;
}
const clipToPaste = clipboard.clip;
// Se for um "recorte", primeiro remove o clipe original
if (clipboard.cutSourceId) {
removeAudioClip(clipboard.cutSourceId); //
clipboard.cutSourceId = null; // Limpa para que não remova de novo
}
// Cria um novo clipe a partir dos dados copiados
const newClip = {
...clipToPaste,
id: Date.now() + Math.random(), // ID novo e único
trackId: targetTrackId,
startTimeInSeconds: targetTimeInSeconds,
// Cria novos nós de áudio
gainNode: new Tone.Gain(Tone.gainToDb(clipToPaste.volume || 1.0)),
pannerNode: new Tone.Panner(clipToPaste.pan || 0),
player: null,
// O buffer será copiado/referenciado
};
newClip.gainNode.connect(newClip.pannerNode);
newClip.pannerNode.connect(getMainGainNode()); //
appState.audio.clips.push(newClip);
// Como o buffer já deve existir no clipe original,
// não precisamos de 'loadAudioForClip', mas chamamos
// para garantir (caso a fonte seja um 'sourcePath').
// A função 'loadAudioForClip' precisa ser inteligente
// para não recarregar se o buffer já existir.
loadAudioForClip(newClip).then(() => { //
renderAudioEditor();
});
}