Da música de um bit - meowbit

O artigo anterior dedicado à placa de treinamento Meowbit e às implementações Python para ela terminou com uma menção à incapacidade do CircuitPython de tocar música simultaneamente com o jogo: CircuitPython não permite que manipuladores de interrupção sejam escritos em Python e, sem isso, um atraso para redesenho de tela (cerca de 0,15 s) "trava" o som ... No entanto, o som de fundo geralmente é necessário e, para a maioria das placas suportadas (100 de 189), o CircuitPython inclui um módulo audioio



ou audiopwmio



que implementa o som de fundo de maneiras nativas da placa. Infelizmente, para Meowbit (e em geral para placas baseadas em STM32) nem um nem outro módulo está implementado; mas em um projeto de código aberto, isso pode ser corrigido. Encontre o ovo de Páscoa na foto Em primeiro lugar: por que existem dois módulos diferentes para reproduzir som com APIs completamente idênticas, e um ou outro é compatível com placas diferentes?













Esta é a aparência de ⅒ segundos de um arquivo

WAV normal (16 bits) em um editor de áudio (como o Audacity) :





O valor muda suavemente dentro da faixa de cerca de -0,2 a +0,2 "unidades convencionais". Se a tensão fornecida ao alto-falante eletrodinâmico for alterada da mesma maneira , a membrana oscilará com a mesma suavidade - de cerca de 0,2 de seu desvio máximo possível em uma direção a 0,2 desvio na outra direção. O módulo audioio



implementa exatamente essa reprodução de som - por meio do DAC, ele altera suavemente a voltagem na saída conectada ao alto-falante.



Mas no Meowbit, em vez de um alto-falante, há um tweeter piezo barato, incapaz de desviar a membrana para posições intermediárias: ele se move muito rapidamente de uma posição extrema para outra e permanece lá até a próxima transição. Pense nisso como um som com resolução de um bit por amostra:





Desta forma, é impossível transmitir a mudança no volume do som, mas é teoricamente possível transmitir todos os harmônicos presentes nele - se, em paralelo com a redução de 32768 vezes na resolução, a frequência de amostragem for aumentada na mesma. quantidade (ou seja, até centenas de megahertz). É improvável que uma membrana piezoeléctrica de tweeter possa vibrar nessa frequência; mas isso pode ser usado a seu favor - se você aprender a mudar a tensão da campainha, quando a membrana estiver na metade, você pode fazer sons de volume intermediário! Uma pesquisa de patentes confirma que as pessoas estão de fato explorando as possibilidades de usar o tweeter piezo desta forma. Não iremos fundo nesta selva, e deixaremos a taxa de amostragem WAV usual de dezenas de quilohertz. Para música em que os harmônicos fundamentais estão na região kilohertz, isso é suficiente; a fala, entretanto, torna-se um ruído quase imperceptível.Você pode comparar como a amostra de som de oito segundos que usei, tocada em uma sirene piezoelétrica de um bit, é percebida: primeiro o original, depois a versão de um bit, depois a gravação Meowbit com um microfone.





O módulo audiopwmio



implementa a reprodução de som por meio de uma saída digital usando PWM : uma gravação de áudio de um bit se transforma em uma sequência de atrasos entre comutar a

saída para o valor oposto.



Portanto, o plano geral de implementação audiopwmio



para Meowbit é o seguinte:



  1. Traduzimos a gravação de áudio transmitida pelo usuário para o formato PWM (uma lista de atrasos entre interruptores);
  2. . pulseio



    , , – – Python .


Não ficou imediatamente óbvio que havia outro aspecto da implementação para cuidar - buffer de áudio. Minha amostra de teste de 8 segundos tem 8 * 22050 * 2 ≈ 340 KB - três vezes o tamanho de toda a RAM Meowbit; portanto, ele terá que ser carregado na memória peça por peça. A implementação padrão audiocore.WaveFile



carrega o arquivo WAV em blocos de 256 bytes, o que corresponde a 128 amostras ou 5,8 ms de tempo de reprodução. Isso significa que, em média, a cada 5,8 ms audiopwmio



terá que solicitar o reabastecimento do buffer; não há saída, exceto colocar esta chamada no mesmo manipulador de interrupção do cronômetro - caso contrário, redesenhar a tela pode atrasar o preenchimento do buffer por uns bons cem milissegundos. Isso, no entanto, não resolve completamente o problema: o que acontece se ocorrer uma interrupção do cronômetro enquanto a tela está sendo redesenhada? A tela do Meowbit é conectada através do barramento SPI , o flash drive é conectado através dele, o que significa que ainda é impossível acessar o flash enquanto redesenha a tela!



O resultado é uma implementação audiopwmio



capaz de reproduzir gravações de áudio da memória (ou gerado processualmente) na mais alta qualidade possível no Meowbit; mas as gravações de áudio dos arquivos são reproduzidas apenas na ausência de chamadas simultâneas para a tela e o flash. Isso é o suficiente para a trilha sonora de jogos simples. PR com minha implementação está esperando por uma revisão por mais de uma semana, e audiopwmio



não se sabe quando Meowbit aparecerá na versão oficial do CircuitPython; mas isso não impede que alguém deseje compilar o CircuitPython para si com meu complemento.










All Articles