Índice:

Detector de notas musicais: 3 etapas
Detector de notas musicais: 3 etapas

Vídeo: Detector de notas musicais: 3 etapas

Vídeo: Detector de notas musicais: 3 etapas
Vídeo: APRENDA A IDENTIFICAR DINHEIRO FALSO EM 3 PASSOS 2024, Novembro
Anonim
Image
Image

Surpreenda seus amigos e familiares com este projeto que detecta a nota tocada por um instrumento. Este projeto exibirá a frequência aproximada, bem como a nota musical tocada em um teclado eletrônico, aplicativo de piano ou qualquer outro instrumento.

Detalhes

Para este projeto, a saída analógica do detector do módulo de som é enviada para a entrada analógica A0 do Arduino Uno. O sinal analógico é amostrado e quantizado (digitalizado). Código de autocorrelação, ponderação e sintonia é usado para encontrar a frequência fundamental usando os primeiros 3 períodos. A frequência fundamental aproximada é então comparada às frequências nas oitavas 3, 4 e 5 para determinar a frequência de nota musical mais próxima. Finalmente, a nota adivinhada para a frequência mais próxima é impressa na tela.

Nota: Este instrutível se concentra apenas em como construir o projeto. Para obter mais informações sobre os detalhes e justificativas do projeto, visite este link: Mais informações

Suprimentos

  • (1) Arduino Uno (ou Genuino Uno)
  • (1) Módulo de detecção de som de alta sensibilidade do sensor de microfone DEVMO compatível
  • (1) Placa de ensaio sem solda
  • (1) Cabo USB-A para B
  • Fios de ligação
  • Fonte musical (piano, teclado ou app paino com alto-falantes)
  • (1) Computador ou laptop

Etapa 1: construir o hardware para o detector de notas musicais

Configure o detector de notas musicais
Configure o detector de notas musicais

Usando um Arduino Uno, fios de conexão, uma placa de ensaio sem solda e um Módulo de detecção de som de alta sensibilidade com sensor de microfone DEVMO (ou similar) construa o circuito mostrado nesta imagem

Etapa 2: programe o detector de notas musicais

No IDE do Arduino, adicione o código a seguir.

gistfile1.txt

/*
Nome do arquivo / esboço: MusicalNoteDetector
Versão nº: v1.0 criada em 7 de junho de 2020
Autor Original: Clyde A. Lettsome, PhD, PE, MEM
Descrição: Este código / esboço exibe a frequência aproximada, bem como a nota musical tocada em um teclado eletrônico ou aplicativo de piano. Para este projeto, a saída analógica do
O detector de módulo de som é enviado para a entrada analógica A0 do Arduino Uno. O sinal analógico é amostrado e quantizado (digitalizado). Código de autocorrelação, ponderação e ajuste é usado para
encontre a frequência fundamental usando os primeiros 3 períodos. A frequência fundamental aproximada é então comparada com as frequências nas oitavas 3, 4 e 5 de alcance para determinar o musical mais próximo
frequência de nota. Finalmente, a nota adivinhada para a frequência mais próxima é impressa na tela.
Licença: Este programa é um software livre; você pode redistribuí-lo e / ou modificá-lo sob os termos da GNU General Public License (GPL) versão 3, ou qualquer posterior
versão de sua escolha, conforme publicada pela Free Software Foundation.
Notas: Copyright (c) 2020 de C. A. Lettsome Services, LLC
Para obter mais informações, visite
*/
# define SAMPLES 128 // Max 128 para Arduino Uno.
#define SAMPLING_FREQUENCY 2048 // Fs = Baseado em Nyquist, deve ser 2 vezes a maior frequência esperada.
# define OFFSETSAMPLES 40 // usado para fins de calibração
# define TUNER -3 // Ajuste até que C3 seja 130,50
float samplingPeriod;
microssegundos longos sem sinal;
int X [AMOSTRAS]; // cria um vetor de AMOSTRAS de tamanho para manter valores reais
float autoCorr [AMOSTRAS]; // cria vetor de AMOSTRAS de tamanho para manter valores imaginários
float storedNoteFreq [12] = {130,81, 138,59, 146,83, 155,56, 164,81, 174,61, 185, 196, 207,65, 220, 233,08, 246,94};
int sumOffSet = 0;
int offSet [OFFSETSAMPLES]; // cria vetor de deslocamento
int avgOffSet; // cria vetor de deslocamento
int i, k, periodEnd, periodBegin, período, ajustador, noteLocation, octaveRange;
float maxValue, minValue;
soma longa;
limite interno = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
byte estado_máquina = 0;
int samplesPerPeriod = 0;
void setup ()
{
Serial.begin (115200); // Taxa Baud 115200 para o Monitor Serial
}
void loop ()
{
//*****************************************************************
// Seção de Calabração
//*****************************************************************
Serial.println ("Calabrando. Por favor, não toque nenhuma nota durante a calabração.");
para (i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = analogRead (0); // Lê o valor do pino analógico 0 (A0), quantiza-o e salva-o como um termo real.
//Serial.println(offSet); // use isso para ajustar o módulo de detecção de som para aproximadamente metade ou 512 quando nenhum som é reproduzido.
sumOffSet = sumOffSet + offSet ;
}
samplesPerPeriod = 0;
maxValue = 0;
//*****************************************************************
// Prepare-se para aceitar a entrada de A0
//*****************************************************************
avgOffSet = round (sumOffSet / OFFSETSAMPLES);
Serial.println ("Contagem regressiva.");
atraso (1000); // pausa por 1 segundo
Serial.println ("3");
atraso (1000); // pausa por 1 segundo
Serial.println ("2");
atraso (1000); // pausa para 1
Serial.println ("1");
atraso (1000); // pausa por 1 segundo
Serial.println ("Toque sua nota!");
atraso (250); // pausa por 1/4 de segundo para tempo de reação
//*****************************************************************
// Colete amostras de AMOSTRAS de A0 com período de amostragem de Período de amostragem
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Período em microssegundos
para (i = 0; i <AMOSTRAS; i ++)
{
microSegundos = micros (); // Retorna o número de microssegundos desde que a placa Arduino começou a executar o script atual.
X = analogRead (0); // Lê o valor do pino analógico 0 (A0), quantiza-o e salva-o como um termo real.
/ * tempo de espera restante entre as amostras, se necessário, em segundos * /
while (micros () <(microSeconds + (samplingPeriod * 1000000)))
{
// não faça nada, apenas espere
}
}
//*****************************************************************
// Função de autocorrelação
//*****************************************************************
para (i = 0; i <AMOSTRAS; i ++) // i = atraso
{
soma = 0;
for (k = 0; k <AMOSTRAS - i; k ++) // Corresponder o sinal ao sinal atrasado
{
soma = soma + (((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] é o sinal e X [k + i] é a versão atrasada
}
autoCorr = soma / AMOSTRAS;
// Máquina de estado de detecção de primeiro pico
if (state_machine == 0 && i == 0)
{
thresh = autoCorr * 0,5;
estado_máquina = 1;
}
else if (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, encontre 1 período para usar o primeiro ciclo
{
maxValue = autoCorr ;
}
else if (state_machine == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodBegin = i-1;
estado_máquina = 2;
numOfCycles = 1;
samplesPerPeriod = (periodBegin - 0);
período = samplesPerPeriod;
ajustador = TUNER + (50,04 * exp (-0,102 * samplesPerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod)) - ajustador; // f = fs / N
}
else if (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, encontre 2 períodos para o 1º e 2º ciclo
{
maxValue = autoCorr ;
}
else if (state_machine == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
estado_máquina = 3;
numOfCycles = 2;
samplesPerPeriod = (periodEnd - 0);
signalFrequency2 = ((numOfCycles * SAMPLING_FREQUENCY) / (samplesPerPeriod)) - ajustador; // f = (2 * fs) / (2 * N)
maxValue = 0;
}
else if (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, encontre 3 períodos para o 1º, 2º e 3º ciclo
{
maxValue = autoCorr ;
}
else if (state_machine == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
estado_máquina = 4;
numOfCycles = 3;
samplesPerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles * SAMPLING_FREQUENCY) / (samplesPerPeriod)) - ajustador; // f = (3 * fs) / (3 * N)
}
}
//*****************************************************************
// Análise de resultados
//*****************************************************************
if (samplesPerPeriod == 0)
{
Serial.println ("Hmm….. Não tenho certeza. Você está tentando me enganar?");
}
outro
{
// prepara a função de ponderação
total = 0;
if (signalFrequency! = 0)
{
total = 1;
}
if (signalFrequency2! = 0)
{
total = total + 2;
}
if (signalFrequency3! = 0)
{
total = total + 3;
}
// calcule a frequência usando a função de ponderação
signalFrequencyGuess = ((1 / total) * signalFrequency) + ((2 / total) * signalFrequency2) + ((3 / total) * signalFrequency3); // encontre uma frequência ponderada
Serial.print ("A nota que você tocou é aproximadamente");
Serial.print (signalFrequencyGuess); // Imprime a estimativa de frequência.
Serial.println ("Hz.");
// encontre a faixa de oitava com base na suposição
octaveRange = 3;
while (! (signalFrequencyGuess> = storedNoteFreq [0] -7 && signalFrequencyGuess <= storedNoteFreq [11] +7))
{
para (i = 0; i <12; i ++)
{
storedNoteFreq = 2 * storedNoteFreq ;
}
octaveRange ++;
}
// Encontre a nota mais próxima
minValue = 10000000;
noteLocation = 0;
para (i = 0; i <12; i ++)
{
if (minValue> abs (signalFrequencyGuess-storedNoteFreq ))
{
minValue = abs (signalFrequencyGuess-storedNoteFreq );
noteLocation = i;
}
}
// Imprima a nota
Serial.print ("Acho que você jogou");
if (noteLocation == 0)
{
Serial.print ("C");
}
else if (noteLocation == 1)
{
Serial.print ("C #");
}
else if (noteLocation == 2)
{
Serial.print ("D");
}
else if (noteLocation == 3)
{
Serial.print ("D #");
}
else if (noteLocation == 4)
{
Serial.print ("E");
}
else if (noteLocation == 5)
{
Serial.print ("F");
}
else if (noteLocation == 6)
{
Serial.print ("F #");
}
else if (noteLocation == 7)
{
Serial.print ("G");
}
else if (noteLocation == 8)
{
Serial.print ("G #");
}
else if (noteLocation == 9)
{
Serial.print ("A");
}
else if (noteLocation == 10)
{
Serial.print ("A #");
}
else if (noteLocation == 11)
{
Serial.print ("B");
}
Serial.println (octaveRange);
}
//*****************************************************************
//Pare aqui. Aperte o botão reset no Arduino para reiniciar
//*****************************************************************
enquanto (1);
}

visualizar rawgistfile1.txt hospedado com ❤ por GitHub

Etapa 3: configurar o detector de notas musicais

Conecte o Arduino Uno ao PC com o código escrito ou carregado no IDE do Arduino. Compile e envie o código para o Arduino. Coloque o circuito perto da fonte de música. Nota: No vídeo de introdução, eu uso um aplicativo instalado no tablet em conjunto com os alto-falantes do PC como minha fonte de música. Aperte o botão de reset na placa Arduino e toque uma nota na fonte da música. Após alguns segundos, o detector de notas musicais exibirá a nota tocada e sua frequência.

Recomendado: