On Thu, May 19, 2022 at 07:43:22AM +0200, Tru Hobbyist wrote: > Hi all, > > I was tinkering with sndio on a fresh OpenBSD 7.1 install and tried to use the > synchronous mode by using a simple application that opens a handle (sio_open()) > with both SIO_PLAY and SIO_REC modes set (mode = SIO_PLAY | SIO_REC). > > >From the documentation: it should now be possible to record from the > microphone and get this recording immediately output through my > speakers, pseudo-simultaneously. > > Problem is, it does not work. The symptoms are: it freezes at sio_psleep() and > nothing happens. > > The same setup (OS, microphone, speakers) works correctly when used in either > SIO_PLAY or SIO_REC mode. I have also tried to record first and then playback > the recorded data (using two sio_open(), sio_start(), sio_read/write(), ... > sio_stop(), sio_close() sequences) in the same program. Works flawlessly. > > What am I doing wrong? > Hi, I'm can't tell for sure without looking at the code, but most probably there's a deadlock: recording direction waits play direction to be ready to start, but play direction can't start as there are no recorded samples to play (yet). Playback and recording always start simultaneously and stay synchronized. But in order to start, the device's play buffer must be full (there must be something to play to start playback). This pseudo-code is deadlock-free: hdl = sio_open(..., SIO_PLAY | SIO_REC, 0); sio_initpar(&par); ... sio_setpar(hdl, &par); ... sio_getpar(hdl, &par); /* * send a full buffer of silence for device to start */ sio_write(hdl, silence, par.bufsz * par.pchan * par.bps); while (1) { /* * record a single block, we need the loop because * sio_read() use Unix read() semantics and may * return short reads */ todo = par.round * par.rchan * par.bps; data = rec_buf; while (todo > 0) n = sio_read(hdl, data, todo); data += n; todo -= n; } /* * do some processing (ex. just copy rec->play * assuming the same number of channels) */ memcpy(play_buf, rec_buf, par.round * par.rchan * par.bps); /* * sio_write() blocks until full block is sent */ sio_write(hdl, play_buf, par.round * par.pchan * par.bps); } This is how a programs to apply effects would work. The latency is: par.bufsz / par.rate which lower bound is a fixed system parameter (170ms in current defaults). If you need to lower latency further, use sndiod -b option to set it to a value suitable for your system. Last note: play and rec direction always stay in sync and recover after underruns. The synchronous mode (aka SIO_SYNC) is not useful here and may create problems. HTH, -- AlexandreReceived on Thu May 19 2022 - 09:50:48 CEST
This archive was generated by hypermail 2.3.0 : Tue Aug 09 2022 - 16:23:51 CEST