Compondo música com Java! É hora do Jmusic

Bruno Rezende Novais - Oct 24 '23 - - Dev Community

É isso mesmo que você leu, se você sempre quis compor uma música ou imaginou como fazer isso com código saiba que é possível fazer isso e está a poucas linhas de distância. Hoje vou discutir um pouco e mostrar como é possível codar música usando Java.

Índice

O que é Música Computacional?

Primeiro é necessário darmos um passo atrás e falarmos sobre música computacional, para quem não conhece, de forma geral música computacional pode ser definida como música que envolve computação em qualquer estágio de seu ciclo de vida (Collins, 2009). Se aprofundarmos um pouco mais nessa definição, podemos pensar esse ramo como o estudo do uso da tecnologia computacional na música em quaisquer de seus estágios, seja na teoria ou prática.

Hoje com o avanço das inteligências artificiais a composição de música por máquinas já não é algo tão distante e geralmente não percebemos, mas já há o uso desse ramo de estudo em nosso dia a dia. Seja no Spotify que você abre, nos módulos de equalização de som que há no seu sistema operacional ou até mesmo no estúdio quando o engenheiro de som está usando compressores digitais ou efeitos de reverbs criados virtualmente. A música computacional é uma realidade.

Se ela é algo ético ou não, podemos discutir isso em outro artigo, mas hoje vamos passar a aprender um pouco mais sobre.

JMusic

Saiba que há uma infinidade de bibliotecas criadas para manipular e gerar som em diversas linguagens de programação, mas nesse artigo irei focar e mostrar que é possível criar música com Java. Para isso, vou introduzir a biblioteca JMusic, um projeto criado por Andrew Sorensen e Andrew R. Brown. Trata-se de uma lib completa e focada em composição que agrega desde exportadores de arquivo MIDI até mesmo instrumentos virtuais para você criar suas composições. Vale citar aqui também o livro escrito por Andrew R. Brown que foca exatamente na composição usando Java, vale leitura!

A documentação do JMusic está disponível aqui.

Show Me The Music

image

Vamos dar uma olhada no código e analisá-lo tal como um maestro.

Caso não esteja familiarizado com alguns termos musicais vou deixar um glossário no fim do artigo para ficar mais fácil :)


import jm.constants.ProgramChanges;
import jm.music.data.Note;
import jm.music.data.Part;
import jm.music.data.Phrase;
import jm.music.data.Score;
import jm.util.Read;
import jm.util.Write;

import static jm.constants.Durations.SEMIBREVE;
import static jm.constants.Pitches.C4;

public class Application {

    public static void main(String[] args) {

        Score score = new Score("JMDemo1 - Chromatic Scale");
        Part prt = new Part("Piano", ProgramChanges.PIANO, 0);
        Phrase phr = new Phrase("Chromatic Scale", 0.0);

        for(int i =0; i < 12; i++) {
            Note n  = new Note(C4+i,SEMIBREVE);
            phr.add(n);
        }

        prt.add(phr);

        score.add(prt);

        SimpleSineInst simpleSineInst = new SimpleSineInst(10000);

        Write.au(score, "WaveformExample.au",simpleSineInst);

        float[] audio = Read.audio("WaveformExample.au");

        Write.audio(audio,"waveform.wav");

    }
}



Enter fullscreen mode Exit fullscreen mode

3.1 Definindo a partitura


      Score score = new Score("JMDemo1 - Chromatic Scale");
      Part prt = new Part("Piano", ProgramChanges.PIANO, 0);
      Phrase phr = new Phrase("Chromatic Scale", 0.0);

Enter fullscreen mode Exit fullscreen mode

Primeiro instanciamos uma classe chamada Score (partitura) e precisaremos definir algumas partes dela como qual será o instrumento a seguir e qual canal do arquivo MIDI utilizaremos. Pense que o arquivo MIDI (Musical Instrument Digital Interface) é um arquivo que tem várias linhas ou canais.

A partir daí, já na linha seguinte criamos uma frase, que é onde conterá nossas notas e ritmos. Nesse caso, vamos fazer um exemplo mais simples e criar uma escala cromática começando a partir do minuto 0:0.


 for(int i =0; i < 12; i++) {
            Note n  = new Note(C4+i,SEMIBREVE);
            phr.add(n);
        }

Enter fullscreen mode Exit fullscreen mode

Já no laço for, inserimos dentro da nossa frase as notas, a nota por sua vez tem também a sua altura. (usaremos a nota Dó – C na cifra americana) Adotaremos o Dó e como ritmo usaremos a semibreve que é uma unidade de tempo para a música. Assim, incrementalmente passaremos de nota em nota até completarmos o laço.


 prt.add(phr);

 score.add(prt);

Enter fullscreen mode Exit fullscreen mode

Podemos pensar então que um Score (ou partitura) contém partes e as partes contém as frases que por sua vez contém as notas. Dessa forma vamos adicionando-as até que a frase fique completa.

3.2. Sintetizando nossa partitura

SimpleSineInst simpleSineInst = new SimpleSineInst(10000);

Write.au(score, "WaveformExample.au",simpleSineInst);
Enter fullscreen mode Exit fullscreen mode

Poderíamos já tocar nossa composição, porém vamos exportá-la primeiro. Para isso, vamos ter que usar um sintetizador para produzir os sons da nossa partitura, assim criaremos uma instância de SimpleSineInst (um sintetizador simples) e passaremos ele para o módulo de escrita, exportando-o inicialmente em um arquivo do tipo au.

3.3 Exportando em outros formatos


float[] audio = Read.audio("WaveformExample.au");

Write.audio(audio,"waveform.wav");

Enter fullscreen mode Exit fullscreen mode

Tendo agora nosso arquivo.aufica fácil, basta que leiamos ele e em seguida pode-se escrevê-lo como arquivo de áudio na extensão .wav por exemplo que é mais comum. Agora temos nossa composição exportada!

Ouça aqui o resultado final! Mas antes, recomendo que abaixe o volume de seu fone de ouvido para evitar problemas.

Quais as vantagens de se compor usando código?

Bom, a primeira de todas é que compomos uma música e criamos um sample(amostra) usando apenas código. Sim, não tivemos que comprar um teclado, uma guitarra ou uma interface de áudio para podermos capturar o som, bastou apenas algumas linhas do bom e velho Java. Com isso a primeira vantagem é custo, o custo para criar música assim é bem reduzido.

Ainda assim, podemos dar uma extrapolada e ir para “fora da caixa”. Podemos pensar no uso disso em diversos lugares, como por exemplo: games. Pode-se gerar proceduralmente música, pode-se fazer com que a partir de uma determinada decisão do jogador um som seja gerado ou ele mesmo gere uma partitura e no final você toque-a usando o JMusic por baixo dos panos, pode-se ler uma imagem por exemplo e convertê-la em uma sequência numérica para poder criar música a partir disso, música a partir de uma imagem!

Em termos de acessibilidade, podemos agora dar o poder para queles que não conseguem tocar por suas limitações físicas para dentro do mundo virtual, onde conseguirão produzir música usando os recursos de assistência dos computadores.

Aqui, o que limita é apenas a sua criatividade e a sua habilidade no código.

Bibliografia

COLLINS,N. Introduction to Computer Music. West Sussex, Reino Unido. 2009. p 2

Glossário

Partitura: Paritura pode ser definida como uma representação escrita de uma música onde está definido o ritmo, o tempo e as frases da música.

Frase: Também conhecida como frase musical, pode ser definido como um trecho de música coerente e autonomo em relação a um ritmo definido pela partitura.

Semibreve: Semibreve é uma das figuras rítmicas usadas na música sendo ela uma das de maior duração.

Escala cromática: A escala cromática é uma das escalas na música, escalas nada mais são que uma sequência ordenada de notas. Você pode saber mais sobre essa escala neste link.

Formato de arquivo Au: arquivos .au são tipo um tipo voltado para áudio, menos usual porém focado em conter informações os dados de áudio divido em três grandes blocos de dados.

Formato de arquivo WAV: arquivos .wav são um tipo mais comum de arquivos de áudio, geralmente usados já para músicas completas com uma maior qualidade sonora, geralmente são arquivos mais pesados em termos de espaço (megabytes)

. . . . . .