Índice:

Detector de notas musicais do Arduino: 3 etapas
Detector de notas musicais do Arduino: 3 etapas

Vídeo: Detector de notas musicais do Arduino: 3 etapas

Vídeo: Detector de notas musicais do Arduino: 3 etapas
Vídeo: 11.- TUTORIAL ARDUINO - Notas musicales y melodias 2024, Dezembro
Anonim
Image
Image

Detectar notas musicais do sinal de áudio é difícil de fazer, especialmente no Arduino, devido à memória limitada e ao poder de processamento. Geralmente, a nota não é uma onda senoidal pura que torna a detecção difícil. Se considerarmos a transformação de frequência de vários instrumentos musicais, ela pode conter vários harmônicos com base na nota que está sendo tocada. Cada instrumento tem sua própria combinação de vários harmônicos. Neste código, tentei fazer um programa que pudesse abranger o maior número de instrumentos possível. Você pode consultar o vídeo em anexo no qual tentei testar os vários tipos de instrumentos, vários tipos de tons gerados pelo teclado e até mesmo o som do vocal são verificados. A precisão da detecção varia de instrumento para instrumento. Para alguns instrumentos (ou seja, piano) em uma faixa limitada (200-500 Hz), é preciso, enquanto alguns instrumentos tem baixa precisão (ou seja, gaita).

Este código faz uso de um código FFT desenvolvido anteriormente, denominado EasyFFT.

A demonstração do código é mostrada no vídeo acima com vários tipos de sons de instrumentos e vocais.

Suprimentos

- Arduino Nano / Uno ou superior

- Módulo de microfone para Arduino

Etapa 1: Algoritmo para detecção de notas

Conforme mencionado na etapa anterior, a detecção é difícil devido à presença de múltiplas frequências nas amostras de áudio.

O programa funciona no seguinte fluxo:

1. Aquisição de dados:

- esta seção obtém 128 amostras de dados de áudio, a separação entre duas amostras (frequência de amostragem) dependendo da frequência de interesse. Neste caso, estamos usando o espaçamento entre duas amostras para aplicar a função de janela de Hann, bem como o cálculo de amplitude / RMS. Este código também zera grosseiramente subtraindo 500 do valor de leitura analógica. Este valor pode ser alterado se necessário. Para um caso típico, esses valores funcionam bem. Além disso, algum atraso precisa ser adicionado para ter uma frequência de amostragem de cerca de 1200Hz. no caso de frequência de amostragem de 1200 Hz, o máximo de frequência de 600 Hz pode ser detectado.

para (int i = 0; i <128; i ++) {a = analogRead (Mic_pin) -500; // deslocamento aproximado de zero soma1 = soma1 + a; // para o valor médio sum2 = sum2 + a * a; // para o valor RMS a = a * (sin (i * 3,14 / 128) * sin (i * 3,14 / 128)); // janela Hann em = 4 * a; // escala de float para conversão interna delayMicroseconds (195); // com base na faixa de frequência de operação}

2. FFT:

Assim que os dados estiverem prontos, o FFT é executado usando o EasyFFT. Esta função EasyFFT é modificada para corrigir FFT para 128 amostras. O código também é modificado para reduzir o consumo de memória. A função EasyFFT original projetada para ter até 1028 amostras (com a placa compatível), enquanto precisamos apenas de 128 amostras. este código reduz o consumo de memória em cerca de 20% em comparação com a função EasyFFT original.

Uma vez que FFT é feito, o código retorna os 5 picos de frequência mais dominantes para análise posterior. Essas frequências são organizadas em ordem decrescente de amplitude.

3. Para cada pico, o código detecta possíveis notas associadas a ele. este código verifica apenas até 1200 Hz. Não é necessário ter nota igual à frequência com amplitude máxima.

Todas as frequências são mapeadas entre 0 e 255, aqui, a primeira oitava é detectada, por exemplo, 65,4 Hz a 130,8 representa uma oitava, 130,8 Hz a 261,6 Hz representa outra. Para cada oitava, as frequências são mapeadas de 0 a 255. aqui mapeando a partir de C a C '.

if (f_peaks > 1040) {f_peaks = 0;} if (f_peaks > = 65,4 && f_peaks = 130,8 && f_peaks = 261,6 && f_peaks = 523,25 && f_peaks = 1046 && f_peaks <= 2093) {f_peaks = 255 * ((f_peaks / 1046) -1);}

Os valores do array NoteV são usados para atribuir a nota às frequências detectadas.

byte Nota V [13] = {8, 23, 40, 57, 76, 96, 116, 138, 162, 187, 213, 241, 255};

4. Depois de calcular a nota para cada frequência, pode ser que existam várias frequências que sugerem a mesma nota. Para ter um código de saída preciso também considera as repetições. O código soma todos os valores de frequência com base na ordem de amplitude e repetições e atinge o pico da nota com amplitude máxima.

Etapa 2: Aplicação

Usar o código é simples, no entanto, também existem várias limitações que precisam ser mantidas em mente enquanto isso. O código pode ser copiado, pois é usado para detecção de notas. Os pontos abaixo precisam ser considerados ao usá-lo.

1. Atribuição de PIN:

Com base na atribuição do Pin em anexo, é necessário modificar. Para o meu experimento, eu o mantive no pino 7 analógico, void setup () {Serial.begin (250000); Mic_pin = A7; }

2. Sensibilidade do microfone:

A sensibilidade do microfone precisa ser modificada para que a forma de onda possa ser gerada com boa amplitude. Geralmente, o módulo de microfone vem com uma configuração de sensibilidade. a sensibilidade apropriada deve ser selecionada de modo que o sinal não seja muito pequeno e também não corte devido à amplitude mais alta.

3. Limiar de amplitude:

Este código é ativado apenas se a amplitude do sinal for alta o suficiente. esta configuração precisa ser definida manualmente pelo usuário. este valor depende da sensibilidade do microfone, bem como da aplicação.

if (soma2-soma1> 5) {

..

no código acima, sum2 dá o valor RMS enquanto sum 1 dá o valor médio. portanto, a diferença entre esses dois valores fornece a amplitude do sinal de som. no meu caso, ele funciona corretamente com um valor de amplitude em torno de 5.

4. Por padrão, este código imprimirá a nota detectada. entretanto, se você estiver planejando usar a nota para alguma outra finalidade, o número atribuído diretamente deve ser usado. por exemplo C = 0; C # = 1, D = 2, D # = 3 e assim por diante.

5. Se o instrumento tiver uma frequência mais alta, o código pode dar uma saída falsa. a frequência máxima é limitada pela frequência de amostragem. portanto, você pode brincar abaixo dos valores de atraso para obter a saída ideal. no atraso de código abaixo de 195 microssegundos. que pode ser ajustado para obter a saída ideal. Isso afetará o tempo de execução geral.

{a = analogRead (Mic_pin) -500; // mudança bruta de zero

soma1 = soma1 + a; // para o valor médio sum2 = sum2 + a * a; // para o valor RMS a = a * (sin (i * 3,14 / 128) * sin (i * 3,14 / 128)); // janela Hann em = 4 * a; // escala de float para conversão interna delayMicroseconds (195); // com base na faixa de frequência de operação}

6. este código só funcionará até a frequência de 2000Hz. eliminando o atraso entre a amostragem em torno de 3-4 kHz de frequências de amostragem pode ser obtido.

Precauções:

  • Conforme mencionado no tutorial EasyFFT, o FFT consome uma grande quantidade de memória do Arduino. Portanto, se você tem um programa que precisa armazenar alguns valores é recomendável usar uma placa com memória maior.
  • Este código pode funcionar bem para um instrumento / vocalista e ruim para outro. A detecção precisa em tempo real não é possível devido a limitações computacionais.

Etapa 3: verão

A detecção de notas é um trabalho computacionalmente intensivo, obter saída em tempo real é muito difícil, especialmente no Arduino. Este código pode fornecer cerca de 6,6 amostras / segundos (para um atraso de 195 microssegundos adicionado). este código funciona bem com o piano e alguns outros instrumentos.

Espero que este código e tutorial sejam úteis em seu projeto relacionado à música. em caso de dúvida ou sugestão fique à vontade para comentar ou enviar mensagem.

No próximo tutorial, irei modificar este código para detecção de acordes musicais. então fique ligado.

Recomendado: