Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How could I "listen" for sounds on the internal motherboard speaker

Tags:

python

windows

We are using a very old program to drive some equipment tests. These tests can run for a couple of days and I would like to know when a test has completed. When a test completes, the executable continuously beeps the motherboard speaker at ~1 beep per second until operator intervention.

Is there a way that I could "listen" for this beep and send out a notification when the MB starts beeping? I am hoping there is a sys or os library that I might use to indicate this.

We are running on Windows XP x86. I have not yet installed Python on the machine.

Pseudocode:

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)
like image 443
Brian Leach Avatar asked Jan 17 '14 17:01

Brian Leach


People also ask

Do motherboards have internal speakers?

A lot of boards have mostly gotten rid of speakers in favour of small LED/LCD displays that show error codes as they're clearer and easier to understand than a series of beeps. That said, a lot still have a small speaker that will beep during boot loops and such.

What is motherboard internal speaker?

Alternatively referred to as a PC speaker, onboard speaker, and system speaker, the internal speaker is a basic speaker on a motherboard that creates beeps, beeping noises, and mono tones. This speaker is very basic and is not a speaker for playing songs, music, or other complex sounds generated in a game.


2 Answers

Is the speaker connected to the motherboard with a 2 pin header?

If so, it should be trivial to intercept it and monitor the signal. Start with an oscilloscope to verify the signal, then hook up some sort of USB digital I/O monitor - you should be able to count pulses and determine frequency. (There are off-the shelf solutions, or a simple Arduino program would work).

Or, if you want to get into really low-level programming, look into querying the "Programmable Interval Timer" chip that drives the speakers. Look specifically at the "output pin state" in the Read Back Status Byte.

You'd probably have to write a C extension to python to access thes ports: See here for some example C code to access the chip.

like image 160
AShelly Avatar answered Oct 12 '22 23:10

AShelly


Ok, here's my attempt at a solution using PyAudio, let me know what you think. Unfortunately, I currently have no means of testing.

This is adapted from the "Record" example on the PyAudio page.

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()

Ok, so that turned out a bit bigger than I expected. This will run for the number of days specified by SEARCHTIME. Every 4.5 seconds, it will record for 5 seconds (to make sure we dont miss anything) This recording will be saved with a dynamic name (to prevent overwriting). Then we perform FFT on that .wav file and see if the frequency is between LOWERBOUND and UPPERBOUND. If the frequency is between these two bounds, a file is created that says when that happens. This code continues until it SEARCHTIME is reached AND at least one beep has been found. Since there is a bit of overlap, all the processing is done in threads.

Note that this can produce false positives, which is why it doesn't terminate after the first finding. Addtionally, if it never finds something, it'll keep running. Forever.

One final note: As I said earlier, I haven't' been able to test it, so it likely won't run on your fist go. I apologize in advance, but at the very least, this should give you a pretty good head start. Please let me know what breaks so I can fix it here!

References:

  • Recording sound: "Record" example from PyAudio page
  • FFT and finding frequency: This post

Good luck

like image 38
wnnmaw Avatar answered Oct 12 '22 23:10

wnnmaw