File: test_openal_buffers.c

package info (click to toggle)
emscripten 3.1.69%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 121,872 kB
  • sloc: ansic: 636,110; cpp: 425,974; javascript: 78,401; python: 58,404; sh: 49,154; pascal: 5,237; makefile: 3,365; asm: 2,415; lisp: 1,869
file content (225 lines) | stat: -rw-r--r-- 5,649 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
 * Copyright 2013 The Emscripten Authors.  All rights reserved.
 * Emscripten is available under two separate licenses, the MIT license and the
 * University of Illinois/NCSA Open Source License.  Both these licenses can be
 * found in the LICENSE file.
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <AL/al.h>
#include <AL/alc.h>
#else
#include "../system/include/AL/al.h"
#include "../system/include/AL/alc.h"
#endif

#define NUM_BUFFERS 4
#define BUFFER_SIZE 1470*10

ALCdevice* device = NULL;
ALCcontext* context = NULL;

// Audio source state.
unsigned char* data = NULL;
unsigned int size = 0;
unsigned int offset = 0;
unsigned int channels = 0;
unsigned int frequency = 0;
unsigned int bits = 0;
ALenum format = 0;
ALuint source = 0;
#ifdef TEST_ANIMATED_PITCH
// When testing animated pitch, start testing at a high pitch, and scale smaller.
float pitch = 1.3f;
#else
// When not testing animating the pitch value, play back at a slow rate.
float pitch = 0.5f;
#endif

void iter() {
  ALuint buffer = 0;
  ALint buffersProcessed = 0;
  ALint buffersWereQueued = 0;
  ALint buffersQueued = 0;
  ALint state;
  float testPitch;

  alGetSourcei(source, AL_BUFFERS_PROCESSED, &buffersProcessed);

  while (offset < size && buffersProcessed--) {
    // unqueue the old buffer and validate the queue length
    alGetSourcei(source, AL_BUFFERS_QUEUED, &buffersWereQueued);
    alSourceUnqueueBuffers(source, 1, &buffer);

    assert(alGetError() == AL_NO_ERROR);
    int len = size - offset;
    if (len > BUFFER_SIZE) {
      len = BUFFER_SIZE;
    }

    alGetSourcei(source, AL_BUFFERS_QUEUED, &buffersQueued);
    assert(buffersQueued == buffersWereQueued - 1);

    // queue the new buffer and validate the queue length
    buffersWereQueued = buffersQueued;
    alBufferData(buffer, format, &data[offset], len, frequency);

    alSourceQueueBuffers(source, 1, &buffer);
    assert(alGetError() == AL_NO_ERROR);

    alGetSourcei(source, AL_BUFFERS_QUEUED, &buffersQueued);
    assert(buffersQueued == buffersWereQueued + 1);

    // make sure it's still playing
    alGetSourcei(source, AL_SOURCE_STATE, &state);
    assert(state == AL_PLAYING);

    offset += len;
  }

#ifdef TEST_ANIMATED_PITCH
  pitch *= .999;
  if (pitch < 0.5f)
    pitch = 0.5f;
  alSourcef(source, AL_PITCH, pitch);
  alGetSourcef(source, AL_PITCH, &testPitch);
  assert(pitch == testPitch);
#endif

  // Exit once we've processed the entire clip.
  if (offset >= size) {
#if __EMSCRIPTEN__
    emscripten_cancel_main_loop();
#endif
    exit(0);
  }
}

int main(int argc, char* argv[]) {
  float testPitch;
  //
  // Setup the AL context.
  //
  device = alcOpenDevice(NULL);
  context = alcCreateContext(device, NULL);
  alcMakeContextCurrent(context);

  //
  // Read in the audio sample.
  //
#ifdef __EMSCRIPTEN__
  FILE* fp = fopen("the_entertainer.wav", "rb");
#else
  FILE* fp = fopen("sounds/the_entertainer.wav", "rb");
#endif
  fseek(fp, 0, SEEK_END);
  size = ftell(fp);
  fseek(fp, 0, SEEK_SET);

  data = (unsigned char*)malloc(size);
  fread(data, size, 1, fp);
  fclose(fp);

  offset = 12; // ignore the RIFF header
  offset += 8; // ignore the fmt header
  offset += 2; // ignore the format type

  channels = data[offset + 1] << 8;
  channels |= data[offset];
  offset += 2;
  printf("Channels: %u\n", channels);

  frequency = data[offset + 3] << 24;
  frequency |= data[offset + 2] << 16;
  frequency |= data[offset + 1] << 8;
  frequency |= data[offset];
  offset += 4;
  printf("Frequency: %u\n", frequency);

  offset += 6; // ignore block size and bps

  bits = data[offset + 1] << 8;
  bits |= data[offset];
  offset += 2;
  printf("Bits: %u\n", bits);

  format = 0;
  if (bits == 8) {
    if (channels == 1) {
      format = AL_FORMAT_MONO8;
    } else if (channels == 2) {
      format = AL_FORMAT_STEREO8;
    }
  } else if (bits == 16) {
    if (channels == 1) {
      format = AL_FORMAT_MONO16;
    } else if (channels == 2) {
      format = AL_FORMAT_STEREO16;
    }
  }
  offset += 8; // ignore the data chunk

  //
  // Seed the buffers with some initial data.
  //
  ALuint buffers[NUM_BUFFERS];
  alGenBuffers(NUM_BUFFERS, buffers);
  alGenSources(1, &source);

  alSourcef(source, AL_PITCH, pitch);
  alGetSourcef(source, AL_PITCH, &testPitch);
  assert(pitch == testPitch);

  ALint numBuffers = 0;
  while (numBuffers < NUM_BUFFERS && offset < size) {
    int len = size - offset;
    if (len > BUFFER_SIZE) {
      len = BUFFER_SIZE;
    }

    alBufferData(buffers[numBuffers], format, &data[offset], len, frequency);
    alSourceQueueBuffers(source, 1, &buffers[numBuffers]);
    assert(alGetError() == AL_NO_ERROR);

    offset += len;
    numBuffers++;
  }

  ALint srcLen = 0;
  alGetSourcei(source, 0x2009 /* AL_BYTE_LENGTH_SOFT */, &srcLen);
  assert(srcLen == NUM_BUFFERS * BUFFER_SIZE);

#ifdef TEST_ANIMATED_PITCH
  printf("You should hear a clip of the 1902 piano song \"The Entertainer\" played back at a high pitch rate, and animated to slow down to half playback speed.\n");
#else
  printf("You should hear a clip of the 1902 piano song \"The Entertainer\" played back at half speed.\n");
#endif

  //
  // Start playing the source.
  //
  alSourcePlay(source);

  ALint state;
  alGetSourcei(source, AL_SOURCE_STATE, &state);
  assert(state == AL_PLAYING);

  alGetSourcei(source, AL_BUFFERS_QUEUED, &numBuffers);
  assert(numBuffers == NUM_BUFFERS);

  //
  // Cycle and refill the buffers until we're done.
  //
#ifdef __EMSCRIPTEN__
  emscripten_set_main_loop(iter, 0, 0);
#else
  while (1) {
    iter();
    usleep(16);
  }
#endif
}