Частотный анализ в 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 (отсюда и импорт bge вверху), но я почти уверен, что моя проблема заключается в модуле AnalyseStream.

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

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


person Dave Moore    schedule 31.01.2012    source источник
comment
Частота дискретизации 1920 выглядит подозрительно. Более типичные частоты дискретизации звука - 8000 или 44100. Какой звук вы используете для проверки правильности? Если это не от генератора синусоидальной волны, высота тона, которую вы слышите, и пик частоты могут сильно отличаться.   -  person hotpaw2    schedule 31.01.2012


Ответы (2)


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

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

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

#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

эдервандер

person ederwander    schedule 02.02.2012

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

person gypaetus    schedule 07.06.2012