How do I write raw bytes to a sound-device?

In the olden days, you used to be able to open /dev/dsp for reading and writing, now, with PulseAudio this doesn't work anymore.

I thought you could do it with padsp, but this code doesn't run:

import ossaudiodev

f = ossaudiodev.open("w")
fmt, channels, rate = dsp.setparameters(fmt, channels, rate)

(running it via padsp python script.py)

The error I get is No such file or directory: '/dev/dsp'.

What am I missing? How do I read and write raw bytes from and to a sound device, and how do I select which one I want to use?


This script is a thin wrapper around PulseAudio's Simple API. It allows you to write samples to the default output:

#!/usr/bin/env python3

import random
import ctypes
import struct

class NoiseMaker (object):

    PA_SAMPLE_U8 = 0
    PA_STREAM_PLAYBACK = 1

    def __init__(self, rate, channels):
        pat_sample_spec = ctypes.c_buffer(struct.pack("LLB",
            self.PA_SAMPLE_U8, rate, channels))
        self.pa = ctypes.cdll.LoadLibrary("libpulse-simple.so.0")
        self.s = self.pa.pa_simple_new(0, "App", self.PA_STREAM_PLAYBACK,
            0, "App Noise", ctypes.byref(pat_sample_spec), 0, 0,0)

    def write(self, data):
        self.pa.pa_simple_write(self.s, data, len(data), 0)

    def __del__(self):
        self.pa.pa_simple_free(self.s)


one_second_noise = bytes(random.randint(0, 255) for i in range(44100*2))
NoiseMaker(44100, 2).write(one_second_noise)

The rate (44100) defines how many samples there are in a second of real time. It expects bytes in the range of 0-255 inclusive, which is defined by PA_SAMPLE_U8 (equivalent to 'Unsigned 8-Bit' as shown by Audacity, for example). If you have more than one channel, it expects alternating samples for each of them. So, one second of noise has 44100 samples per channel = 88200 samples, where the (modulo 2 = 0) ones are for the left channel.

Please note that this script runs only on Python 3