Pergunta

Com recursos limitados, como CPUs mais lentas, tamanho do código e RAM, qual a melhor forma de detectar o tom de uma nota musical, semelhante ao que um sintonizador eletrônico ou de software faria?

Devo usar:

  • Beijar fft
  • Fftw
  • Transformação de wavelet discreta
  • autocorrelação
  • Análise de cruzamento zero
  • Filtros com espaços de oitava

outro?

Em poucas palavras, o que estou tentando fazer é reconhecer uma única nota musical, duas oitavas abaixo do Middle-C a duas oitavas acima, tocadas em qualquer instrumento (razoável). Eu gostaria de estar dentro de 20% do semitono - em outras palavras, se o usuário tocar muito plano ou muito nítido, preciso distinguir isso. No entanto, não precisarei da precisão necessária para o ajuste.

Foi útil?

Solução

Se você não precisar de tanta precisão, uma FFT pode ser suficiente. Janela O pedaço do áudio primeiro para obter picos bem definidos e, em seguida, encontre o primeiro pico significativo.

Largura do compartimento = taxa de amostragem / tamanho de FFT:

Fundamentos vai de 20 Hz a 7 KHz, então uma taxa de amostragem de 14 kHz seria suficiente. A próxima taxa de amostragem "padrão" é de 22050 Hz.

O tamanho da FFT é então determinado pela precisão que você deseja. A saída da FFT é linear em frequência, enquanto os tons musicais são logarítmicos em frequência, portanto, a pior precisão será em baixas frequências. Para 20% de um semitão a 20 Hz, você precisa de uma largura de 1,2 Hz, o que significa um comprimento de FFT de 18545. O próximo poder de dois é 215 = 32768. Isso é 1,5 segundos de dados e leva o processador do meu laptop 3 ms para calcular.

Isso não funcionará com sinais que têm um "faltando fundamental", e encontrar o pico" primeiro significativo "é um pouco difícil (já Os harmônicos geralmente são mais altos que os fundamentais), mas você pode descobrir uma maneira que se adapte à sua situação.

Espectro de autocorrelação e produto harmônico são melhores em encontrar o verdadeiro fundamental para uma onda em vez de um dos harmônicos, mas acho que eles também não lidam com inarmonicidade, e a maioria dos instrumentos como piano ou guitarra é inarmônica (os harmônicos são levemente nítidos do que deveriam ser). Realmente depende de suas circunstâncias, no entanto.

Além disso, você pode salvar ainda mais ciclos de processador computando apenas dentro de uma faixa de frequência específica de interesse, usando o Transformação Chirp-Z.

Eu escrevi Alguns métodos diferentes em Python Para fins de comparação.

Outras dicas

Se você deseja fazer reconhecimento de afinação em tempo real (e preciso em 1/100 de um semi-tom), sua única esperança real é a abordagem de cruzamento zero. E é uma esperança fraca, desculpe dizer. Cruzamento zero pode estimar o tom a partir de apenas alguns comprimentos de onda de dados, e isso pode ser feito com o poder de processamento de um smartphone, mas não é especialmente preciso, pois pequenos erros na medição dos comprimentos de onda resultam em grandes erros na frequência estimada. Dispositivos como sintetizadores de guitarra (que deduzem o tom de uma corda de guitarra com apenas alguns comprimentos de onda) funcionam quantizando as medições nas notas da escala. Isso pode funcionar para seus propósitos, mas esteja ciente de que a cruz zero funciona muito bem com formas de onda simples, mas tende a funcionar cada vez menos com sons de instrumentos mais complexos.

No meu aplicativo (um sintetizador de software que é executado em smartphones), uso gravações de notas de instrumentos únicas como matéria -prima para síntese de onda e, para produzir notas em um determinado tom, preciso conhecer o tom fundamental de uma gravação, precisa precisa Para 1/1000 de um semi-tom (eu realmente só preciso de precisão de 1/100, mas sou o TOC sobre isso). A abordagem de cruzamento zero é Muito de Muito impreciso para isso, e as abordagens baseadas em FFT são muito imprecisas ou muito lentas (ou às vezes).

A melhor abordagem que encontrei neste caso é usar a autocorrelação. Com a autocorrelação, você basicamente adivinha o tom e mede a autocorrelação da sua amostra no comprimento de onda correspondente. Digitando através da faixa de arremessos plausíveis (digamos A = 55 Hz a A = 880 Hz) por semi-tons, localizo o tom mais correlacionado e, em seguida, faço uma varredura de grão mais finamente no bairro daquele arremesso para obter um valor mais preciso.

A abordagem melhor para você depende inteiramente do que você está tentando usar.

Não estou familiarizado com todos os métodos que você menciona, mas o que você escolhe deve depender principalmente da natureza dos seus dados de entrada. Você está analisando tons puros ou sua fonte de entrada tem várias notas? O discurso é um recurso de sua entrada? Existem limitações no período de tempo em que você precisa provar a entrada? Você pode trocar alguma precisão por velocidade?

Até certo ponto, o que você escolhe também depende se você gostaria de realizar seus cálculos em Tempo ou em espaço de frequência. Convertendo um Série temporal A uma representação de frequência leva tempo, mas na minha experiência tende a dar melhores resultados.

Autocorrelação compara dois sinais no domínio do tempo. Uma implementação ingênua é simples, mas relativamente cara, de calcular, pois requer diferenciação entre pares entre todos os pontos nos sinais originais e com mudança de tempo, seguida de diferenciação para identificar pontos de virada na função de autocorrelação e, em seguida, seleção do mínimo correspondente a a frequência fundamental. Existem métodos alternativos. Por exemplo, Magnitude média diferenciação é uma forma muito barata de autocorrelação, mas a precisão sofre. Todas as técnicas de autocorrelação correm o risco de erros de oitava, pois os picos que não são os fundamentais existem na função.

Medindo Pontos de cruzamento zero é simples e direto, mas terá problemas se você tiver várias formas de onda presentes no sinal.

No espaço de frequência, técnicas baseadas em Fft pode ser eficiente o suficiente para seus propósitos. Um exemplo é a técnica do espectro do produto harmônico, que compara o espectro de potência do sinal com versões reduzidas em cada harmônico e identifica o tom multiplicando os espectros para produzir um pico claro.

Como sempre, não há substituto para testar e criar um perfil de várias técnicas, para determinar empiricamente o que funcionará melhor para o seu problema e restrições.

Uma resposta como essa só pode arranhar a superfície deste tópico. Além dos links anteriores, aqui estão algumas referências relevantes para leituras adicionais.

No meu projeto DANSTUNER, Eu peguei código de Audácia. Ele essencialmente pegou uma FFT, depois encontrou o pico de potência colocando uma curva cúbica na FFT e encontrando o pico dessa curva. Funciona muito bem, embora eu tivesse que se proteger contra o salto de Octave.

Ver Spectrum.cpp.

O cruzamento zero não funcionará porque um som típico tem harmônicos e cruzamentos zero muito mais do que a frequência base.

Algo com o qual experimentei (como um projeto lateral em casa) foi o seguinte:

  1. Experimente o som com o ADC a qualquer taxa de amostra necessária.
  2. Detecte os níveis dos picos positivos e negativos a curto prazo da forma de onda (janela deslizante ou similar). Ou seja, um detector de envelope.
  3. Faça uma onda quadrada que aumenta quando a forma de onda chegar a 90% (ou mais) do envelope positivo e ficar baixo quando a forma de onda entrar em 90% do envelope negativo. Ou seja, uma onda quadrada de rastreamento com histerese.
  4. Meça a frequência dessa onda quadrada com cálculos de contagem/tempo seguidos, usando quantas amostras precisar para obter a precisão necessária.

No entanto, descobri que, com as entradas do meu teclado eletrônico, para alguns sons de instrumentos, ele conseguiu pegar 2 × a frequência base (próxima oitava). Este foi um projeto paralelo e eu nunca consegui implementar uma solução antes de passar para outras coisas. Mas eu pensei que era promissor como sendo muito menos carga da CPU que a FFT.

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