Частотный анализ в Python

Я пытаюсь использовать Python для получения доминирующих частот живого аудиовхода. На данный момент я экспериментирую с использованием аудиопотока, который мой ноутбук встроен в микрофон, но при тестировании следующего кода я получаю очень плохие результаты.

    # Read from Mic Input and find the freq's
    import pyaudio
    import numpy as np
    import bge
    import wave

    chunk = 2048

    # use a Blackman window
    window = np.blackman(chunk)
    # open stream
    FORMAT = pyaudio.paInt16
    CHANNELS = 1
    RATE = 1920

    p = pyaudio.PyAudio()
    myStream = p.open(format = FORMAT, channels = CHANNELS, rate = RATE, input = True, frames_per_buffer = chunk)

    def AnalyseStream(cont):
        data = myStream.read(chunk)
        # unpack the data and times by the hamming window
        indata = np.array(wave.struct.unpack("%dh"%(chunk), data))*window
        # Take the fft and square each value
        fftData=abs(np.fft.rfft(indata))**2
        # find the maximum
        which = fftData[1:].argmax() + 1
        # use quadratic interpolation around the max
        if which != len(fftData)-1:
            y0,y1,y2 = np.log(fftData[which-1:which+2:])
            x1 = (y2 - y0) * .5 / (2 * y1 - y2 - y0)
            # find the frequency and output it
            thefreq = (which+x1)*RATE/chunk
            print("The freq is %f Hz." % (thefreq))
        else:
            thefreq = which*RATE/chunk
            print("The freq is %f Hz." % (thefreq))

    # stream.close()
    # p.terminate()

Код упорядочен из этого вопроса, который посвящен анализу Фурье волнового файла. Это в текущей модульной структуре, поскольку я реализую ее с помощью среды Blender Game (следовательно, import bge наверху), но я вполне уверен, что моя проблема лежит в модуле AnalyseStream.

Любые советы, которые вы можете предложить, будут высоко оценены.

UPDATE: я получаю правильные значения время от времени, но они встречаются редко среди неправильных значений (< 10 Гц). Это и программа работает ДЕЙСТВИТЕЛЬНО медленно.

Ответ 1

Привет, найдем максимальное вычисление БПФ для анализа в реальном времени становится немного медленным.

Если вы не будете работать со сложными волновыми формами, чтобы найти частоты, вы можете использовать любой метод, основанный на временной области, такой как пересечение нуля, где производительность будет лучше.

В прошлом году я делаю одну простую функцию для вычисления частоты путем пересечения нуля.

#Eng Eder de Souza 01/12/2011
#ederwander
from matplotlib.mlab import find
import pyaudio
import numpy as np
import math


chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 20


def Pitch(signal):
    signal = np.fromstring(signal, 'Int16');
    crossing = [math.copysign(1.0, s) for s in signal]
    index = find(np.diff(crossing));
    f0=round(len(index) *RATE /(2*np.prod(len(signal))))
    return f0;


p = pyaudio.PyAudio()

stream = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
output = True,
frames_per_buffer = chunk)

for i in range(0, RATE / chunk * RECORD_SECONDS):
    data = stream.read(chunk)
    Frequency=Pitch(data)
    print "%f Frequency" %Frequency

ederwander

Ответ 2

Существует также функция scipy.signal.lombscargle, которая вычисляет периодограмму Ломб-Скворца и доступна с v0.10.0. Этот метод должен работать даже для неравномерно выбранных сигналов. Похоже, что значение данных должно быть вычтено, чтобы этот метод работал правильно, хотя это не упоминается в документации. Более подробную информацию можно найти в справочном руководстве Scipy: http://docs.scipy.org/doc/scipy/reference/tutorial/signal.html#lomb-scargle-periodograms-spectral-lombscargle