Pergunta

Estou pensando em criar um software que faça o teclado funcionar como um piano (por exemplo, o usuário pressiona a tecla 'W' e os alto-falantes tocam uma nota D).Provavelmente usarei OpenAL.Entendo os fundamentos do áudio digital, mas reproduzir áudio em tempo real em resposta ao pressionamento de teclas apresenta alguns problemas que estou tendo dificuldade para resolver.

Aqui está o problema: Digamos que eu tenha 10 buffers de áudio e cada buffer contenha um segundo de dados de áudio.Se eu tivesse que preencher os buffers antes de serem reproduzidos nos alto-falantes, estaria preenchendo os buffers um ou dois segundos antes de serem reproduzidos.Isso significa que sempre que o usuário tentar tocar uma nota, haverá um atraso de um ou dois segundos entre o pressionamento da tecla e a nota tocada.

Como você contorna esse problema?Você apenas torna os buffers tão pequenos quanto possível e os preenche o mais tarde possível?Existe algum truque que estou perdendo?

Foi útil?

Solução

A maioria dos sintetizadores de software não usa vários buffers.

Eles apenas usam um único e pequeno anel que é tocado constantemente.

Um encadeamento de alta prioridade será o mais rápido possível, verifique a posição de reprodução atual e preencha a peça gratuita (por exemplo, a parte que foi realizada desde a última vez que seu thread estava em execução) do ringbuffer com dados sonoros.

Isso lhe dará uma latência constante que está ligada apenas pelo tamanho do seu buffer de anel e pela latência de saída da sua placa de som (geralmente não tanto).

Você pode diminuir ainda mais sua latência:

No caso de uma nova nota a ser tocada (por exemplo, o usuário acabou de pressionar uma tecla), você verifica a posição atual de reprodução dentro do anel, adiciona algumas amostras para segurança e depois renderize os dados de som com o novo som- Configurações aplicadas.

Isso se torna complicado se você tiver efeitos baseados no tempo em execução (linhas de atraso, reverb e assim por diante), mas é factível. Basta acompanhar os últimos 10 estados de seus efeitos baseados no tempo a cada milissegundos. Isso tornará possível recuperar 10 milissegundos no tempo.

Outras dicas

Com o Winapi, você só pode chegar tão longe em termos de latência. Geralmente você não pode ficar abaixo de 40-50ms, o que é bastante desagradável. A solução é implementar o suporte da ASIO em seu aplicativo e fazer o usuário executar algo como asio4all em segundo plano. Isso reduz a latência para 5ms, mas a um custo: outros aplicativos não podem jogar som ao mesmo tempo.

Eu sei disso porque sou um usuário do FL Studio.

A solução são buffers pequenos, preenchidos frequentemente por um encadeamento em tempo real.O tamanho dos buffers (ou o quão cheio você deixa o buffer ficar com um buffer em anel) é limitado pela latência de agendamento do seu sistema operacional.Você provavelmente achará 10ms aceitáveis.

Existem algumas dicas desagradáveis ​​​​para os não iniciados - principalmente no que diz respeito à arquitetura de software e segurança de thread.

Você poderia tentar dar uma olhada Juce - que é uma estrutura multiplataforma para escrever software de áudio e, em particular - plug-ins de áudio, como SoftSynths e efeitos.Inclui software para plug-ins e hosts de amostra.É no host que os problemas de threading são tratados principalmente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top