2

我正在尝试将 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 提供正确的参数。
有谁知道如何配置常量使其工作?
非常感谢 !

4

1 回答 1

1

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

于 2018-03-24T17:40:27.317 回答