Частотный анализ в Python - PullRequest
11 голосов
/ 31 января 2012

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

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

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

Ответы [ 2 ]

6 голосов
/ 03 февраля 2012

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

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

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

#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 голосов
/ 07 июня 2012

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

...