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