#pragma once #include #include #include #ifdef CAMU_MIXER_THREADED #include #endif #include "../codec/codec.h" #ifdef CAMU_MIXER_THREADED // Do we need a 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 }; struct camu_mixer { struct camu_audio *audio; f32 volume; struct camu_resampler_format fmt; atomic(bool) paused; u8 empty_after; array(struct camu_audio_buffer *) buffers; #ifdef CAMU_MIXER_THREADED array(struct camu_audio_buffer *) add_queue; array(struct camu_audio_buffer *) rem_queue; atomic(bool) queued; struct nn_mutex mutex; #endif void (*callback)(void *, u8); void *userdata; }; bool camu_mixer_init(struct camu_mixer *mixer, struct camu_audio *audio); void camu_mixer_pick_format(struct camu_mixer *mixer, struct camu_resampler_format *fmt); void camu_mixer_set_volume(struct camu_mixer *mixer, f32 volume); f32 camu_mixer_offset_volume(struct camu_mixer *mixer, f32 amount); f64 camu_mixer_get_latency(struct camu_mixer *mixer); void camu_mixer_add_buffer(struct camu_mixer *mixer, struct camu_audio_buffer *buf); void camu_mixer_remove_buffer(struct camu_mixer *mixer, struct camu_audio_buffer *buf); #ifdef CAMU_MIXER_THREADED void camu_mixer_run_queue(struct camu_mixer *mixer); void camu_mixer_clear(struct camu_mixer *mixer); #endif void camu_mixer_pause(struct camu_mixer *mixer); void camu_mixer_resume(struct camu_mixer *mixer); void camu_mixer_close(struct camu_mixer *mixer);