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