119 lines
2.6 KiB
C
119 lines
2.6 KiB
C
|
#include <AL/al.h>
|
||
|
#include <AL/alc.h>
|
||
|
#include <assert.h>
|
||
|
#include <emscripten.h>
|
||
|
#include <kinc/audio2/audio.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
static kinc_a2_buffer_t a2_buffer;
|
||
|
|
||
|
static ALCdevice *device = NULL;
|
||
|
static ALCcontext *context = NULL;
|
||
|
static unsigned int channels = 0;
|
||
|
static unsigned int bits = 0;
|
||
|
static ALenum format = 0;
|
||
|
static ALuint source = 0;
|
||
|
|
||
|
static bool audioRunning = false;
|
||
|
#define BUFSIZE 4096
|
||
|
static short buf[BUFSIZE];
|
||
|
#define NUM_BUFFERS 3
|
||
|
|
||
|
static uint32_t samples_per_second = 44100;
|
||
|
|
||
|
static void copySample(void *buffer) {
|
||
|
float left_value = *(float *)&a2_buffer.channels[0][a2_buffer.read_location];
|
||
|
float right_value = *(float *)&a2_buffer.channels[1][a2_buffer.read_location];
|
||
|
a2_buffer.read_location += 1;
|
||
|
if (a2_buffer.read_location >= a2_buffer.data_size) {
|
||
|
a2_buffer.read_location = 0;
|
||
|
}
|
||
|
((int16_t *)buffer)[0] = (int16_t)(left_value * 32767);
|
||
|
((int16_t *)buffer)[1] = (int16_t)(right_value * 32767);
|
||
|
}
|
||
|
|
||
|
static void streamBuffer(ALuint buffer) {
|
||
|
if (kinc_a2_internal_callback(&a2_buffer, BUFSIZE / 2)) {
|
||
|
for (int i = 0; i < BUFSIZE; i += 2) {
|
||
|
copySample(&buf[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
alBufferData(buffer, format, buf, BUFSIZE * 2, samples_per_second);
|
||
|
}
|
||
|
|
||
|
static void iter() {
|
||
|
if (!audioRunning) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ALint processed;
|
||
|
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
||
|
|
||
|
if (processed <= 0) {
|
||
|
return;
|
||
|
}
|
||
|
while (processed--) {
|
||
|
ALuint buffer;
|
||
|
alSourceUnqueueBuffers(source, 1, &buffer);
|
||
|
streamBuffer(buffer);
|
||
|
alSourceQueueBuffers(source, 1, &buffer);
|
||
|
}
|
||
|
|
||
|
ALint playing;
|
||
|
alGetSourcei(source, AL_SOURCE_STATE, &playing);
|
||
|
if (playing != AL_PLAYING) {
|
||
|
alSourcePlay(source);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool a2_initialized = false;
|
||
|
|
||
|
void kinc_a2_init() {
|
||
|
if (a2_initialized) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
kinc_a2_internal_init();
|
||
|
a2_initialized = true;
|
||
|
|
||
|
a2_buffer.read_location = 0;
|
||
|
a2_buffer.write_location = 0;
|
||
|
a2_buffer.data_size = 128 * 1024;
|
||
|
a2_buffer.channel_count = 2;
|
||
|
a2_buffer.channels[0] = (float*)malloc(a2_buffer.data_size * sizeof(float));
|
||
|
a2_buffer.channels[1] = (float*)malloc(a2_buffer.data_size * sizeof(float));
|
||
|
|
||
|
audioRunning = true;
|
||
|
|
||
|
device = alcOpenDevice(NULL);
|
||
|
context = alcCreateContext(device, NULL);
|
||
|
alcMakeContextCurrent(context);
|
||
|
format = AL_FORMAT_STEREO16;
|
||
|
|
||
|
ALuint buffers[NUM_BUFFERS];
|
||
|
alGenBuffers(NUM_BUFFERS, buffers);
|
||
|
alGenSources(1, &source);
|
||
|
|
||
|
streamBuffer(buffers[0]);
|
||
|
streamBuffer(buffers[1]);
|
||
|
streamBuffer(buffers[2]);
|
||
|
|
||
|
alSourceQueueBuffers(source, NUM_BUFFERS, buffers);
|
||
|
|
||
|
alSourcePlay(source);
|
||
|
}
|
||
|
|
||
|
void kinc_a2_update() {
|
||
|
iter();
|
||
|
}
|
||
|
|
||
|
void kinc_a2_shutdown() {
|
||
|
audioRunning = false;
|
||
|
}
|
||
|
|
||
|
uint32_t kinc_a2_samples_per_second(void) {
|
||
|
return samples_per_second;
|
||
|
}
|