99 lines
2.4 KiB
C
99 lines
2.4 KiB
C
#include "./mixer.h"
|
|
|
|
#include <assert.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "thirdparty/miniaudio/miniaudio.h"
|
|
|
|
#include "util/container/array.h"
|
|
#include "util/memory/memory.h"
|
|
|
|
#include "./effect.h"
|
|
|
|
struct jukebox_mixer_t {
|
|
ma_device device;
|
|
|
|
jukebox_format_t format;
|
|
|
|
size_t effects_reserved;
|
|
size_t effects_length;
|
|
jukebox_effect_t* effects[1];
|
|
};
|
|
|
|
static void jukebox_mixer_device_callback_(
|
|
ma_device* device, void* out, const void* in, ma_uint32 frames) {
|
|
assert(device != NULL);
|
|
assert(out != NULL);
|
|
assert(frames > 0);
|
|
|
|
jukebox_mixer_t* mixer = (typeof(mixer)) device->pUserData;
|
|
assert(mixer != NULL);
|
|
|
|
const jukebox_effect_pcm_t pcm = {
|
|
.ptr = out,
|
|
.frames = frames,
|
|
};
|
|
for (size_t i = 0; i < mixer->effects_length; ++i) {
|
|
jukebox_effect_affect(mixer->effects[i], &pcm);
|
|
}
|
|
|
|
(void) in;
|
|
}
|
|
|
|
jukebox_mixer_t* jukebox_mixer_new(
|
|
const jukebox_format_t* format, size_t reserve) {
|
|
assert(jukebox_format_valid(format));
|
|
assert(reserve > 0);
|
|
|
|
jukebox_mixer_t* mixer = memory_new(
|
|
sizeof(*mixer) + (reserve-1)*sizeof(mixer->effects[0]));
|
|
*mixer = (typeof(*mixer)) {
|
|
.format = *format,
|
|
.effects_reserved = reserve,
|
|
};
|
|
|
|
ma_device_config config = ma_device_config_init(ma_device_type_playback);
|
|
config.playback.format = ma_format_f32;
|
|
config.playback.channels = mixer->format.channels;
|
|
config.sampleRate = mixer->format.sample_rate;
|
|
config.dataCallback = jukebox_mixer_device_callback_;
|
|
config.pUserData = mixer;
|
|
|
|
if (ma_device_init(NULL, &config, &mixer->device) != MA_SUCCESS) {
|
|
fprintf(stderr, "failed to open audio device\n");
|
|
abort();
|
|
}
|
|
|
|
if (ma_device_start(&mixer->device) != MA_SUCCESS) {
|
|
fprintf(stderr, "failed to start audio device\n");
|
|
ma_device_uninit(&mixer->device);
|
|
abort();
|
|
}
|
|
|
|
return mixer;
|
|
}
|
|
|
|
void jukebox_mixer_delete(jukebox_mixer_t* mixer) {
|
|
if (mixer == NULL) return;
|
|
|
|
ma_device_uninit(&mixer->device);
|
|
|
|
memory_delete(mixer);
|
|
}
|
|
|
|
void jukebox_mixer_add_effect(
|
|
jukebox_mixer_t* mixer, jukebox_effect_t* effect) {
|
|
assert(mixer != NULL);
|
|
assert(effect != NULL);
|
|
|
|
ma_mutex_lock(&mixer->device.lock);
|
|
if (mixer->effects_length >= mixer->effects_reserved) {
|
|
fprintf(stderr, "mixer effects overflow\n");
|
|
abort();
|
|
}
|
|
mixer->effects[mixer->effects_length++] = effect;
|
|
ma_mutex_unlock(&mixer->device.lock);
|
|
}
|