3 pontos por GN⁺ 2024-08-11 | 1 comentários | Compartilhar no WhatsApp
  • Sonic Pi é apresentado como um ambiente para criar música mesmo sem instrumentos ou equipamentos, permitindo escrever diretamente notas, acordes, escalas e timing com uma DSL baseada em Ruby
  • Ao aproveitar funções, arrays, condicionais, loops e escopo do Ruby, é possível combinar play, sleep, play_pattern_timed, chord e scale para construir padrões repetitivos e arpejos de forma concisa
  • Combinando in_thread, ring, flatten, o operador splat e with_fx, é possível executar vários “instrumentos” ao mesmo tempo e aplicar camadas de notas sobrepostas e ritmos diferentes
  • O ajuste de attack, decay, sustain e release do envelope ADSR se concentra menos em reproduzir um coral real e mais em acertar tempo de sustentação e separação
  • live_loop permite atualizar e repetir o código durante a reprodução, transformando o Sonic Pi em uma ferramenta para performance ao vivo e levando a ver o código como texto legível e ato criativo

Sonic Pi controlado por código

  • Sonic Pi, diferentemente de aplicações de áudio convencionais, é um sintetizador de software controlado apenas por código
  • Sua linguagem de controle própria é uma linguagem específica de domínio (DSL) que estende Ruby e mapeia conceitos de música e áudio sobre a sintaxe de Ruby
  • Os elementos básicos são compostos por valores Ruby e funções do Sonic Pi
    • Nomes de notas como :c4 são usados como símbolos correspondentes ao respectivo código MIDI
    • É possível criar acordes recebendo como argumentos a nota raiz e a estrutura do acorde, como em chord(:d3, :maj7)
    • play toca uma nota, e, junto com sleep do Ruby, controla intervalos de tempo
    • play_pattern_timed recebe uma lista de notas e intervalos de tempo, reduzindo o código de reprodução repetida
  • O objetivo do exemplo é criar por código um acompanhamento de demonstração usando apenas os recursos básicos do Sonic Pi, sem MIDI externo nem samples
  • Ao instalar o app Sonic Pi, é possível colar o código de exemplo e acompanhar; a documentação da linguagem e tutoriais também vêm incluídos

Criando padrões repetitivos com sintaxe Ruby

  • O exemplo básico altera o BPM com use_bpm 70 e usa o sintetizador pulse com use_synth :pulse, em vez da onda senoidal padrão
  • Repetindo play :c2 e sleep 0.25, é possível tocar notas em sequência; com play_pattern_timed [ :c3, :d3, :e3, :g3 ], 0.25, a mesma estrutura pode ser escrita de forma mais curta
  • Como a linguagem de controle está sobre Ruby, é possível abstrair padrões com funções e loops
    • A função arpeggiate recebe uma nota raiz e a informação opcional de modo menor, criando um padrão ascendente e descendente
    • O loop 4.times executa o mesmo padrão ao longo de várias oitavas
    • Uma condicional altera a terça quando o modo é menor, e o map do array soma intervalos à nota raiz para gerar a lista de notas
  • É possível configurar primeiro as opções padrão do sintetizador, como em use_synth_defaults amp: 0.1, ou passar opções diretamente para play ou play_pattern_timed
  • Em Ruby, os parênteses em chamadas de função são opcionais, mas em casos como play chord(:a3, maj7) pode ser necessário deixar a separação clara

Execução paralela e camadas

  • O bloco in_thread do é usado no Sonic Pi para executar código em paralelo
  • Com blocos in_thread diferentes, é possível executar dois “instrumentos” separados ao mesmo tempo
    • Uma thread pode ficar responsável pelo padrão de arpejo
    • Outra thread pode tocar uma melodia separada usando use_synth :saw, um array de melodia e um array de ritmo
  • play_pattern_timed pode receber não só uma lista de notas, mas também uma lista de intervalos de tempo
    • [1] * 2 aumenta o tamanho do array repetindo seu conteúdo, como em [1, 1]
    • Como play_pattern_timed não aceita arrays aninhados diretamente, usa-se flatten para transformá-los em um array de uma só camada
  • Para criar notas sobrepostas, como em um coral, é possível agrupar várias notas com ring(:c5, :e5)
  • flatten pode acabar juntando também a lista interna do ring; nesse caso, usa-se o operador splat * para expandir o conteúdo da lista dentro do array pai

Escopo, efeitos e composição de partes de coral

  • Com in_thread aninhados, é possível compartilhar fragmentos rítmicos do escopo externo e, ao mesmo tempo, reutilizar o mesmo nome de variável em cada thread interna
  • Ao separar partes como soprano e contralto em threads diferentes, cada bloco tem seu próprio escopo e não acessa diretamente as variáveis dos outros
  • with_fx :reverb, mix: 0.2 cria um bloco de efeito, e o fluxo do sinal começa na camada mais interna e segue para a cadeia de efeitos externa
  • mix indica o grau de mistura entre o sinal wet e o sinal dry
    • O sinal wet é o sinal com efeito aplicado
    • O sinal dry é o sinal sem efeito
  • Envolver todo o grupo em um único efeito pode ser usado de forma parecida com um bus em uma DAW, mas roteamentos mais profundos são manuais e, por causa do escopo, em geral precisam ser organizados de cima para baixo
  • É mais natural tratar o Sonic Pi como um instrumento, em vez de uma ferramenta sofisticada de produção

Ajustando a duração das notas com envelope ADSR

  • play_pattern_timed adiciona o valor de sustain, permitindo ajustar diretamente o tempo de sustentação de acordes longos e curtos
  • attack, decay, sustain e release formam o envelope ADSR, que representa como o volume muda ao longo do tempo
    • attack é o tempo para ir de 0 até o primeiro pico, correspondendo ao ataque inicial, como o momento em que uma corda de violão é pinçada ou o martelo de um piano toca a corda
    • decay é o tempo de queda a partir do primeiro pico, correspondendo ao trecho em que o som diminui gradualmente mesmo mantendo uma tecla de piano ou uma corda de violão pressionada
    • sustain é o tempo em que o som se mantém em um volume estável, como em uma corda tocada com arco ou em um vocal sustentado
    • release é o tempo desde soltar o som até ele efetivamente ficar silencioso
  • Nem todos os sons têm todos os elementos de ADSR
    • Tons de sintetizador são sons gerados, portanto não necessariamente têm build-up inicial ou reverberação
    • Em instrumentos naturais, a proporção dos elementos varia conforme a forma de tocar
  • A simulação de coral do exemplo se concentra menos em realismo e mais em fazer com que as notas sejam sustentadas pelo tempo correto e haja um pouco de separação entre os acordes
  • A função choral_rings notes, sus recebe uma lista de notas e o tempo de sustentação, toca-as juntas com ring(*notes), calcula sustain e release e então espera até o próximo evento com sleep sus

Live coding com live_loop

  • Com live_loop, é possível executar código repetidamente por tempo indeterminado
  • O Sonic Pi é uma ferramenta bastante voltada a performance ao vivo, e o código dentro de live_loop roda até o programa ser interrompido
  • Mesmo durante a reprodução, é possível alterar o conteúdo do loop; ao executar novamente o comando de início, o loop atualizado passa a valer a partir da próxima repetição
  • Os loops externos existentes com in_thread podem ser transformados no formato live_loop :some_unique_name
  • Como a cadeia de efeitos é recriada a cada volta do loop, quanto mais efeitos forem empilhados, mais barato em termos de recursos é colocá-los fora de live_loop
  • O exemplo final é composto por live_loop :harp e live_loop :choir
    • O loop :harp usa o sintetizador :square e um padrão de arpejo de duração 0.25
    • O loop :choir toca acordes de coral usando o sintetizador :saw, sleep 64, with_fx :reverb, mix: 0.75 e chamadas à função choral_rings

Ver programação como ato criativo

  • O trabalho técnico costuma ser discutido pela perspectiva da ciência da computação, mas programação também pode ser arte
  • Ela não é artística apenas quando cria resultados intencionalmente criativos, como geração de áudio ou layouts em CSS
  • Código não é só um conjunto de instruções otimizadas para a máquina, mas também texto organizado lido por outras pessoas e pelo seu eu do futuro
  • Bom código é aquele escrito para que outra pessoa, ou você mesmo daqui a seis meses, consiga entendê-lo de imediato
  • Às vezes, a qualidade artística do código se torna um fim em si mesma, e o exemplo do Sonic Pi mostra esse ponto por meio da criação musical

1 comentários

 
GN⁺ 2024-08-11
Opiniões no Hacker News
  • Se você tem interesse em live coding, Glicol(https://glicol.org) também vale a pena experimentar
    Também existe o TidalCycles, e a capacidade de Haskell e Ruby de criar DSLs é realmente digna de elogios
    O Glicol se concentra em uma sintaxe inspirada em sintetizadores, velocidade de composição e conveniência no design de som. A ideia é trazer hábitos de programação existentes, mas projetar uma DSL que não fique presa a uma linguagem específica

  • Alguns anos atrás, vi no YouTube um vídeo de alguém recriando o THX Deep Note com Sonic Pi
    No começo, a pessoa não explicava o que ia criar; fazia um único “tom” de som e o chamava de abelha. Depois de ajustar e tocar esse som de abelha aos poucos, no fim ela seguia algo como “vamos criar algumas centenas dessas abelhas e ver como soa dentro de uma colmeia”, e naquele momento o Deep Note surgia
    Eu gostei muito daquele vídeo, mas nunca mais consegui encontrá-lo. Se alguém souber o link, seria ótimo se compartilhasse

  • Acho que este é um dos casos em que Ruby brilha. Graças à metaprogramação, dá para fazer a sintaxe parecer quase inglês

    • É verdade, mas a DSL do Sonic Pi me parece um pouco mais próxima de Lisp do que de linguagem natural
    • É metaprogramação mesmo
  • Alguns anos atrás, vi Sam Aaron, ou seja, o criador do Sonic Pi, fazendo uma apresentação ao vivo com Sonic Pi
    A música continuava evoluindo cada vez que o código mudava em tempo real, e era realmente boa

    • Eu também já conheci o Sam. Por volta de 2008–2010, depois de uma palestra dele na Clojure Conj, jantamos juntos; ele já era uma pessoa muito bacana na época, e a apresentação também foi excelente
  • Se você quiser exemplos de artistas que usam Sonic Pi, conheci a DJ_Dave há algum tempo, e acho que ela é um ótimo exemplo de uma musicista talentosa e experiente usando bem essa ferramenta
    Ela também fez um AMA no Reddit há um tempo, e parece ter trabalhos no GitHub
    [1] https://www.youtube.com/watch?v=JiQHclg_648
    [2] https://www.reddit.com/r/audius/comments/19dxmy6/hey_audius_...
    [3] https://github.com/algorave-dave

  • Como desenvolvedor Ruby, isso parece muito legal. Acho que seria divertido usar para música generativa algorítmica, e eu queria transformar eventos barulhentos de um repositório git em algum tipo de música algorítmica; isso parece se encaixar bem
    Mas, do ponto de vista de um músico com vários instrumentos de teclado, se for para compor uma música, basta tocar em um teclado MIDI ou gravar um instrumento acústico e criar loops; não vejo muito motivo para programar sequências musicais em Ruby. Entendo que dá para digitar o que se quer com uma DSL em Ruby, mas é difícil dizer que a experiência de usuário seja melhor do que a de um teclado de piano
    Em outras palavras, acho que eu não usaria isso para substituir o Logic. Claro, é uma preferência pessoal
    Referência: http://listen.hatnote.com/

    • Ainda assim, em alguns aspectos, uma DSL em Ruby expressa a intenção de forma mais clara do que uma sequência MIDI
      Na prática, às vezes pensamos algo como “agora um arpejo em dó menor, agora um arpejo em fá maior”, e é bom poder compor essa intenção de forma bem explícita com funções
    • O Sonic Pi parece ser mais focado em música criada por algoritmos, especialmente live coding, do que em ser uma ferramenta geral de composição
      O ponto central parece estar em gerar por algoritmo, em vez de tocar nota por nota
      Ainda assim, usar de forma interessante uma ferramenta que você normalmente não usaria, por causa de restrições incomuns, combina bastante com os interesses do Hacker News
    • Pode servir para teóricos musicais com pouca coordenação e pouca motricidade fina
    • Como o post original também sugeria, na maioria das vezes é por causa de restrições práticas
      Tenho um teclado de que gosto e, em teoria, poderia usá-lo para esse trabalho, mas pessoalmente, por circunstâncias complicadas, todos os meus instrumentos estão guardados em um depósito há algum tempo
  • Coincidentemente, há alguns dias eu estava pensando no Sonic Pi e vi alguns vídeos online
    Eu só tinha mexido nele um pouco alguns anos atrás, e naquela época tentei tocar músicas clássicas como Old MacDonald e Hot Cross Buns

  • Se você tiver curiosidade sobre outra abordagem para programação musical, embora não seja ao vivo, vale a pena ver o scamp[0] para Python
    O criador postou no YouTube muitos vídeos do que fez com ele; um exemplo é o vídeo Fourier Elise[1]
    [0] http://scamp.marcevanstein.com/
    [1] https://www.youtube.com/watch?v=zq32bIud3OM

  • Parece que os comentários HTML não estão sendo aplicados. O editor deve ter trocado dois hífens -- por um único travessão

    • Bem observado. Na verdade, rodei busca/substituição com pressa demais e deixei passar alguns casos desses XD
  • Também recomendo minha live coder favorita de Sonic Pi, alsoknownasrox
    https://www.youtube.com/watch?v=wXIvXrBQFkE