6.3 KiB
6.3 KiB
Visão Geral do Código
Este é o código de um sequenciador de música para a web, similar a um "DAW" (Digital Audio Workstation) simplificado, focado em criar batidas e melodias. Ele permite carregar e salvar projetos no formato .mmp (LMMS), manipular trilhas de instrumentos, programar notas em um sequenciador e controlar aspectos como volume e pan.
main.js - O Ponto de Partida
Este arquivo inicializa a aplicação. Ele conecta os botões da interface (como "Play", "Salvar", "Adicionar Trilha") às suas funções correspondentes, que estão em outros arquivos. Pense nele como o cérebro que delega as tarefas.
Função Principal
- Configura todos os "ouvintes de eventos" (event listeners).
Exemplo: Quando o usuário clica no botão com o ID play-btn, a função togglePlayback do arquivo audio.js é chamada para iniciar ou parar a música.
// Exemplo de como um botão é conectado a uma função
playBtn.addEventListener("click", togglePlayback);
addInstrumentBtn.addEventListener("click", addTrackToState);
saveMmpBtn.addEventListener("click", generateMmpFile);
state.js - O Coração da Aplicação
Aqui fica guardado todo o estado atual do projeto. Isso inclui as trilhas, as notas, o volume de cada instrumento, se a música está tocando ou não, etc. Quando algo muda (por exemplo, o usuário adiciona uma nota), este estado é atualizado, e a interface visual reflete essa mudança.
Função Principal
- Manter um objeto central (appState) com todas as informações do projeto.
Exemplo: O objeto appState contém uma lista (tracks) onde cada item representa um instrumento com seus padrões de notas, volume e nome do sample.
export let appState = {
tracks: [], // Lista de instrumentos
isPlaying: false, // A música está tocando?
currentStep: 0, // Qual passo da batida está sendo tocado
masterVolume: 0.8, // Volume geral
};
ui.js - A Interface Gráfica
Este arquivo é responsável por desenhar tudo o que o usuário vê e com o que interage na tela: as trilhas, os "knobs" de volume, a grade do sequenciador e o navegador de arquivos de áudio. Ele lê os dados do state.js para saber o que mostrar.
Função Principal
- Gerar e atualizar os elementos HTML da página.
Exemplo: A função renderApp cria uma "div" para cada trilha existente no appState, e redrawSequencer desenha os quadradinhos de notas, colorindo os que estão ativos.
// Exemplo da lógica para desenhar os passos da batida
for (let i = 0; i < totalGridSteps; i++) {
const stepElement = document.createElement("div");
// Se a nota 'i' estiver marcada como ativa no estado, adiciona a classe 'active'
if (patternSteps[i] === true) {
stepElement.classList.add("active");
}
sequencerContainer.appendChild(stepElement);
}
audio.js - O Módulo de Som
Este é o motor de áudio. Ele usa a API de Áudio do navegador para carregar os samples (os sons dos instrumentos), controlar a reprodução, gerenciar o tempo (BPM), tocar o metrônomo e garantir que as notas toquem na hora certa.
Função Principal
- Controlar a reprodução de áudio e o tempo da música.
Exemplo: A função tick é chamada repetidamente em um intervalo de tempo preciso (calculado a partir do BPM). A cada chamada, ela verifica quais notas devem ser tocadas no passo atual e dispara os sons correspondentes.
function tick() {
// Para cada trilha...
appState.tracks.forEach((track) => {
// Se a nota no passo atual estiver ativa...
if (activePattern.steps[appState.currentStep]) {
// Toca o som daquela trilha
playSample(track.samplePath, track.id);
}
});
// Avança para o próximo passo
appState.currentStep = (appState.currentStep + 1) % totalSteps;
}
file.js - O Gerenciador de Arquivos
Responsável por ler, interpretar e salvar arquivos de projeto. Ele sabe como decodificar o formato .mmp (baseado em XML) e traduzi-lo para a estrutura de dados que a aplicação entende (appState). Também faz o caminho inverso, convertendo o estado atual do projeto em um arquivo .mmp que pode ser salvo.
Função Principal
- Ler e escrever projetos no formato .mmp.
Exemplo: Ao carregar um arquivo, a função parseMmpContent usa o DOMParser do navegador para ler o XML, extrair informações como BPM e as notas de cada trilha, e popular o appState.
Utilitários
- config.js e utils.js
config.js
- Guarda valores constantes e configurações padrão, como o volume inicial ou o pan. Isso facilita a manutenção, mantendo números "mágicos" em um só lugar.
utils.js
- Contém pequenas funções de ajuda usadas em várias partes do código. Por exemplo, a função getTotalSteps calcula quantos "passos" a música terá com base no número de compassos e na fórmula de compasso definidos pelo usuário.
upload_server.py - O Servidor de Suporte
Este é um pequeno servidor web escrito em Python que roda nos bastidores. Sua principal tarefa é permitir o upload de novos samples de áudio. Quando um novo arquivo é enviado, ele o salva na pasta correta e, crucialmente, atualiza os arquivos de "manifesto" (.json). Esses manifestos são listas que a interface web consulta para saber quais samples e projetos estão disponíveis para serem carregados.
Função Principal
- Receber uploads de arquivos e manter os manifestos de samples e projetos atualizados.
Exemplo: Um usuário faz o upload do arquivo kick_drum.wav. O servidor salva este arquivo e automaticamente adiciona uma entrada para kick_drum.wav no arquivo samples-manifest.json. Da próxima vez que o usuário abrir o navegador de samples, o novo bumbo aparecerá na lista.
style.css - A Aparência
Este é o arquivo de estilização. Ele define todas as cores, tamanhos, fontes e o layout da aplicação. É o que dá ao sequenciador sua aparência de "software de música", com temas escuros e elementos visuais que lembram equipamentos de estúdio.
Função Principal
- Definir o estilo visual de todos os componentes.
Exemplo: O estilo para um passo ativo no sequenciador é definido aqui, fazendo-o brilhar em verde.
.step.active {
background-color: var(--accent-green);
border: 1px solid #fff;
box-shadow: 0 0 8px var(--accent-green);
}