summaryrefslogtreecommitdiff
path: root/src/mixer
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-01-03 16:53:06 -0500
committerAndrew Opalach <andrew@akon.city> 2025-01-03 16:53:06 -0500
commitd86e3f6dade53d5ca3b23a5c72c550b8f0583f91 (patch)
tree2452d09fda386a497a82eb120d8f36ac59dc912f /src/mixer
parent298debac881c1e7ca5e3a28834f32ff3e74e45f6 (diff)
downloadcamu-d86e3f6dade53d5ca3b23a5c72c550b8f0583f91.tar.gz
camu-d86e3f6dade53d5ca3b23a5c72c550b8f0583f91.tar.bz2
camu-d86e3f6dade53d5ca3b23a5c72c550b8f0583f91.zip
Audio buffer, mixer and sink improvements
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/mixer')
-rw-r--r--src/mixer/mixer.c18
-rw-r--r--src/mixer/mixer.h8
2 files changed, 21 insertions, 5 deletions
diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c
index 5a21b19..1360934 100644
--- a/src/mixer/mixer.c
+++ b/src/mixer/mixer.c
@@ -13,10 +13,12 @@ static s32 data_callback(void *userdata, u8 *data, s32 frame_count, bool *silenc
{
struct camu_mixer *mixer = (struct camu_mixer *)userdata;
size_t req = camu_audio_format_samples_to_bytes(&mixer->fmt.req, (size_t)frame_count);
+#ifdef CAMU_MIXER_THREADED_START_STOP
if (UNLIKELY(mixer->paused)) {
al_memset(data, 0, req);
*silence = MIXER_WANT_INITIAL_SILENCE;
} else {
+#endif
#ifdef CAMU_MIXER_THREADED
if (al_atomic_load(u8)(&mixer->queued, AL_ATOMIC_RELAXED)) {
camu_mixer_run_queue(mixer);
@@ -58,7 +60,9 @@ static s32 data_callback(void *userdata, u8 *data, s32 frame_count, bool *silenc
}
break;
}
+#ifdef CAMU_MIXER_THREADED_START_STOP
}
+#endif
return frame_count;
}
@@ -260,7 +264,7 @@ void camu_mixer_clear(struct camu_mixer *mixer)
void camu_mixer_pause(struct camu_mixer *mixer)
{
-#ifdef CAMU_MIXER_THREADED
+#ifdef CAMU_MIXER_THREADED_START_STOP
nn_mutex_lock(&mixer->mutex);
#endif
if (!mixer->paused) {
@@ -268,25 +272,29 @@ void camu_mixer_pause(struct camu_mixer *mixer)
mixer->paused = true;
}
#ifdef CAMU_MIXER_THREADED
+ // This assumes stop() blocks until the output actually stops.
+ // That may not be the behavior we want to require.
run_queue_internal(mixer);
+#endif
+#ifdef CAMU_MIXER_THREADED_START_STOP
nn_mutex_unlock(&mixer->mutex);
#endif
}
void camu_mixer_resume(struct camu_mixer *mixer)
{
-#ifdef CAMU_MIXER_THREADED
+#ifdef CAMU_MIXER_THREADED_START_STOP
nn_mutex_lock(&mixer->mutex);
#endif
if (mixer->paused) {
// start() can internally call data_callback once before returning.
- // In that call mixer->paused will still be true. So, we have a special case to
- // immediately return silence and avoid any possible locking.
+ // In that call mixer->paused will still be true. So, if MIXER_THREADED_START_STOP
+ // is defined, we have a special case to immediately return silence to avoid a deadlock.
// Outputs can treat that silence as part of the stream with MIXER_WANT_INITIAL_SILENCE.
mixer->audio->start(mixer->audio);
mixer->paused = false;
}
-#ifdef CAMU_MIXER_THREADED
+#ifdef CAMU_MIXER_THREADED_START_STOP
nn_mutex_unlock(&mixer->mutex);
#endif
}
diff --git a/src/mixer/mixer.h b/src/mixer/mixer.h
index 16ec924..802d1b5 100644
--- a/src/mixer/mixer.h
+++ b/src/mixer/mixer.h
@@ -9,6 +9,14 @@
#include "../codec/codec.h"
+#ifdef CAMU_MIXER_THREADED
+// Do we need to lock in order to synchronize the mixers paused state.
+// Disabling this is a very specific optimization to allow the audio device to
+// buffer data during start(). It requires pause(), resume(), and remove_buffer()
+// to all come from the same thread.
+//#define CAMU_MIXER_THREADED_START_STOP
+#endif
+
enum {
CAMU_MIXER_EMPTY = 0
};