OpenBSD FAQ - Multimedia [FAQ Index]



Enabling Audio Recording

For privacy reasons, audio recording is disabled by default in OpenBSD. The kern.audio.record sysctl may be used to enable it.
# sysctl kern.audio.record=1
# echo kern.audio.record=1 >> /etc/sysctl.conf

Configuring Audio Hardware

Each sound card model has its own set of controls. Some have no controls at all; others have a hundred or more. Running mixerctl(8) as root will list all of the controls and current settings.

Not every option of every audio chip necessarily reaches the outside world. There may be, for example, more outputs listed than are physically connected. The controls of an audio device may be labeled differently. Usually the controls have a meaningful label, but sometimes one must simply try different settings to see what effect each control has.

Here's a list of controls to consider:

Mute and Level controls - Even if the main controls seem to be properly set, there might be multiple mute or level controls in the signal path. In the example below, the device has a master recording level and a microphone gain control:

record.adc-0:1=248,248
record.adc-0:1_source=mic
inputs.mic=85,85
External Amplifier Power-Down (EAPD) - This switch is typically used for power saving in laptops and may need to be set to get an output signal:
outputs.spkr_eapd=on
Recording Source - Some devices have multiple microphone inputs. Examples of such controls:
record.source=mic
record.adc-0:1_source=mic
To make the changes take effect on each reboot, edit the /etc/mixerctl.conf file. For example:
record.adc-0:1_source=mic
inputs.mic=85,85

Adjusting Audio Levels

The sndioctl(1) utility is used to manipulate audio controls as a regular user. Running it with no arguments will list all the controls and current settings.

The output.level control is always present. It either corresponds to a hardware control or is emulated in software.

Using a USB Audio Interface

An example of a USB audio interface in a dmesg output might look like this:
uaudio0 at uhub2 port 1 configuration 1 interface 1 "ABC C-Media USB Audio Device" rev 1.10/1.00 addr 2
uaudio0: class v1, full-speed, sync, channels: 2 play, 1 rec, 8 ctls
audio1 at uaudio0
On most systems, the first audio device is the internal sound card. A USB audio device then becomes the second one when connected. In the default sndiod(8) configuration, both devices are known to programs as snd/0 (the default) and snd/1 respectively and may be used independently. Programs set up to use snd/1 will use the USB device.

sndiod(8) may be configured to make snd/0 correspond to the USB device if it's connected or to the internal one when it's not:

# rcctl set sndiod flags -f rsnd/0 -F rsnd/1
# rcctl restart sndiod
When the server opens the device, it will first try the USB one. If it's not present, the internal one is used instead. If the USB device is disconnected, sndiod attempts to continue operation using the internal sound card. If the USB device is connected again, sndiod will see it the next time it attempts to open the device. To force sndiod to switch between devices, reload the server:
# rcctl reload sndiod

Playing Audio

OpenBSD comes with aucat(1), a program able to play uncompressed WAV, AIFF and AU files. It can be used in very simple cases or to test playback:

$ aucat -i filename.wav
There are many other players available as packages that support other audio formats.

Recording Audio

Once recording is enabled with the kern.audio.record sysctl, aucat(1) can be used for recording uncompressed WAV, AIFF and AU files.
$ aucat -o file.wav
The above command will start the recording of a file in WAV format. Press CTRL+C to finish the recording.

To play the file back, run:

$ aucat -i file.wav
If recording seemed to work, but playback of the recording was silent or not what was expected, the mixer probably needs some configuration. Make sure that you select the right source to record from and that it is unmuted.

If needed, the resulting WAV file could be compressed with the appropriate program from the ports tree. Alternatively, ports like audacity or ffmpeg can be used to record, process and compress audio files.

Recording a Monitor Mix of All Audio Playback

A monitoring stream records combined audio output from all playback devices, allowing you to duplicate or save anything going through the audio subsystem. This feature can be useful for screencasts or any kind of live audio mixing.

Create the monitor sub-device mon for sndiod(8) by using:

# rcctl set sndiod flags -s default -m play,mon -s mon
# rcctl restart sndiod
Configure your program to record audio from the snd/0.mon device, for instance:
$ aucat -f snd/0.mon -o file.wav
At this point, whatever your system plays is recorded in file.wav.

Lowering Audio Latency

Latency is the time between when a program takes the decision to play a sample and when the user hears the sample. Since audio data is always buffered, this delay is proportional to the audio buffer size. The following values are recommended: The smaller the audio buffers are (to achieve low latency), the larger the probability to overrun/underrun is. Buffer overruns/underruns result in stuttering of the sound.

sndiod(8) imposes a minimum latency on all audio applications, and the default latency is 160ms. If you plan to use applications that require a lower latency, use the -b option to select the desired latency (expressed in number of frames). For instance, at 48000 samples/second, 50ms latency corresponds to:

48000 samples/second × 0.050 seconds = 2400 samples
Then do:
# rcctl set sndiod flags -b2400

Does low latency improve audio-video synchronization?

No, synchronizing audio to video doesn't require low latency. Synchronization problems are often caused by the software itself. Forcing the application to use smaller buffers (by starting sndiod(8) in low latency mode) may hide the actual problem in some cases, and give the feeling that the software works better, but obviously the right thing to do is to start searching for the corresponding bug.

Using Remote Audio Hardware

sndiod(8) can be configured to accept connections from the network, allowing other machines to use the sound card as well. On the remote system with the sound card, run:
# rcctl set sndiod flags -L-
On the local system, configure your program to use snd@hostname/0, where "hostname" is the address of the remote system. The AUDIODEVICE environment variable could be set to the above value to make the remote sound card the default audio device.

Any system able to connect to TCP port 11025 of the remote host will be able to use the audio device. For privacy reasons, only one user from one system may have connections to it at a given time. If multiple systems have to use the audio device simultaneously, the sndio(7) authorization cookie must be the same. For instance, copy your ~/.sndio/cookie to all accounts that may use the audio device.

To avoid glitches, TCP traffic on port 11025 could be prioritized with the packet filter. With the default configuration, sndiod will consume around 200kB/s of network bandwidth.

Choosing the Default Audio Device

The default audio device is selected with the AUDIODEVICE environment variable. If it's not set, snd/0 is used, which is the first audio device managed by sndiod(8). The most flexible way of choosing the default device is to export AUDIODEVICE, possibly in the user's login profile.

Another way to change the default audio output device is to make the desired device the first device managed by sndiod(8). For example, to use an external DAC rather than your motherboard's onboard audio, just change sndiod(8)'s startup flags to use that device:

# rcctl set sndiod flags -f rsnd/1
# rcctl restart sndiod
This would make the second audio device (rsnd/1) the default.

Debugging Audio Problems

If you do not hear anything when playing audio, it's possible there is a mixer control turned to low or simply muted. See this section for configuring the mixer. Please unmute all inputs and outputs before reporting a problem.

If you believe your device should be working, but for whatever reason isn't, then it's time for a little debugging. The following steps can determine if data is being processed by the DAC.

# cat > /dev/audio0 < /dev/zero &
[1] 9926
# audioctl play.{bytes,errors}
play.bytes=3312000
play.errors=0
# audioctl play.{bytes,errors}
play.bytes=7065600
play.errors=0
# audioctl play.{bytes,errors}
play.bytes=9379200
play.errors=0
# kill %1
# fg %1
cat > /dev/audio0 < /dev/zero
Terminated
Here we see that the processed data count play.bytes increases each time we check, so data is flowing. We also see that the device has not underrun any samples (play.errors). That's good too.

Note that even if you had speakers plugged in when running the above test, you should not have heard anything. The test sends zeros to the device, which is silence for all currently supported default encodings.

Since we know the device can process data, it's a good idea to check the mixer settings again. Make sure all outputs and all inputs are unmuted and are at a reasonable level.

If you are still having problems at this point, it's probably time to file a bug report. Besides the normal bug report information such as a full dmesg and description of the problem, please also include the default output of mixerctl -v and the output of the above test for DAC processing.

Using MIDI Instruments

The Musical Instrument Digital Interface (MIDI) protocol provides a standardized and efficient means to represent musical performance information as electronic data. MIDI data contains only instructions needed by a synthesizer to play the sounds, rather than the actual sounds.

To play MIDI data, a synthesizer connected to a MIDI port of the machine is required. Similarly, to record a MIDI data a MIDI instrument is required (such as a MIDI keyboard). Advanced MIDI instruments may contain multiple subparts (synthesizers, keyboards, control surfaces, etc...). They appear as multiple MIDI ports on OpenBSD.

When you already have OpenBSD running, look for MIDI ports in the output of the dmesg(8) command. An example of MIDI ports in a dmesg output is:

umidi0 at uhub2 port 2 configuration 1 interface 0 "Roland Roland XV-2020" rev 1.10/1.00 addr 2
midi0 at umidi0: <USB MIDI I/F>
umidi1 at uhub1 port 2 configuration 1 interface 1 "Evolution Electronics Ltd. USB Keystation 61es" rev 1.00/1.25 addr 3
midi1 at umidi1: <USB MIDI I/F>
It shows two midi(4) drivers attached, known by programs as: The output of the keyboard can be connected to the input of the synthesizer as follows:
$ midicat -q midi/0 -q midi/1
Now you can hear what you're playing on the MIDI keyboard on the synthesizer.

The sndiod(8) server exposes MIDI thru ports, allowing programs to send each other MIDI data. For instance, if you have no hardware synthesizer connected, you could start a software one (like the audio/fluidsynth port) and then use it as MIDI output:

$ midicat -q midi/0 -q midithru/0