TransWikia.com

How to play more than one stream at once using soundio?

Stack Overflow Asked by 010110110101 on January 3, 2021

I’m new to soundio. I’m wondering how to play more than one audio source at once.

I’m looking to understand if I’m supposed to create several streams (seems wrong) and let the operating system do the mixing, or am I supposed to implement software mixing?

Software mixing seems tough too if my input sources are operating at different frequencies.

Am I basically asking "how to mix audio"?

I need a little direction.

Here’s my use-case:

I have 5 different MP3 files. One is background music and the other 4 are sound effects. I want to start the background music and then play the sound effects as the user does something (such as click a graphical button). (This is for a game)

One Answer

You can create multiple streams and play them simultaneously. You don't need to do the mixing yourself. Anyway, it needs a lot of work.

Define WAVE_INFO and PLAYBACK_INFO:

struct WAVE_INFO
{
    SoundIoFormat format;
    std::vector<unsigned char*> data;
    int frames; // number of frames in this clip
}

struct PLAYBACK_INFO
{
    const WAVE_INFO* wave_info; // information of sound clip
    int progress; // number of frames already played
}
  1. Extract WAVE info out of sound clips and store them in an array of WAVE_INFO: std::vector<WAVE_INFO> waves_;. This vector is not going to change after being initialized.
  2. When you want to play waves_[index]:
SoundIoOutStream* outstream = soundio_outstream_create(sound_device_);
outstream->write_callback = write_callback;
PlayBackInfo* playback_info = new PlayBackInfo({&waves_[index], 0});
outstream->format = playback_info->wave_info->format;
outstream->userdata = playback_info;
soundio_outstream_open(outstream);
soundio_outstream_start(outstream);
std::thread stopper([this, outstream]()
{
    PlayBackInfo* playback_info = (PlayBackInfo*)outstream->userdata;
    while (playback_info->progress != playback_info->wave_info->frames)
    {
        soundio_wait_events(soundio_);
    }
    soundio_outstream_destroy(outstream);
    delete playback_info;
});
stopper.detach();
  1. In write_callback function:
PlayBackInfo* playback_info = (PlayBackInfo*)outstream->userdata;
int frames_left = playback_info->audio_info->frames - playback_info->progress;
if (frames_left == 0)
{
    soundio_wakeup(Window::window_->soundio_);
    return;
}
if (frames_left > frame_count_max)
{
    frames_left = frame_count_max;
}
// fill the buffer using
// soundio_outstream_begin_write and
// soundio_outstream_end_write by
// data in playback_info->wave_info.data
// considering playback_info->progress.

// update playback_info->progress based on
// number of frames are written to buffer

// for background music:
if (playback_info->audio_info->frames == playback_info->progress)
{
    // if application has not exited:
    playback_info->progress = 0;
}

Also this solution works, it needs lots of improvements. Please consider it as a POC only.

Answered by Null on January 3, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP