[Tutor] Beep sound

eryksun eryksun at gmail.com
Sun Mar 24 09:24:55 CET 2013


On Sun, Mar 24, 2013 at 12:38 AM, Phil <phil_lor at bigpond.com> wrote:
> On 24/03/13 12:18, Steven D'Aprano wrote:
>> Nonsense. Not only does echo exist as a command on any Unix, including
>> Apple Mac OS, FreeBSD, OpenBSD, Solaris and others, it also exists on
>> Windows and DOS:
> I don't want to appear augmentative but there is no echo -e command for
> Windows. There is, however, echo without the 'e' switch.

PulseAudio also suggests that you're using Linux or BSD, though I
think it does have ports for OS X and Windows.

The ossaudiodev module exists on Linux/BSD, so try something
relatively simple like outputting a square wave to /dev/dsp. Here's an
example device configuration:

    format = ossaudiodev.AFMT_U8  # unsigned 8-bit
    channels = 1
    rate = 8000  # samples/second
    strict = True

    dsp = ossaudiodev.open('/dev/dsp', 'w')
    dsp.setparameters(format, channels, rate, strict)

Say you want a 1000 Hz, 50% duty-cycle square wave. Given the rate is
8000 sample/s, that's 8 samples per cycle. In 8-bit mode, a cycle has
four bytes at the given amplitude followed by four null bytes. For a
0.5 s beep, you need 0.5 * 1000 = 500 cycles.

In general:

    amp = chr(amplitude)  # bytes([amplitude]) in 3.x
    cycles = int(duration * frequency)
    nhalf = int(0.5 * rate / frequency)
    data = (amp * nhalf + b'\x00' * nhalf) * cycles

Then just write the data. Make sure to close the device when you no
longer need it.

    dsp.write(data)
    dsp.close()

You can use threading to play the beep in the background without
blocking the main thread. To me this is simpler than juggling partial
writes in nonblock mode. However, you can't access the device
concurrently. Instead you could make beep() a method. Then queue the
requests, to be handled sequentially by a worker thread.


More information about the Tutor mailing list