5
#include <emscripten.h>
9
#include "../system/include/AL/al.h"
10
#include "../system/include/AL/alc.h"
14
#define BUFFER_SIZE 1470*10
16
ALCdevice* device = NULL;
17
ALCcontext* context = NULL;
19
// Audio source state.
20
unsigned char* data = NULL;
21
unsigned int size = 0;
22
unsigned int offset = 0;
23
unsigned int channels = 0;
24
unsigned int frequency = 0;
25
unsigned int bits = 0;
29
void iter(void *arg) {
31
ALint buffersProcessed = 0;
32
ALint buffersWereQueued = 0;
33
ALint buffersQueued = 0;
36
alGetSourcei(source, AL_BUFFERS_PROCESSED, &buffersProcessed);
38
while (offset < size && buffersProcessed--) {
39
// unqueue the old buffer and validate the queue length
40
alGetSourcei(source, AL_BUFFERS_QUEUED, &buffersWereQueued);
41
alSourceUnqueueBuffers(source, 1, &buffer);
43
assert(alGetError() == AL_NO_ERROR);
44
int len = size - offset;
45
if (len > BUFFER_SIZE) {
49
alGetSourcei(source, AL_BUFFERS_QUEUED, &buffersQueued);
50
assert(buffersQueued == buffersWereQueued - 1);
52
// queue the new buffer and validate the queue length
53
buffersWereQueued = buffersQueued;
54
alBufferData(buffer, format, &data[offset], len, frequency);
56
alSourceQueueBuffers(source, 1, &buffer);
57
assert(alGetError() == AL_NO_ERROR);
59
alGetSourcei(source, AL_BUFFERS_QUEUED, &buffersQueued);
60
assert(buffersQueued == buffersWereQueued + 1);
62
// make sure it's still playing
63
alGetSourcei(source, AL_SOURCE_STATE, &state);
64
assert(state == AL_PLAYING);
69
// Exit once we've processed the entire clip.
79
int main(int argc, char* argv[]) {
81
// Setup the AL context.
83
device = alcOpenDevice(NULL);
84
context = alcCreateContext(device, NULL);
85
alcMakeContextCurrent(context);
88
// Read in the audio sample.
91
FILE* fp = fopen("the_entertainer.wav", "rb");
93
FILE* fp = fopen("sounds/the_entertainer.wav", "rb");
95
fseek(fp, 0, SEEK_END);
97
fseek(fp, 0, SEEK_SET);
99
data = (unsigned char*)malloc(size);
100
fread(data, size, 1, fp);
103
offset = 12; // ignore the RIFF header
104
offset += 8; // ignore the fmt header
105
offset += 2; // ignore the format type
107
channels = data[offset + 1] << 8;
108
channels |= data[offset];
110
printf("Channels: %u\n", channels);
112
frequency = data[offset + 3] << 24;
113
frequency |= data[offset + 2] << 16;
114
frequency |= data[offset + 1] << 8;
115
frequency |= data[offset];
117
printf("Frequency: %u\n", frequency);
119
offset += 6; // ignore block size and bps
121
bits = data[offset + 1] << 8;
122
bits |= data[offset];
124
printf("Bits: %u\n", bits);
129
format = AL_FORMAT_MONO8;
130
} else if (channels == 2) {
131
format = AL_FORMAT_STEREO8;
133
} else if (bits == 16) {
135
format = AL_FORMAT_MONO16;
136
} else if (channels == 2) {
137
format = AL_FORMAT_STEREO16;
140
offset += 8; // ignore the data chunk
143
// Seed the buffers with some initial data.
145
ALuint buffers[NUM_BUFFERS];
146
alGenBuffers(NUM_BUFFERS, buffers);
147
alGenSources(1, &source);
149
ALint numBuffers = 0;
150
while (numBuffers < NUM_BUFFERS && offset < size) {
151
int len = size - offset;
152
if (len > BUFFER_SIZE) {
156
alBufferData(buffers[numBuffers], format, &data[offset], len, frequency);
157
alSourceQueueBuffers(source, 1, &buffers[numBuffers]);
158
assert(alGetError() == AL_NO_ERROR);
165
// Start playing the source.
167
alSourcePlay(source);
170
alGetSourcei(source, AL_SOURCE_STATE, &state);
171
assert(state == AL_PLAYING);
173
alGetSourcei(source, AL_BUFFERS_QUEUED, &numBuffers);
174
assert(numBuffers == NUM_BUFFERS);
177
// Cycle and refill the buffers until we're done.
180
emscripten_set_main_loop(iter, 0, 0);