Start spatialization and data conversion systems;

This commit is contained in:
bjorn 2020-05-21 14:06:10 -06:00 committed by Bjorn
parent 40cffbe590
commit 121a4f7108
3 changed files with 90 additions and 32 deletions

View File

@ -1,21 +1,38 @@
#include "audio/audio.h"
#include "data/soundData.h"
#include "core/arr.h"
#include "core/ref.h"
#include "core/ref.h"
#include "core/util.h"
#include <string.h>
#include <stdlib.h>
#include "lib/miniaudio/miniaudio.h"
#define SAMPLE_RATE 44100
static const ma_format formats[] = {
[SAMPLE_I16] = ma_format_s16,
[SAMPLE_F32] = ma_format_f32
};
struct Source {
Source* next;
SoundData* sound;
ma_data_converter* converter;
uint32_t offset;
float volume;
bool tracked;
bool playing;
bool looping;
bool tracked;
bool spatial;
};
typedef struct {
bool (*init)(void);
void (*destroy)(void);
void (*apply)(Source* source, const void* input, float* output, uint32_t frames);
} Spatializer;
static struct {
bool initialized;
ma_context context;
@ -23,13 +40,19 @@ static struct {
ma_device devices[2];
ma_mutex locks[2];
Source* sources;
arr_t(ma_data_converter) converters;
Spatializer* spatializer;
} state;
static void onPlayback(ma_device* device, void* output, const void* input, uint32_t frames) {
// Device callbacks
static void onPlayback(ma_device* device, void* output, const void* _, uint32_t frames) {
ma_mutex_lock(&state.locks[0]);
float buffer[1024];
size_t stride = sizeof(buffer) / 2 / sizeof(float);
float rawBuffer[1024];
float mixBuffer[1024];
size_t stride = sizeof(rawBuffer) / 2 / sizeof(float);
for (Source** list = &state.sources, *source = *list; source != NULL; source = *list) {
if (!source->playing) {
@ -41,11 +64,13 @@ static void onPlayback(ma_device* device, void* output, const void* input, uint3
for (uint32_t f = 0; f < frames; f += stride) {
uint32_t count = MIN(stride, frames - f);
uint32_t n = source->sound->read(source->sound, source->offset, count, buffer);
uint32_t n = source->sound->read(source->sound, source->offset, count, rawBuffer);
memcpy(mixBuffer, rawBuffer, count * stride);
float* p = (float*) output + f * 2;
for (uint32_t i = 0; i < n * 2; i++) {
p[i] += buffer[i] * source->volume;
p[i] += mixBuffer[i] * source->volume;
}
if (n < count) {
@ -72,6 +97,26 @@ static void onCapture(ma_device* device, void* output, const void* input, uint32
static const ma_device_callback_proc callbacks[] = { onPlayback, onCapture };
// Spatializers
static bool phonon_init(void) {
return false;
}
static void phonon_destroy(void) {
//
}
static void phonon_apply(Source* source, const void* input, float* output, uint32_t frames) {
//
}
static Spatializer spatializers[] = {
{ phonon_init, phonon_destroy, phonon_apply }
};
// Entry
bool lovrAudioInit(AudioConfig config[2]) {
if (state.initialized) return false;
@ -99,6 +144,15 @@ bool lovrAudioInit(AudioConfig config[2]) {
}
}
for (size_t i = 0; i < sizeof(spatializers) / sizeof(spatializers[0]); i++) {
if (spatializers[i].init()) {
state.spatializer = &spatializers[i];
break;
}
}
arr_init(&state.converters);
return state.initialized = true;
}
@ -109,6 +163,8 @@ void lovrAudioDestroy() {
ma_mutex_uninit(&state.locks[0]);
ma_mutex_uninit(&state.locks[1]);
ma_context_uninit(&state.context);
if (state.spatializer) state.spatializer->destroy();
arr_free(&state.converters);
memset(&state, 0, sizeof(state));
}
@ -118,8 +174,11 @@ bool lovrAudioReset() {
ma_device_type deviceType = (i == 0) ? ma_device_type_playback : ma_device_type_capture;
ma_device_config config = ma_device_config_init(deviceType);
config.sampleRate = SAMPLE_RATE;
config.playback.format = ma_format_f32;
config.capture.format = ma_format_f32;
config.playback.channels = 2;
config.capture.channels = 1;
config.dataCallback = callbacks[i];
if (ma_device_init(&state.context, &config, &state.devices[i])) {
@ -156,6 +215,31 @@ Source* lovrSourceCreate(SoundData* sound) {
source->sound = sound;
lovrRetain(source->sound);
source->volume = 1.f;
for (size_t i = 0; i < state.converters.length; i++) {
ma_data_converter* converter = &state.converters.data[i];
if (converter->config.formatIn != formats[source->sound->format]) continue;
if (converter->config.sampleRateIn != source->sound->sampleRate) continue;
if (converter->config.channelsIn != source->sound->channels) continue;
if (converter->config.channelsOut != (2 >> source->spatial)) continue;
source->converter = converter;
break;
}
if (!source->converter) {
ma_data_converter_config config = ma_data_converter_config_init_default();
config.formatIn = formats[source->sound->format];
config.formatOut = ma_format_f32;
config.channelsIn = source->sound->channels;
config.channelsOut = 2 >> source->spatial;
config.sampleRateIn = source->sound->sampleRate;
config.sampleRateOut = SAMPLE_RATE;
arr_expand(&state.converters, 1);
ma_data_converter* converter = &state.converters.data[state.converters.length++];
lovrAssert(!ma_data_converter_init(&config, converter), "Problem creating Source data converter");
source->converter = converter;
}
return source;
}

View File

@ -1,11 +0,0 @@
#include <stdbool.h>
#include <stdint.h>
#pragma once
typedef struct {
bool (*init)(void);
void (*apply)(const float* input, float* output, uint32_t frames, float* transform);
} Spatializer;
extern Spatializer lovrSteamAudioSpatializer;

View File

@ -1,15 +0,0 @@
#include "spatializer.h"
#include <phonon.h>
static bool steamaudio_init() {
return false;
}
static void steamaudio_apply(const float* input, float* output, uint32_t frames, float* transform) {
//
}
Spatializer lovrSteamAudioSpatializer = {
.init = steamaudio_init,
.apply = steamaudio_apply
};