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