40

Recently I have been exploring the enchanted /dev folder. I want to write some random data to an audio device in order to generate some noise.

I am using ALSA.

So I instruct cat to pipe some random data to the playback file in the /dev folder...

 cat file-of-random-data > /dev/snd/pcmC0D0p

then I recieve what seems to be an error from cat

 cat: write error: File descriptor in bad state

How can I fix this so I can hear some delicious static play from my sound card?

  • 1
    I think you need to send random PCM data, or maybe you need to set up the device with a few ioctls first — you can't just dump random bytes. – Gilles May 25 '11 at 7:22
  • @Gilles According to Wikipedia, .wav is PCM and I get exactly the same result when replace the random file with a .wav file. I will investigate setting up some in/out controls. – jones May 25 '11 at 8:52
  • Does someone have a pointer for a tutorial on how to set up some ioctls? For something called ioctls, I thought ALSA as an API should provide the interface for input and output? – jones May 25 '11 at 10:20
  • Here is a working example how to write pcm data directly to the device file: github.com/igor-liferenko/pcm – Igor Liferenko Jan 22 '18 at 3:31
45

I think the reason this isn't working for you is because that interface has been deprecated. You normally can't write audio using /dev/dsp anymore, at least without being tricky.

There is a program that will accomplish this for you on your system: padsp. This will map the /dev/audio or /dev/dsp file to the new Audio Server system.

Fire up the terminal and get into root mode with sudo su.

Then, I'm going to cat /dev/urandom and pipe the output into padsp and use the tee command to send the data to /dev/audio. You'll get a ton of garbage in your terminal, so you may want to redirect to /dev/null.

Once you're in superuser, try this command:

cat /dev/urandom | padsp tee /dev/audio > /dev/null

You may even want to try with other devices, like your mouse: Use: /dev/psaux, for instance or the usb driver. You can even run your memory through it: /dev/mem

Hope this clarifies why it wasn't working before.

Personally, I found the mouse and memory to be way more interesting than playing random static!

  • 1
    Thanks a lot! This is what I was looking for. Answered a full 7 months after posting the question! :-) – jones Jan 28 '12 at 9:50
  • 3
    It seems that sudo privileges are not required for this. – iyrin May 8 '15 at 18:03
  • 2
    thanks very much. i found binaries to be weirdly interesting. things like /usr/bin/ls /usr/bin/gnome-terminal /usr/bin/mysql – don bright Jun 5 '15 at 5:59
  • hmm, strange, 'tee' can do this but 'dd of=/dev/audio' cannot. – Jasen Feb 13 '18 at 22:50
  • @Jasen dd may be writing too much at a time. padsp simulates /dev/audio to redirect it through alsa. dd without padsp will not even see /dev/audio unless in-kernel OSS emulation is enabled (and by default it isn't). And I think writing a large block, much larger than the in-driver buffers, could even fail. – Paul Stelian Aug 6 at 10:49
8

cat /dev/urandom | aplay is the command that needs to be typed. If you aren't in "audio" group, you could prefix aplay with sudo. This also doesn't interfere with any daemons (I was running pulseaudio while this command was active and correctly heard the "noise".

EDIT (Aug 6, 2019): In an older version of the command I also had a padsp tee thing between the cat and aplay. Now that I'm actually working in the field I realise that it made absolutely no sense. Also, I know the updated command (the one visible now at the beginning of this answer) works because I use it several times a day at work.

  • 6
    I use ALSA, and "padsp tee" isn't necessary. – Geremia Jan 11 '14 at 23:31
  • 1
    In my pulseaudio experiences (and whatever Ubuntu is using when PA is down) that padsp tee was required (I had precise 12.04.2 at that time) The thing is you shouldn't try to dump data directly into devices, even if you were root (as far as I know few files are readable and none writable in the /dev folder), because you could either get an error (in the best case, which gets more common with each update), crash the kernel or even break the device, in rare cases. One should use unprivileged elements, like aplay, to do this (audio group or root required, unfortunately). @geremia – Paul Stelian Feb 3 '14 at 2:12
  • Funny how now I see that the padsp tee thing actually doesn't make any sense AT ALL. At work I use something similar without that line to test that I'm making progress with writing the audio driver. Will now update my answer. – Paul Stelian Aug 6 at 10:41
3

Try /dev/audio or one of the other devices under /dev/snd. Not all of them are audio data sinks, you might have caught a mixer, microphone, or something

  • 1
    thanks for the reply. According to /proc/asound/devices /dev/snd/pcmC0D0p is the right device for audio playback (hence the 'p') – jones May 25 '11 at 10:06
  • 1
    Also, I am not sure, but can there be multiple dev "files" for playback? I don't have a '/dev/audio' I think '/dev/audio' has something to do with OSS which is used on older kernels (before 2.5) – jones May 25 '11 at 10:14
2

Is a sound daemon (e.g. pulseaudio) holding a lock on the device? I think you can find out if anything else has a handle on it via lsof.

  • 1
    Thanks for the helpful suggestion. I had a check, using grep and lsof. pulseaudio is using /dev/snd/controlC0 but it isn't on /dev/snd/pcmC0D0p . I had a double check by going to /var/lock to find if there was a file for a lock on the device. ls -al tells that the folder is empty. So I guess there is no lock on pcmC0D0p – jones May 31 '11 at 12:51
  • @jones Holding a lock on the control may be enough to lock the whole card, depending on the driver. (sorry for answering after 8 years, now I learnt that myself) – Paul Stelian Aug 6 at 10:44
0

TL;DR: The device's parameters must be set before reading or writing data to it.

Step by step:

  1. Open the PCM device. E.g.: fd = open("/dev/snd/pcmC0D0p", O_RDWR). After open, PCM is in OPEN state.

  2. Set parameters with ioctl(fd, SNDRV_PCM_IOCTL_HW_PARAMS, (struct snd_pcm_hw_params*) p). The hardware parameters structure has masks (each bit is a value) and intervals ([minimum, maximum] range). The parameters that are not being set must be passed filled (all bits/values set for masks; full range for intervals). After setting hardware parameters, PCM is in SETUP state. See pcm_set_config() of TinyALSA for code.

    Setting ACCESS, FORMAT, RATE, CHANNELS, PERIOD_SIZE and PERIODS is sufficient. The other parameters are variants of these, except BUFFER_SIZE that in some devices may be set to a non multiple of PERIOD_SIZE.

  3. Call ioctl(fd, SNDRV_PCM_IOCTL_PREPARE) to prepare device and ALSA runtime variables. After this, the PCM is in PREPARED state.

  4. Start reading (capture) or writing (playback).

A minimal application for reading or writing to a PCM device will have most of its code around hardware parameters manipulation.

  • I'm not sure if actual read/write work, as aplay uses (at least on the system I'm developing on) ioctl(fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, ...) and not an actual write() call on playback. Does ALSA itself have a wrapper that takes the read/write entry points and translates them to the ioctl's? – Paul Stelian Aug 6 at 10:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.