Python “我怎么可能?”;“听”;对于内置主板扬声器的声音

Python “我怎么可能?”;“听”;对于内置主板扬声器的声音,python,windows,Python,Windows,我们正在使用一个非常旧的程序来驱动一些设备测试。这些测试可以运行几天,我想知道测试何时完成。测试完成后,可执行文件会以每秒约1嘟嘟声的速度持续向主板扬声器发出嘟嘟声,直到操作员干预为止 有没有一种方法可以让我“监听”这个蜂鸣音,并在MB开始蜂鸣时发出通知?我希望有一个sys或os库可以用来说明这一点 我们在WindowsXPx86上运行。我还没有在机器上安装Python 伪代码: already_beeping = True while True: speaker_beeping = ch

我们正在使用一个非常旧的程序来驱动一些设备测试。这些测试可以运行几天,我想知道测试何时完成。测试完成后,可执行文件会以每秒约1嘟嘟声的速度持续向主板扬声器发出嘟嘟声,直到操作员干预为止

有没有一种方法可以让我“监听”这个蜂鸣音,并在MB开始蜂鸣时发出通知?我希望有一个
sys
os
库可以用来说明这一点

我们在WindowsXPx86上运行。我还没有在机器上安装Python

伪代码:

already_beeping = True

while True:
  speaker_beeping = check_speaker() # returns True or False
  if speaker_beeping == True:
    if already_beeping == False:
      send_notification()
      already_beeping = True
    else:
      pass
  else:
    already_beeping = False
  time.sleep(10)

扬声器是否通过2针头连接到主板

如果是这样的话,截获它并监视信号应该是微不足道的。从示波器开始验证信号,然后连接某种USB数字I/O监视器-您应该能够计算脉冲并确定频率。(有现成的解决方案,或者一个简单的Arduino项目就可以了)

或者,如果你想进入真正的低级编程领域,就去查询那个芯片。请特别查看中的“输出引脚状态”


您可能需要为python编写一个C扩展来访问这些端口:请参阅一些访问芯片的C代码示例。

好的,下面是我尝试使用的解决方案,让我知道您的想法。不幸的是,我目前没有测试手段

这是根据PyAudio页面上的“录制”示例改编的

import threading
import PyAudio
import wave
import struct
import numpy as np
import os
import datetime

CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5

SEARCHTIME = 5
LOWERBOUND = 0.9
UPPERBOUND = 1.1

class RecorderThread(threading.Thread):
    def __init__(self, name):
        threading.Thread.__init__(self)
        self.name = name
        self.stream = p.open(format=FORMAT,
                             channels=CHANNELS,
                             rate=RATE,
                             input=True,
                             frames_per_buffer=CHUNK)
        self.start()

    def run(self):
        p = pyaudio.PyAudio()
        print("* recording")

        frames = []

        for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
            data = self.stream.read(CHUNK)
            frames.append(data)

        print("* done recording")

        self.stream.stop_stream()
        self.stream.close()
        p.terminate()

        wf = wave.open(self.name, 'wb')
        wf.setnchannels(CHANNELS)
        wf.setsampwidth(p.get_sample_size(FORMAT))
        wf.setframerate(RATE)
        wf.writeframes(b''.join(frames))
        wf.close()

        frate = RATE
        wav_file = wave.open(self.name,'r')
        data = wav_file.readframes(wav_file.getnframes())
        wav_file.close()
        os.remove(self.file)
        data =s truct.unpack('{n}h'.format(n=data_size), data)
        data = np.array(data)

        w = np.fft.fft(data)
        freqs = np.fft.fftfreq(len(w))

        idx=np.argmax(np.abs(w)**2)
        freq=freqs[idx]
        freq_in_hertz=abs(freq*frate)

        if freq_in_herts > LOWERBOUND and freq_in_herts < UPPERBOUND:
            curName = "found0.txt"

            while os.path.exists(curName):
                num = int(curName.split('.')[0][6:])
                curName = "found{}.txt".format(str(num+1))

            f = open(curName, 'r')
            f.write("Found it at {}".format(datetime.datetime.now()))
            f.close()

def main():
    recordingThreads = []

    totalTime = 0

    while totalTime < SEARCHTIME*(24*3600) and not os.path.exists("found.txt"):
        start = datetime.datetime(year=2012, month=2, day=25, hour=9)

        curName = "record0.wav"

        while os.path.exists(curName):
            num = int(curName.split('.')[0][6:])
            curName = "record{}.wav".format(str(num+1))

        recorder = RecorderThread(curName)
        time.sleep(4.5)
        end = datetime.datetime(year=2012, month=2, day=25, hour=18)
        totalTime += end - start

if __name__ == "__main__": main()
导入线程
导入PyAudio
输入波
导入结构
将numpy作为np导入
导入操作系统
导入日期时间
区块=1024
格式=pyaudio.paInt16
通道=2
费率=44100
记录时间=5秒
搜索时间=5
LOWERBOUND=0.9
上限=1.1
类记录器线程(threading.Thread):
定义初始化(self,name):
threading.Thread.\uuuuu init\uuuuuu(自)
self.name=名称
self.stream=p.open(format=format,
频道=频道,
比率=比率,
输入=真,
帧(每帧缓冲区=块)
self.start()
def运行(自):
p=pyaudio.pyaudio()
打印(“*记录”)
帧=[]
对于范围内的i(0,int(速率/块*记录秒)):
data=self.stream.read(块)
frames.append(数据)
打印(“*已完成录制”)
self.stream.stop_stream()
self.stream.close()
p、 终止()
wf=wave.open(self.name,“wb”)
wf.设置通道(通道)
wf.setsampwidth(p.get_样本大小(格式))
设置帧率(速率)
wf.writeframes(b.)。连接(帧))
wf.close()
弗拉特=汇率
wav_file=wave.open(self.name,'r')
data=wav_file.readframes(wav_file.getnframes())
wav_文件.close()
删除(self.file)
data=s结构解包({n}h'.格式(n=data\u大小),数据)
data=np.array(数据)
w=np.fft.fft(数据)
freqs=np.fft.fftfreq(len(w))
idx=np.argmax(np.abs(w)**2)
freq=freqs[idx]
频率单位为赫兹=绝对值(频率*频率)
如果freq_in_herts>下限,freq_in_herts<上限:
curName=“found0.txt”
当os.path.exists(curName)存在时:
num=int(curName.split('.')[0][6:]
curName=“found{}.txt”。格式(str(num+1))
f=打开(curName,'r')
f、 write(“在{}找到它”。格式(datetime.datetime.now())
f、 关闭()
def main():
recordingThreads=[]
总时间=0
当totalTime
好的,结果比我预期的要大一点。这将在
SEARCHTIME
指定的天数内运行。每4.5秒,它将录制5秒(以确保我们不会错过任何内容)。此录制将使用动态名称保存(以防止覆盖)。然后我们在
.wav
文件上执行FFT,查看频率是否在
下限
上限
之间。如果频率介于这两个界限之间,则会创建一个文件,说明发生频率的时间。此代码将一直持续,直到达到
SEARCHTIME
并且发现至少一声蜂鸣音。因为有一点重叠,所以所有的处理都是在线程中完成的

请注意,这可能会产生误报,这就是为什么它不会在第一次发现后终止。另外,如果它没有找到什么东西,它会继续运行。永远

最后一点注意:正如我之前所说的,我还无法测试它,所以它很可能不会在你的拳头上运行。我提前道歉,但至少,这会给你一个很好的开端。请让我知道什么坏了,这样我就可以在这里修理它了

参考文献:

  • 录制声音:PyAudio页面中的“录制”示例
  • FFT和查找频率:

祝你好运

我不熟悉Windows上的编程,所以这个答案有很多猜测


该程序可能会调用一些Windows API函数来提示扬声器,这可能是由某个DLL提供的。在POSIX平台上,我将使用
LD_PRELOAD
加载一个共享库,该库将用我自己的版本覆盖该API函数,然后它将能够通知我。Windows上可能有类似的技术;也许有帮助。

你的电脑有微型计算机吗