正确配置Aubio / Alsaaudio

时间:2018-03-20 09:23:21

标签: python alsa aubio

我正在尝试将aubio和python用于学校项目,这里的目标是:检测有人发出两个声音,每个声音长度为2秒,并且它们之间的间隔最大为3秒。第二个需要高于第一个。满足这些条件时,程序将发送Wake-On-Lan软件包(未在当前代码中实现)。

import alsaaudio
import numpy as np
import aubio
import time
import threading



class Audio_watcher:
    # constants
    samplerate = 44100
    win_s = 2048
    hop_s = win_s // 2
    framesize = hop_s
    nb_samples = 20
    tone_duration = 2.0
    per_sampling = tone_duration / nb_samples
    tone_max_interval = 3.0
    tone_diff_ratio = 2


    def __init__(self):
        self.last_frequencies = np.zeros(Audio_watcher.nb_samples)
        self.last_energies = np.zeros(Audio_watcher.nb_samples)
        self.detected_tone = 0

        # set up audio input
        recorder = alsaaudio.PCM(type=alsaaudio.PCM_CAPTURE)
        recorder.setperiodsize(Audio_watcher.framesize)
        recorder.setrate(Audio_watcher.samplerate)
        recorder.setformat(alsaaudio.PCM_FORMAT_FLOAT_LE)
        recorder.setchannels(1)
        self.recorder = recorder

        pitcher = aubio.pitch("default", Audio_watcher.win_s, Audio_watcher.hop_s, Audio_watcher.samplerate)
        pitcher.set_unit("Hz")
        pitcher.set_silence(-40)
        self.pitcher = pitcher
        # A filter
        f = aubio.digital_filter(7)
        f.set_a_weighting(Audio_watcher.samplerate)
        self.f = f


    def get_audio(self):
        # read and convert data from audio input
        _, data = self.recorder.read()
        samples = np.fromstring(data, dtype=aubio.float_type)
        filtered_samples = self.f(samples)
        print(filtered_samples)

        # pitch and energy of current frame
        freq = self.pitcher(filtered_samples)[0]
        print(freq)
        self.last_frequencies = np.roll(self.last_frequencies, 1)
        self.last_frequencies[0] = freq
        self.last_energies = np.roll(self.last_energies, 1)
        self.last_energies[0] = np.sum(filtered_samples**2)/len(filtered_samples)

        threading.Timer(Audio_watcher.per_sampling, self.get_audio).start()


    def reset_detected_tone():
        self.detected_tone = 0


    def detect_tone(self):
        std_last = np.std(self.last_frequencies)
        if std_last <= 200 and std_last > 0:
            mean_freq = np.mean(self.last_frequencies)
            if self.detected_tone == 0:
                self.detected_tone = mean_freq
                threading.Timer(Audio_watcher.tone_max_interval, self.reset_detected_tone).start()
            elif mean_freq > Audio_watcher.tone_diff_ratio * self.detected_tone:
                print('wol')

        threading.Timer(Audio_watcher.tone_duration, self.detect_tone).start()



aw = Audio_watcher()
aw.get_audio()
aw.detect_tone()

然而,使用这段代码我会在声音和它们的检测之间得到很大的延迟,我认为它与录音机每0.1秒只调用一次,但我找不到如何给aubio提供正确的参数。
有谁知道如何配置常量以便它可以工作?
非常感谢!

1 个答案:

答案 0 :(得分:1)

找出导致此错误的原因,我需要在get_audio函数中设置设置音频输入的代码,以便每次更新