Estou tentando criar um analisador de espectro gráfico em python.
No momento, estou lendo 1.024 bytes de um fluxo de áudio de taxa de amostragem de canal duplo de 16 bits e 44.100 Hz e calculando a média da amplitude dos 2 canais juntos. Portanto, agora tenho uma matriz de 256 shorts assinados. Agora quero pré-formar um fft nessa matriz, usando um módulo como numpy, e usar o resultado para criar o analisador de espectro gráfico, que, para começar, terá apenas 32 barras.
Eu li os artigos da Wikipedia sobre Fast Fourier Transform e Discrete Fourier Transform, mas ainda não estou certo do que a matriz resultante representa. Esta é a aparência da matriz depois que eu pré-formo um fft na minha matriz usando numpy:
[ -3.37260500e+05 +0.00000000e+00j 7.11787022e+05 +1.70667403e+04j
4.10040193e+05 +3.28653370e+05j 9.90933073e+04 +1.60555003e+05j
2.28787050e+05 +3.24141951e+05j 2.09781047e+04 +2.31063376e+05j
-2.15941453e+05 +1.63773851e+05j -7.07833051e+04 +1.52467334e+05j
-1.37440802e+05 +6.28107674e+04j -7.07536614e+03 +5.55634993e+03j
-4.31009964e+04 -1.74891657e+05j 1.39384348e+05 +1.95956947e+04j
1.73613033e+05 +1.16883207e+05j 1.15610357e+05 -2.62619884e+04j
-2.05469722e+05 +1.71343186e+05j -1.56779748e+04 +1.51258101e+05j
-2.08639913e+05 +6.07372799e+04j -2.90623668e+05 -2.79550838e+05j
-1.68112214e+05 +4.47877871e+04j -1.21289916e+03 +1.18397979e+05j
-1.55779104e+05 +5.06852464e+04j 1.95309737e+05 +1.93876325e+04j
-2.80400414e+05 +6.90079265e+04j 1.25892113e+04 -1.39293422e+05j
3.10709174e+04 -1.35248953e+05j 1.31003438e+05 +1.90799303e+05j...
Estou me perguntando o que exatamente esses números representam e como eu converteria esses números em uma porcentagem de uma altura para cada uma das 32 barras. Além disso, devo calcular a média dos 2 canais juntos?
Embora este tópico tenha anos, achei-o muito útil. Eu só queria dar minha opinião a qualquer pessoa que descobrir isso e estiver tentando criar algo semelhante.
Quanto à divisão em barras, isso não deve ser feito como o antti sugere, dividindo os dados igualmente com base no número de barras. O mais útil seria dividir os dados em oitavas, cada oitava sendo o dobro da frequência da anterior. (ou seja, 100 Hz é uma oitava acima de 50 Hz, que é uma oitava acima de 25 Hz).
Dependendo de quantos compassos você deseja, você divide toda a gama em intervalos de 1 / X oitava. Com base em uma determinada frequência central de A na barra, você obtém os limites superior e inferior da barra de:
Para calcular a próxima frequência central adjacente, você usa um cálculo semelhante:
Em seguida, você calcula a média dos dados que se enquadram nessas faixas para obter a amplitude de cada barra.
Por exemplo: Queremos dividir em intervalos de 1/3 oitavas e começamos com uma frequência central de 1 khz.
Dadas amostras de 44100 Hz e 1024 (43 Hz entre cada ponto de dados), devemos calcular a média dos valores de 21 a 26. (890,9 / 43 = 20,72 ~ 21 e 1122,5 / 43 = 26,10 ~ 26)
(Barras de 1/3 de oitava gerariam cerca de 30 compassos entre ~ 40 Hz e ~ 20 kHz). Como você pode perceber agora, à medida que subimos, teremos a média de um intervalo maior de números. Barras baixas normalmente incluem apenas 1 ou um pequeno número de pontos de dados. Enquanto as barras mais altas podem ter a média de centenas de pontos. A razão é que 86 Hz é uma oitava acima de 43 Hz ... enquanto 10086 Hz soa quase o mesmo que 10043 Hz.
fonte
o que você tem é uma amostra cuja duração no tempo é 256/44100 = 0,00580499 segundos. Isso significa que sua resolução de frequência é 1 / 0,00580499 = 172 Hz. Os 256 valores que você obtém do Python correspondem às frequências, basicamente, de 86 Hz a 255 * 172 + 86 Hz = 43946 Hz. Os números que você obtém são números complexos (daí o "j" no final de cada segundo número).
EDITADO: INFORMAÇÕES ERRADAS FIXAS
Você precisa converter os números complexos em amplitude calculando o sqrt (i 2 + j 2 ) onde i e j são as partes reais e imaginárias, resp.
Se você quiser ter 32 barras, você deve, pelo que entendi, tirar a média de quatro amplitudes sucessivas, obtendo 256/4 = 32 barras como você deseja.
fonte
FFT retorna N valores complexos que podem ser calculados
module=sqrt(real_part^2+imaginary_part^2)
. Para obter o valor de cada banda, você deve somar os módulos sobre todos os harmônicos dentro da banda. Abaixo você pode ver um exemplo sobre um analisador de espectro de 10 barras. O código c deve ser encapsulado para obter um módulo pyd python.Eu projetei e fiz um analisador de espectro de barras inteiro de 10 led da Python. Em vez de usar a biblioteca nunmpy (muito grande e inútil para obter apenas o FFT), foi criado um módulo python pyd (apenas 27 KB) para obter o FFT e dividir todo o espectro de áudio em bandas.
Além disso, para ler a saída de áudio, foi criado um módulo loopback WASapi portaudio pyd. Você pode ver o projeto (diagrama de blocos) na imagem 10BarsSpectrumAnalyzerWithWASapi.jpg
Acabei de adicionar um vídeo tutorial no meu canal do YouTube: como projetar e fazer uma barra de LED 10 do Python Spectrum Analyzer muito inteligente
fonte