Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
SIO_OPEN(3)		 BSD Library Functions Manual		   SIO_OPEN(3)

NAME
     sio_open, sio_close, sio_setpar, sio_getpar, sio_getcap, sio_start,
     sio_stop, sio_read, sio_write, sio_onmove,	sio_nfds, sio_pollfd,
     sio_revents, sio_eof, sio_setvol, sio_onvol, sio_initpar -- sndio inter-
     face to audio devices

SYNOPSIS
     #include <sndio.h>

     struct sio_hdl *
     sio_open(const char *name,	unsigned int mode, int nbio_flag);

     void
     sio_close(struct sio_hdl *hdl);

     int
     sio_setpar(struct sio_hdl *hdl, struct sio_par *par);

     int
     sio_getpar(struct sio_hdl *hdl, struct sio_par *par);

     int
     sio_getcap(struct sio_hdl *hdl, struct sio_cap *cap);

     int
     sio_start(struct sio_hdl *hdl);

     int
     sio_stop(struct sio_hdl *hdl);

     size_t
     sio_read(struct sio_hdl *hdl, void	*addr, size_t nbytes);

     size_t
     sio_write(struct sio_hdl *hdl, const void *addr, size_t nbytes);

     void
     sio_onmove(struct sio_hdl *hdl, void (*cb)(void *arg, int delta),
	 void *arg);

     int
     sio_nfds(struct sio_hdl *hdl);

     int
     sio_pollfd(struct sio_hdl *hdl, struct pollfd *pfd, int events);

     int
     sio_revents(struct	sio_hdl	*hdl, struct pollfd *pfd);

     int
     sio_eof(struct sio_hdl *hdl);

     int
     sio_setvol(struct sio_hdl *hdl, unsigned int vol);

     int
     sio_onvol(struct sio_hdl *hdl, void (*cb)(void *arg, unsigned int vol),
	 void *arg);

     void
     sio_initpar(struct	sio_par	*par);

DESCRIPTION
     The sndio library allows user processes to	access audio(4)	hardware and
     the sndiod(8) audio server	in a uniform way.

   Opening and closing an audio	device
     First the application must	call the sio_open() function to	obtain a han-
     dle to the	device;	later it will be passed	as the hdl argument of most
     other functions.  The name	parameter gives	the device string discussed in
     sndio(7).	In most	cases it should	be set to SIO_DEVANY to	allow the user
     to	select it using	the AUDIODEVICE	environment variable.

     The following values of the mode parameter	are supported:

     SIO_PLAY		 Play-only mode: data written will be played by	the
			 device.

     SIO_REC		 Record-only mode: samples are recorded	by the device
			 and must be read.

     SIO_PLAY |	SIO_REC	 The device plays and records synchronously; this
			 means that the	n-th recorded sample was physically
			 sampled exactly when the n-th played sample was actu-
			 ally played.

     If	the nbio_flag argument is true (i.e. non-zero),	then the sio_read()
     and sio_write() functions (see below) will	be non-blocking.

     The sio_close() function stops the	device as if sio_stop()	is called and
     frees the handle.	Thus, no samples submitted with	sio_write() are	dis-
     carded.

   Negotiating audio parameters
     Audio samples are interleaved.  A frame consists of one sample for	each
     channel.  For example, a 16-bit stereo encoding has two samples per frame
     and, two bytes per	sample (thus 4 bytes per frame).

     The set of	parameters of the device that can be controlled	is given by
     the following structure:

     struct sio_par {
	     unsigned int bits;	     /*	bits per sample	*/
	     unsigned int bps;	     /*	bytes per sample */
	     unsigned int sig;	     /*	1 = signed, 0 =	unsigned int */
	     unsigned int le;	     /*	1 = LE,	0 = BE byte order */
	     unsigned int msb;	     /*	1 = MSB, 0 = LSB aligned */
	     unsigned int rchan;     /*	number channels	for recording */
	     unsigned int pchan;     /*	number channels	for playback */
	     unsigned int rate;	     /*	frames per second */
	     unsigned int appbufsz;  /*	minimum	buffer size without xruns */
	     unsigned int bufsz;     /*	end-to-end buffer size (read-only) */
	     unsigned int round;     /*	optimal	buffer size divisor */
     #define SIO_IGNORE	     0	     /*	pause during xrun */
     #define SIO_SYNC	     1	     /*	resync after xrun */
     #define SIO_ERROR	     2	     /*	terminate on xrun */
	     unsigned int xrun;	     /*	what to	do on overrun/underrun */
     };

     The parameters are	as follows:

     bits      Number of bits per sample: must be between 1 and	32.

     bps       Bytes per samples; if specified,	it must	be large enough	to
	       hold all	bits.  By default it's set to the smallest power of
	       two large enough	to hold	bits.

     sig       If set (i.e. non-zero) then the samples are signed, else	un-
	       signed.

     le	       If set, then the	byte order is little endian, else big endian;
	       it's meaningful only if bps > 1.

     msb       If set, then the	bits are aligned in the	packet to the most
	       significant bit (i.e. lower bits	are padded), else to the least
	       significant bit (i.e. higher bits are padded); it's meaningful
	       only if bits < bps * 8.

     rchan     The number of recorded channels;	meaningful only	if SIO_REC
	       mode was	selected.

     pchan     The number of played channels; meaningful only if SIO_PLAY mode
	       was selected.

     rate      The sampling frequency in Hz.

     bufsz     The maximum number of frames that may be	buffered.  This	param-
	       eter takes into account any buffers, and	can be used for	la-
	       tency calculations.  It is read-only.

     appbufsz  Size of the buffer in frames the	application must maintain non-
	       empty (on the play end) or non-full (on the record end) by
	       calling sio_write() or sio_read() fast enough to	avoid overrun
	       or underrun conditions.	The audio subsystem may	use additional
	       buffering, thus this parameter cannot be	used for latency cal-
	       culations.

     round     Optimal number of frames	that the application buffers should be
	       a multiple of, to get best performance.	Applications can use
	       this parameter to round their block size.

     xrun      The action when the client doesn't accept recorded data or
	       doesn't provide data to play fast enough; it can	be set to one
	       of the SIO_IGNORE, SIO_SYNC, or SIO_ERROR constants.

     The following approach is recommended to negotiate	device parameters:

     +o	 Initialize a sio_par structure	using sio_initpar() and	fill it	with
	 the desired parameters.  Then call sio_setpar() to request the	device
	 to use	them.  Parameters left unset in	the sio_par structure will be
	 set to	device-specific	defaults.

     +o	 Call sio_getpar() to retrieve the actual parameters of	the device and
	 check that they are usable.  If they are not, then fail or set	up a
	 conversion layer.  Sometimes the rate set can be slightly different
	 to what was requested.	 A difference of about 0.5% is not audible and
	 should	be ignored.

     Parameters	cannot be changed after	sio_start() has	been called,
     sio_stop()	must be	called before parameters can be	changed.

     If	the device is exposed by the sndiod(8) server, which is	the default
     configuration, a transparent emulation layer will automatically be	set
     up, and in	this case any combination of rate, encoding and	numbers	of
     channels is supported.

     To	ease filling the sio_par structure, the	following macros can be	used:

     SIO_BPS(bits)  Return the smallest	value for bps that is a	power of two
		    and	that is	large enough to	hold bits.

     SIO_LE_NATIVE  Can	be used	to set the le parameter	when native byte order
		    is required.

   Getting device capabilities
     There's no	way to get an exhaustive list of all parameter combinations
     the device	supports.  Applications	that need to have a set	of working pa-
     rameter combinations in advance can use the sio_getcap() function.

     The sio_cap structure contains the	list of	parameter configurations.
     Each configuration	contains multiple parameter sets.  The application
     must examine all configurations, and choose its parameter set from	one of
     the configurations.  Parameters of	different configurations are not us-
     able together.

     struct sio_cap {
	     struct sio_enc {		     /*	allowed	encodings */
		     unsigned int bits;
		     unsigned int bps;
		     unsigned int sig;
		     unsigned int le;
		     unsigned int msb;
	     } enc[SIO_NENC];
	     unsigned int rchan[SIO_NCHAN];  /*	allowed	rchans */
	     unsigned int pchan[SIO_NCHAN];  /*	allowed	pchans */
	     unsigned int rate[SIO_NRATE];   /*	allowed	rates */
	     unsigned int nconf;	     /*	num. of	confs[]	*/
	     struct sio_conf {
		     unsigned int enc;	     /*	bitmask	of enc[] indexes */
		     unsigned int rchan;     /*	bitmask	of rchan[] indexes */
		     unsigned int pchan;     /*	bitmask	of pchan[] indexes */
		     unsigned int rate;	     /*	bitmask	of rate[] indexes */
	     } confs[SIO_NCONF];
     };

     The parameters are	as follows:

     enc[SIO_NENC]     Array of	supported encodings.  The tuple	of bits, bps,
		       sig, le,	and msb	parameters are usable in the corre-
		       sponding	parameters of the sio_par structure.

     rchan[SIO_NCHAN]  Array of	supported channel numbers for recording	usable
		       in the sio_par structure.

     pchan[SIO_NCHAN]  Array of	supported channel numbers for playback usable
		       in the sio_par structure.

     rate[SIO_NRATE]   Array of	supported sample rates usable in the sio_par
		       structure.

     nconf	       Number of different configurations available, i.e. num-
		       ber of filled elements of the confs[] array.

     confs[SIO_NCONF]  Array of	available configurations.  Each	configuration
		       contains	bitmasks indicating which elements of the
		       above parameter arrays are valid	for the	given configu-
		       ration.	For instance, if the second bit	of rate	is
		       set, in the sio_conf structure, then the	second element
		       of the rate[SIO_NRATE] array of the sio_cap structure
		       is valid	for this configuration.

   Starting and	stopping the device
     The sio_start() function puts the device in a waiting state: the device
     will wait for playback data to be provided	(using the sio_write() func-
     tion).  Once enough data is queued	to ensure that play buffers will not
     underrun, actual playback is started automatically.  If record mode only
     is	selected, then recording starts	immediately.  In full-duplex mode,
     playback and recording will start synchronously as	soon as	enough data to
     play is available.

     The sio_stop() function puts the audio subsystem in the same state	as be-
     fore sio_start() is called.  It stops recording, drains the play buffer
     and then stops playback.  If samples to play are queued but playback
     hasn't started yet	then playback is forced	immediately; playback will ac-
     tually stop once the buffer is drained.  In no case are samples in	the
     play buffer discarded.

   Playing and recording
     When record mode is selected, the sio_read() function must	be called to
     retrieve recorded data; it	must be	called often enough to ensure that in-
     ternal buffers will not overrun.  It will store at	most nbytes bytes at
     the addr location and return the number of	bytes stored.  Unless the
     nbio_flag flag is set, it will block until	data becomes available and
     will return zero only on error.

     Similarly,	when play mode is selected, the	sio_write() function must be
     called to provide data to play.  Unless the nbio_flag is set, sio_write()
     will block	until the requested amount of data is written.

   Non-blocking	mode operation
     If	the nbio_flag is set on	sio_open(), then the sio_read()	and
     sio_write() functions will	never block; if	no data	is available, they
     will return zero immediately.

     The poll(2) system	call can be used to check if data can be read from or
     written to	the device.  The sio_pollfd() function fills the array pfd of
     pollfd structures,	used by	poll(2), with events; the latter is a bit-mask
     of	POLLIN and POLLOUT constants; refer to poll(2) for more	details.
     sio_pollfd() returns the number of	pollfd structures filled.  The
     sio_revents() function returns the	bit-mask set by	poll(2)	in the pfd ar-
     ray of pollfd structures.	If POLLIN is set, recorded samples are avail-
     able in the device	buffer and can be read with sio_read().	 If POLLOUT is
     set, space	is available in	the device buffer and new samples to play can
     be	submitted with sio_write().  POLLHUP may be set	if an error occurs,
     even if it	is not selected	with sio_pollfd().

     The sio_nfds() function returns the number	of pollfd structures the
     caller must preallocate in	order to be sure that sio_pollfd() will	never
     overrun.

   Synchronizing non-audio events to the audio stream in real-time
     In	order to perform actions at precise positions of the audio stream,
     such as displaying	video in sync with the audio stream, the application
     must be notified in real-time of the exact	position in the	stream the
     hardware is processing.

     The sio_onmove() function can be used to register the cb()	callback func-
     tion called at regular time intervals.  The delta argument	contains the
     number of frames the hardware played and/or recorded since	the last call
     of	cb().  It is called by sio_read(), sio_write(),	and sio_revents().
     When the first sample is played and/or recorded, right after the device
     starts, the callback is invoked with a zero delta argument.  The value of
     the arg pointer is	passed to the callback and can contain anything.

     If	desired, the application can maintain the current position by starting
     from zero (when sio_start() is called) and	adding to the current position
     delta every time cb() is called.

   Measuring the latency and buffers usage
     The playback latency is the delay it will take for	the frame just written
     to	become audible,	expressed in number of frames.	The exact playback la-
     tency can be obtained by subtracting the current position from the	number
     of	frames written.	 Once playback is actually started (first sample audi-
     ble) the latency will never exceed	the bufsz parameter (see the sections
     above).  There's a	phase during which sio_write() only queues data; once
     there's enough data, actual playback starts.  During this phase talking
     about latency is meaningless.

     In	any cases, at most bufsz frames	are buffered.  This value takes	into
     account all buffers.  The number of frames	stored is equal	to the number
     of	frames written minus the current position.

     The recording latency is obtained similarly, by subtracting the number of
     frames read from the current position.

     Note that sio_write() might block even if there is	buffer space left; us-
     ing the buffer usage to guess if sio_write() would	block is false and
     leads to unreliable programs - consider using poll(2) for this.

   Handling buffer overruns and	underruns
     When the application cannot accept	recorded data fast enough, the record
     buffer (of	size appbufsz) might overrun; in this case recorded data is
     lost.  Similarly if the application cannot	provide	data to	play fast
     enough, the play buffer underruns and silence is played instead.  Depend-
     ing on the	xrun parameter of the sio_par structure, the audio subsystem
     will behave as follows:

     SIO_IGNORE	 The devices pauses during overruns and	underruns, thus	the
		 current position (obtained through sio_onmove()) stops	being
		 incremented.  Once the	overrun	and/or underrun	condition is
		 gone, the device resumes; play	and record are always kept in
		 sync.	With this mode,	the application	cannot notice under-
		 runs and/or overruns and shouldn't care about them.

		 This mode is the default.  It's suitable for applications,
		 like audio players and	telephony, where time is not important
		 and overruns or underruns are not short.

     SIO_SYNC	 If the	play buffer underruns, then silence is played, but in
		 order to reach	the right position in time, the	same amount of
		 written samples will be discarded once	the application	is un-
		 blocked.  Similarly, if the record buffer overruns, then sam-
		 ples are discarded, but the same amount of silence will be
		 returned later.  The current position (obtained through
		 sio_onmove()) is still	incremented.  When the play buffer un-
		 derruns the play latency might	become negative; when the
		 record	buffer overruns, the record latency might become
		 larger	than bufsz.

		 This mode is suitable for applications, like music produc-
		 tion, where time is important and where underruns or overruns
		 are short and rare.

     SIO_ERROR	 With this mode, on the	first play buffer underrun or record
		 buffer	overrun, playback and/or recording is terminated and
		 no other function than	sio_close() will succeed.

		 This mode is mostly useful for	testing.

   Controlling the volume
     The sio_setvol() function can be used to set playback attenuation.	 The
     vol parameter takes a value between 0 (maximum attenuation) and
     SIO_MAXVOL	(no attenuation).  It specifies	the weight the audio subsystem
     will give to this stream.	It is not meant	to control hardware parameters
     like speaker gain;	the mixerctl(1)	interface should be used for that pur-
     pose instead.

     An	application can	use the	sio_onvol() function to	register a callback
     function that will	be called each time the	volume is changed, including
     when sio_setvol() is used.	 The callback is always	invoked	when
     sio_onvol() is called in order to provide the initial volume.  An appli-
     cation can	safely assume that once	sio_onvol() has	returned a non-zero
     value, the	callback has been invoked and thus the current volume is
     available.	 If there's no volume setting available, sio_onvol() returns 0
     and the callback is never invoked and calls to sio_setvol() are ignored.

     The sio_onvol() function can be called with a NULL	argument to check
     whether a volume knob is available.

   Error handling
     Errors related to the audio subsystem (like hardware errors, dropped con-
     nections) and programming errors (e.g. call to sio_read() on a play-only
     stream) are considered fatal.  Once an error occurs, all functions	taking
     a sio_hdl argument, except	sio_close() and	sio_eof(), stop	working	(i.e.
     always return 0).

     The sio_eof() function can	be used	at any stage; it returns 0 if there's
     no	pending	error, and a non-zero value if there's an error.

RETURN VALUES
     The sio_open() function returns the newly created handle on success or
     NULL on failure.  The sio_setpar(), sio_getpar(), sio_getcap(),
     sio_start(), sio_stop(), sio_pollfd(), and	sio_setvol() functions return
     1 on success and 0	on failure.  The sio_read() and	sio_write() functions
     return the	number of bytes	transferred.

ENVIRONMENT
     AUDIODEVICE     Device to use if sio_open() is called with	SIO_DEVANY as
		     the name argument.
     SNDIO_DEBUG     The debug level: may be a value between 0 and 2.

SEE ALSO
     audio(4), sndio(7), sndiod(8), audio(9)

BUGS
     The audio(4) driver doesn't drain playback	buffers, thus if sndio is used
     to	directly access	an audio(4) device, the	sio_stop() function will stop
     playback immediately.

     If	the application	doesn't	consume	recorded data fast enough then
     "control messages"	from the sndiod(8) server are delayed and consequently
     sio_onmove() callback or volume changes may be delayed.

     The sio_open(), sio_setpar(), sio_getpar(), sio_getcap(), sio_start(),
     and sio_stop() functions may block	for a very short period	of time, thus
     they should be avoided in code sections where blocking is not desirable.

BSD				 April 6, 2020				   BSD

NAME | SYNOPSIS | DESCRIPTION | RETURN VALUES | ENVIRONMENT | SEE ALSO | BUGS

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=sio_open&sektion=3&manpath=FreeBSD+12.1-RELEASE+and+Ports>

home | help