【问题标题】:How could I "listen" for sounds on the internal motherboard speaker我如何“听”内部主板扬声器上的声音
【发布时间】:2014-01-21 07:00:02
【问题描述】:

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

有没有一种方法可以让我“听到”此哔哔声并在 MB 开始哔哔声时发出通知?我希望有一个sysos 库可以用来表明这一点。

我们在 Windows XP x86 上运行。我还没有在机器上安装 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)

【问题讨论】:

  • 您的计算机是否有可以尝试从属的麦克风?
  • 听上去是一件很酷的极客之事,我们都愿意为之梦想一个解决方案,但必须有更好的方法来实现它。没有退出代码,或者您可以监控的进程?甚至屏幕抓取可能会更容易。
  • @wnnmaw 我想我不明白你说的奴役麦克风是什么意思。如果需要,我可以找到一个麦克风。
  • 你使用的是什么架构和操作系统?
  • @wnnmaw 尽管我很想实施和测试您提出的方法,但我无法证明学习曲线来解决这个特定问题是合理的。感谢您的回复,我相信有人会发现它很有用。我最终培训了一些实验室技术人员,当他们听到哔哔声时该怎么做:)

标签: python windows


【解决方案1】:

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

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

或者,如果您想进行真正的低级编程,请查看drives the speakers"Programmable Interval Timer" 芯片。具体看Read Back Status Byte中的“输出引脚状态”。

您可能必须为 python 编写一个 C 扩展来访问这些端口:请参阅 here 以获取访问芯片的一些示例 C 代码。

【讨论】:

    【解决方案2】:

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

    这改编自 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()
    

    好的,结果比我预期的要大一些。这将运行SEARCHTIME 指定的天数。每 4.5 秒,它会记录 5 秒(以确保我们不会遗漏任何内容)此记录将以动态名称保存(以防止覆盖)。然后我们对那个.wav文件执行FFT,看看频率是否在LOWERBOUNDUPPERBOUND之间。如果频率在这两个界限之间,则会创建一个文件,说明何时发生。这段代码一直持续到到达SEARCHTIME并且至少找到一个哔声。由于有一点重叠,所以所有的处理都是在线程中完成的。

    请注意,这可能会产生误报,这就是它不会在第一次发现后终止的原因。此外,如果它永远找不到任何东西,它将继续运行。永远。

    最后一点:正如我之前所说,我无法对其进行测试,因此它可能不会立即运行。我提前道歉,但至少,这应该给你一个很好的开端。请让我知道发生了什么问题,以便我在这里修复它!

    参考资料:

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

    祝你好运

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-27
        • 1970-01-01
        • 1970-01-01
        • 2012-10-16
        • 1970-01-01
        • 1970-01-01
        • 2013-01-10
        • 1970-01-01
        相关资源
        最近更新 更多