pcm_mixer: implement mixer_switch_sink

Change-Id: I1549470774f96a6f470817cbc5fe4611812de6fa
This commit is contained in:
mojyack 2026-03-31 11:52:43 +09:00
parent be4b0591ee
commit 9ffc8a00ce
2 changed files with 68 additions and 47 deletions

View file

@ -23,6 +23,7 @@
#define PCM_MIXER_H #define PCM_MIXER_H
#include <sys/types.h> #include <sys/types.h>
#include "pcm_sink.h"
/** Simple config **/ /** Simple config **/
@ -111,6 +112,9 @@ void mixer_channel_play_pause(enum pcm_mixer_channel channel, bool play);
/* Stop playback on a channel */ /* Stop playback on a channel */
void mixer_channel_stop(enum pcm_mixer_channel channel); void mixer_channel_stop(enum pcm_mixer_channel channel);
/* Switch playback sink */
bool mixer_switch_sink(enum pcm_sink_ids sink);
/* Set channel's amplitude factor */ /* Set channel's amplitude factor */
void mixer_channel_set_amplitude(enum pcm_mixer_channel channel, void mixer_channel_set_amplitude(enum pcm_mixer_channel channel,
unsigned int amplitude); unsigned int amplitude);

View file

@ -286,6 +286,56 @@ static void mixer_start_pcm(void)
start, mix_frame_size); start, mix_frame_size);
} }
/* Notify users of samplerate change */
static void mixer_handle_sampr_change(unsigned int sampr)
{
for (size_t i = 0; i < ARRAYLEN(active_channels) && active_channels[i]; i += 1)
{
struct mixer_channel* chan = active_channels[i];
/* Notify upstreams */
if (chan->play_cbs)
{
if (chan->play_cbs->sampr_changed)
{
chan->play_cbs->sampr_changed(sampr);
}
if (chan->play_cbs->get_more)
{
/* Remake buffer */
const void *start = NULL;
size_t size;
chan->play_cbs->get_more(&start, &size);
if (start && size) {
chan->start = start;
chan->size = size;
chan->last_size = 0;
} else {
channel_stopped(chan);
}
}
}
/* Notify buffer monitor */
if (chan->buf_cbs)
{
if (chan->buf_cbs->sampr_changed)
{
chan->buf_cbs->sampr_changed(sampr);
}
}
}
/* Work out how much space we really need */
if (sampr > SAMPR_96)
mix_frame_size = 4;
else if (sampr > SAMPR_48)
mix_frame_size = 2;
else
mix_frame_size = 1;
mix_frame_size *= MIX_FRAME_SAMPLES * 4;
}
/** Public interfaces **/ /** Public interfaces **/
/* Start playback on a channel */ /* Start playback on a channel */
@ -371,6 +421,19 @@ void mixer_channel_stop(enum pcm_mixer_channel channel)
pcm_play_unlock(); pcm_play_unlock();
} }
/* Switch playback sink */
bool mixer_switch_sink(enum pcm_sink_ids sink)
{
if(pcm_current_sink() == sink)
return true;
if(!pcm_switch_sink(sink))
return false;
mixer_handle_sampr_change(SAMPR_NUM(pcm_get_frequency()));
return true;
}
/* Set channel's amplitude factor */ /* Set channel's amplitude factor */
void mixer_channel_set_amplitude(enum pcm_mixer_channel channel, void mixer_channel_set_amplitude(enum pcm_mixer_channel channel,
unsigned int amplitude) unsigned int amplitude)
@ -461,53 +524,7 @@ void mixer_set_frequency(unsigned int samplerate)
return; return;
pcm_set_frequency(samplerate); pcm_set_frequency(samplerate);
mixer_handle_sampr_change(SAMPR_NUM(pcm_get_frequency()));
for (size_t i = 0; i < ARRAYLEN(active_channels) && active_channels[i]; i += 1)
{
struct mixer_channel* chan = active_channels[i];
/* Notify upstreams */
if (chan->play_cbs)
{
if (chan->play_cbs->sampr_changed)
{
chan->play_cbs->sampr_changed(SAMPR_NUM(samplerate));
}
if (chan->play_cbs->get_more)
{
/* Remake buffer */
const void *start = NULL;
size_t size;
chan->play_cbs->get_more(&start, &size);
if (start && size) {
chan->start = start;
chan->size = size;
chan->last_size = 0;
} else {
channel_stopped(chan);
}
}
}
/* Notify buffer monitor */
if (chan->buf_cbs)
{
if (chan->buf_cbs->sampr_changed)
{
chan->buf_cbs->sampr_changed(SAMPR_NUM(samplerate));
}
}
}
/* Work out how much space we really need */
if (SAMPR_NUM(samplerate) > SAMPR_96)
mix_frame_size = 4;
else if (SAMPR_NUM(samplerate) > SAMPR_48)
mix_frame_size = 2;
else
mix_frame_size = 1;
mix_frame_size *= MIX_FRAME_SAMPLES * 4;
if (pcm_is_initialized()) if (pcm_is_initialized())
pcm_apply_settings(); pcm_apply_settings();
} }