NameDateSize

..01-May-202440

basic.cH A D29-Jun-20232.7 KiB

midi.cH A D14-Feb-20242.4 KiB

ossinit.hH A D14-Feb-20247.8 KiB

ossmidi.hH A D14-Feb-20241.9 KiB

READMEH A D04-Aug-20213.2 KiB

README

1Briefly summarised, a general audio application will:
2- open(2)
3- ioctl(2)
4- read(2)
5- write(2)
6- close(2)
7
8In this example, read/write will be called in a loop for a duration of
9record/playback. Usually, /dev/dsp is the device you want to open, but it can
10be any OSS compatible device, even user space one created with virtual_oss. For
11configuring sample rate, bit depth and all other configuring of the device
12ioctl is used. As devices can support multiple sample rates and formats, what
13specific application should do in case there's an error issuing ioctl, as not
14all errors are fatal, is upon the developer to decide. As a general guideline
15Official OSS development howto should be used. FreeBSD OSS and virtual_oss are
16different to a small degree.
17
18For more advanced OSS and real-time applications, developers need to handle
19buffers more carefully. The size of the buffer in OSS is selected using fragment
20size size_selector and the buffer size is 2^size_selector for values between 4
21and 16. The formula on the official site is:
22
23int frag = (max_fragments << 16) | (size_selector);
24ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag);
25
26The max_fragments determines in how many fragments the buffer will be, hence if
27the size_selector is 4, the requested size is 2^4 = 16 and for the
28max_fragments of 2, the total buffer size will be
29
30(2 ^ size_selector) * max_fragments
31
32or in this case 32 bytes. Please note that size of buffer is in bytes not
33samples. For example, 24bit sample will be represented with 3 bytes. If you're
34porting audio app from Linux, you should be aware that 24 bit samples are
35represented with 4 bytes (usually int).
36
37FreeBSD kernel will round up max_fragments and size of fragment/buffer, so the
38last thing any OSS code should do is get info about buffer with audio_buf_info
39and SNDCTL_DSP_GETOSPACE. That also means that not all values of max_fragments
40are permitted.
41
42From kernel perspective, there are few points OSS developers should be aware of:
43- There is a software facing buffer (bs) and a hardware driver buffer (b)
44- The sizes can be seen with cat /dev/sndstat as [b:_/_/_] [bs:_/_/_] (needed:
45  sysctl hw.snd.verbose=2)
46- OSS ioctl only concern software buffer fragments, not hardware
47
48For USB the block size is according to hw.usb.uaudio.buffer_ms sysctl, meaning
492ms at 48kHz gives 0.002 * 48000 = 96 samples per block, all multiples of this
50work well. Block size for virtual_oss, if used, should be set accordingly.
51
52OSS driver insists on reading / writing a certain number of samples at a time,
53one fragment full of samples. It is bound to do so in a fixed time frame, to
54avoid under- and overruns in communication with the hardware.
55
56The idea of a total buffer size that holds max_fragments fragments is to give
57some slack and allow application to be about max_fragments - 1 fragments late.
58Let's call this the jitter tolerance. The jitter tolerance may be much less if
59there is a slight mismatch between the period and the samples per fragment.
60
61Jitter tolerance gets better if we can make either the period or the samples
62per fragment considerably smaller than the other. In our case that means we
63divide the total buffer size into smaller fragments, keeping overall latency at
64the same level.
65
66Official OSS development howto: http://manuals.opensound.com/developer/DSP.html
67