On Fri, Jun 05, 2026 at 04:09:53PM -0400, Paul Wisehart wrote:
> Hi!,
>
> I am working on a curses C sndio app to
> play samples that are just wav files.
> I would like to be able to play them
> "over each other" like not sequentially.
>
> (I would like for the wav file to play
> regardless if another one is already playing.)
>
> I can play ONE wav file using sndio.
>
> https://codeberg.org/pkw/siotest/src/branch/main/siotest.c#L130
>
> What is the easiest and most idiomatic way
> to play multiples ones ?
>
> My naive approach is to just do the same thing
> as I would do for one and put that into
> a pthread. That means I am opening the
> sndio device each time. (sio_open)
That would work for 2-3 files, but would consume a lot of resources
and the offset between the files is difficult to control.
>
> I see in game programming people do "mixing"
> of sound.
>
This is the most flexible approach, imo. In a loop "pull" a block of
data and send it to the device. In pseudo-code:
while (1) {
for (f = file_list; f != NULL; f = f->next) {
read_samples(f, tmp_buf, par.round);
mix_samples(out_buf, tmp_buf, par.round);
}
sio_write(hdl, out_buf, par.round * par.pchan * par.bps);
}
If all files use the same format, the code can be small and
simple. Mixing is roughly adding the samples. It's even simpler if
they are small and are pre-loaded in memory.
Above approach can be extended naturally, ex. if conversions or
effects are necessary, they can be hidden in read_file(). If low
latency is needed, the file-system calls could go in a dedicated
thread, etc.
> Any pointers or places to look?
>
The playrec_cycle() function in src/usr.bin/aucat/aucat.c does this,
you can ignore the recording part and the conversions. Many programs
do something equivalent, so pick the one that's the most readable for
you.
> I want to use just OpenBSD and sndio if possible.
> I am using libsndfile, but that is just to
> open the wav files easily.
>