Skip to content

Desenvolvimento de um afinador que se ajusta automaticamente ao instrumento musical escolhido pelo utilizador

License

Notifications You must be signed in to change notification settings

D1ogoCS/Afinador-de-Instrumentos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Afinador de Instrumentos

Afinador que se ajusta automaticamente ao instrumento musical escolhido pelo utilizador

Foi proposto realizar um projeto que englobasse uma área de Processamento Digital de Sinais e decidi criar uma aplicação, que tem como função ser um afinador que se adapta ao instrumento musical escolhido pelo utilizador.

Objetivos:

  • O utilizador deve escolher qual o instrumento musical que quer afinar
  • Ser possível visualizar um gráfico com as frequências que estão a ser capturadas em tempo real
  • Mostrar a frequência que está a ser captada
  • Indicar a nota e a oitava
  • Se o instrumento estiver desafinado, indicar com uma seta para que lado se encontra a nota mais próxima. Se o instrumento estiver afinado, deve aparecer a mensagem "Ok"
  • Utilizar um filtro que foi lecionado durante as aulas de Processamento Digital de Sinais

Ferramentas utilizadas:

  • IDLE (Python 3.10 64-bit)

Tecnologias utilizadas:

  • Linguagem Python

Requisitos técnicos:

  • Python 3.7 ou superior
  • tkinter
  • matplotlib
  • pyaudio
  • numpy
  • scipy
  • threading

Bibliotecas:

  • tkinter: É uma biblioteca gráfica que permite criar interfaces gráficas para o utilizador (GUI's) em Python. Com o tkinter, é possível criar janelas, botões, caixas de texto, menus, entre outros elementos da interface gráfica.

  • matplotlib.animation.FuncAnimation: É uma classe da biblioteca matplotlib que permite criar animações em Python. É usada para criar animações de gráficos, como gráficos de linha, de barra, de dispersão, entre outros. A classe FuncAnimation permite criar animações com base numa função que é chamada repetidamente em intervalos regulares.

  • matplotlib.pyplot: É uma função da biblioteca matplotlib que fornece uma interface para criar gráficos em Python. É usada para criar gráficos de linha, de barra, de dispersão, entre outros. A biblioteca pyplot é baseada na biblioteca MATLAB e é muito útil para visualizar dados em Python.

  • pyaudio: É uma biblioteca que fornece uma interface para trabalhar com áudio em Python. É usada para gravar e reproduzir áudio em tempo real. A biblioteca pyaudio é muito útil para criar aplicações que precisam trabalhar com áudio, como aplicações de gravação de voz, de reconhecimento de fala, entre outros.

  • numpy: É uma biblioteca que fornece suporte para arrays e matrizes multidimensionais em Python. É usada para realizar operações matemáticas em arrays e matrizes, como adição, subtração, multiplicação, divisão, entre outras. A biblioteca numpy é muito útil para trabalhar com dados numéricos em Python.

  • scipy.signal.butter: É uma função da biblioteca scipy.signal que é usada para projetar filtros digitais que podem ser usados para filtrar sinais de áudio, sinais de vídeo, entre outros.

  • scipy.signal.lfilter: É uma função da biblioteca scipy.signal que é usada para filtrar sinais digitais. A função lfilter é muito útil para filtrar sinais de áudio, sinais de vídeo, entre outros.

  • threading: É uma biblioteca que fornece suporte para threads em Python. É usada para criar e gerir threads no Python. A biblioteca threading é muito útil para criar aplicações que precisam executar várias tarefas simultaneamente.

Funções desenvolvidas:

Para que o código da aplicação fique mais organizado e não exista repetição de código, foram implementadas algumas funções.

  • executarComoThread(): Define a animação do gráfico. Cria uma animação do gráfico que é atualizada a cada 500 milissegundos. A função atualizarGrafico() é executada a cada atualização e é responsável por atualizar o gráfico.

  • atualizarGrafico(): Define uma função que recebe um parâmetro i. A função atualiza os valores do eixo X e cria um gráfico com os valores das frequências. O gráfico é composto por duas linhas, uma vermelha e outra azul, que representam as frequências sem filtro e com filtro, respetivamente. O gráfico também possui um título, rótulos para os eixos X e Y e uma legenda. O limite do eixo Y é definido de acordo com o instrumento escolhido. Além disso, a função adiciona os valores no gráfico.

  • butterBandpass(): Define uma função que implementa um filtro passa-banda Butterworth. Aceita quatro argumentos: lowcut, highcut, fs e order.

    lowcut: A frequência de corte inferior do filtro em Hz.

    highcut: A frequência de corte superior do filtro em Hz.

    fs: A taxa de amostragem do sinal em Hz.

    order: A ordem do filtro Butterworth.

    A função retorna dois arrays NumPy, b e a, que representam os coeficientes do filtro. Esses coeficientes podem ser usados para filtrar um sinal usando a função lfilter do módulo scipy.signal.

  • butterBandpassFilter(): Define uma função que implementa um filtro passa-banda Butterworth de ordem n para um sinal de entrada com frequências de corte e taxa de amostragem. O filtro é implementado usando a função butterBandpass() que retorna os coeficientes do filtro. Em seguida, a função lfilter() é usada para aplicar o filtro ao sinal de entrada usando os coeficientes do filtro. O sinal filtrado é retornado pela função.

  • buscarBlocoNotas(): Define uma função que recebe um argumento "option" e define a variável global "blocoNotas" com base no valor de "option".

  • introduzirNotas(): Define uma função que recebe um número variável de argumentos. A função tem como objetivos: procurar um bloco de notas, limpar o dicionário "notas", ler o bloco de notas e armazená-las as notas no dicionário "notas". Em seguida, a função procura o menor e o maior valor do dicionário "notas" e armazena-os nas variáveis globais "menorValor" e "maiorValor", respetivamente. Por fim, a função imprime o menor e o maior valor do dicionário "notas" e verifica se o dicionário está correto, imprimindo as chaves e os valores do dicionário "notas".

  • ouvir(): Define uma função que durante um intervalo de tempo recolhe o que é captado pelo microfone e guarda esses dados num array. Após isso, o array é convertido para um array numpy do tipo int16, é aplicado o filtro passa-banda e são calculadas as frequências com e sem filtro. Depois são executadas algumas operações com base no valor de "selected_option". Se "selected_option" for igual a "Notas Gerais", o código percorre o dicionário "notas" e encontra o valor mais próximo da frequência. Se "selected_option" não for igual a "Notas Gerais", o código percorre o dicionário "notas" e encontra a nota que corresponde à frequência fornecida. Se a frequência captada for menor que a frequência exata da nota, a variável "simbolo" é definida como "--->" e a variável "cor" é definida como "red". Se a frequência captada for maior que a frequência exata da nota, a variável "simbolo" é definida como "<---" e a variável "cor" é definida como "red". Caso contrário, a variável "simbolo" é definida como "OK" e a variável "cor" é definida como "green".

Resultados:

Quando a aplicação é executada, uma janela e um gráfico são exibidos e vão mostrando a frequência dos dados filtrados e dos dados originais, do que está a ser captado pelo microfone em tempo real. O microfone capta durante 0,5 segundos e guarda o que foi captado num array. Após isso, é necessário converter esse array num array $numpy$ do tipo int16. Assim que está em execução, a aplicação calcula a frequência e indica na janela a frequência captada, a oitava e a nota musical.

Janela principal

Janela principal

Gráfico de frequências em tempo real

Gráfico de frequências em tempo real

O utilizador pode, através de uma lista, adaptar a aplicação para vários tipos de instrumentos.

Instrumentos disponíveis

Instrumentos disponíveis

Por exemplo, se o utilizador escolher o instrumento musical "Guitarra" e tocar numa corda do instrumento, a aplicação vai analisar o som e descobrir qual é a nota que mais se assemelha ao som captado. Depois é indicado se a corda do instrumento se encontra afinada ou não, dependendo da nota musical captada.

Se a seta indicar para a esquerda, significa que a nota se encontra à esquerda, se a seta indicar para a direita, significa que a nota se encontra à direita.

Nota incorreta

Nota incorreta

Se a frequência da nota musical for a correta, existe uma indicação com a palavra "OK" a cor verde.

Nota correta

Nota correta

A função de transferência H $(s)$ de um filtro Butterworth de ordem n pode ser expressa como:

$$ [ H(s) = \frac{1}{\sqrt{1 + \left(\frac{s}{\omega_c}\right)^{2n}}} ] $$

onde:

  • $( s )$ é a variável complexa;
  • $( \omega_c )$ é a frequência de corte;
  • $( n )$ é a ordem do filtro.

A frequência de corte $( \omega_c )$ é o ponto onde a magnitude da resposta em frequência é 3 dB abaixo do ganho na faixa de passagem. Para um filtro Butterworth, as operações matemáticas envolvem manipulação algébrica desta função de transferência. A frequência angular $f$ por $w = 2πf$ está relacionada com a frequência, portanto, a função de transferência também pode ser expressa em termos de $f$ .

Ilustração do filtro Butterworth

Iustração do filtro Butterworth

Filtros Butterworth de ordens mais altas geralmente apresentam características de resposta em frequência mais acentuadas e abruptas em comparação com ordens mais baixas. Isso pode levar a representações gráficas que parecem desproporcionais ou têm características distintas.

About

Desenvolvimento de um afinador que se ajusta automaticamente ao instrumento musical escolhido pelo utilizador

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages