00001 #include "device_oal.h"
00002 #include "threads.h"
00003
00004
00005 static const int BUFFER_COUNT = 4;
00006 static const int BUFFER_MILLISECONDS = 250;
00007
00008
00009 namespace audiere {
00010
00011 OALAudioDevice*
00012 OALAudioDevice::create(const ParameterList& parameters) {
00013
00014 ALCdevice* device = alcOpenDevice(0);
00015 if (!device) {
00016 return 0;
00017 }
00018
00019
00020 ALCcontext* context = alcCreateContext(device, 0);
00021 if (!context) {
00022 alcCloseDevice(device);
00023 return false;
00024 }
00025
00026 alcMakeContextCurrent(context);
00027
00028
00029 ALfloat position[] = { 0.0, 0.0, 0.0 };
00030 ALfloat velocity[] = { 0.0, 0.0, 0.0 };
00031 ALfloat orientation[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };
00032
00033
00034 bool success = false;
00035 alListenerfv(AL_POSITION, position);
00036 if (alGetError() == AL_NO_ERROR) {
00037 alListenerfv(AL_VELOCITY, velocity);
00038 if (alGetError() == AL_NO_ERROR) {
00039 alListenerfv(AL_ORIENTATION, orientation);
00040 if (alGetError() == AL_NO_ERROR) {
00041
00042
00043 alDistanceModel(AL_NONE);
00044 success = (alGetError() == AL_NO_ERROR);
00045
00046 }
00047 }
00048 }
00049
00050
00051 if (!success) {
00052 alcMakeContextCurrent(0);
00053 alcDestroyContext(context);
00054 alcCloseDevice(device);
00055 return 0;
00056 }
00057
00058 return new OALAudioDevice(device, context);
00059 }
00060
00061
00062 OALAudioDevice::OALAudioDevice(ALCdevice* device, ALCcontext* context) {
00063 m_device = device;
00064 m_context = context;
00065 }
00066
00067
00068 OALAudioDevice::~OALAudioDevice() {
00069 if (m_context) {
00070 alcMakeContextCurrent(0);
00071 alcDestroyContext(m_context);
00072 m_context = 0;
00073 }
00074
00075 if (m_device) {
00076 alcCloseDevice(m_device);
00077 m_device = 0;
00078 }
00079 }
00080
00081
00082 void
00083 OALAudioDevice::update() {
00084
00085 StreamList::iterator i = m_open_streams.begin();
00086 while (i != m_open_streams.end()) {
00087 OALOutputStream* s = *i++;
00088 s->update();
00089 }
00090 }
00091
00092
00093 OutputStream*
00094 OALAudioDevice::openStream(SampleSource* source) {
00095 if (!source) {
00096 return 0;
00097 }
00098
00099 int channel_count, sample_rate;
00100 SampleFormat sample_format;
00101 source->getFormat(channel_count, sample_rate, sample_format);
00102
00103
00104 ALenum format;
00105 if (channel_count == 1 && sample_format == SF_U8) {
00106 format = AL_FORMAT_MONO8;
00107 } else if (channel_count == 1 && sample_format == SF_S16) {
00108 format = AL_FORMAT_MONO16;
00109 } else if (channel_count == 2 && sample_format == SF_U8) {
00110 format = AL_FORMAT_STEREO8;
00111 } else if (channel_count == 2 && sample_format == SF_S16) {
00112 format = AL_FORMAT_STEREO16;
00113 } else {
00114 return 0;
00115 }
00116
00117
00118 ALuint* buffers = new ALuint[BUFFER_COUNT];
00119 alGenBuffers(BUFFER_COUNT, buffers);
00120 if (alGetError() != AL_NO_ERROR) {
00121 delete[] buffers;
00122 return NULL;
00123 }
00124
00125
00126
00127 ALuint al_source;
00128 alGenSources(1, &al_source);
00129 if (alGetError() != AL_NO_ERROR) {
00130 alDeleteBuffers(BUFFER_COUNT, buffers);
00131 delete[] buffers;
00132 return NULL;
00133 }
00134
00135 OALOutputStream* stream = new OALOutputStream(
00136 this,
00137 source,
00138 al_source,
00139 buffers,
00140 format,
00141 sample_rate);
00142 m_open_streams.push_back(stream);
00143 return stream;
00144 }
00145
00146
00147 OutputStream*
00148 OALAudioDevice::openBuffer(
00149 void* samples, int frame_count,
00150 int channel_count, int sample_rate, SampleFormat sample_format)
00151 {
00153 return 0;
00154 }
00155
00156
00157 void
00158 OALAudioDevice::removeStream(OALOutputStream* stream) {
00159 m_open_streams.remove(stream);
00160 }
00161
00162
00163 OALOutputStream::OALOutputStream(
00164 OALAudioDevice* device,
00165 SampleSource* source,
00166 ALuint al_source,
00167 ALuint* buffers,
00168 ALenum format,
00169 int sample_rate)
00170 {
00171 m_device = device;
00172
00173 m_source = source;
00174
00175 m_sample_rate = sample_rate;
00176 m_format = format;
00177 switch (format) {
00178 case AL_FORMAT_MONO8: m_sample_size = 1; break;
00179 case AL_FORMAT_MONO16: m_sample_size = 2; break;
00180 case AL_FORMAT_STEREO8: m_sample_size = 2; break;
00181 case AL_FORMAT_STEREO16: m_sample_size = 4; break;
00182 }
00183
00184 m_last_sample = new ALubyte[m_sample_size];
00185 memset(m_last_sample, 0, m_sample_size);
00186
00187 m_ALsource = al_source;
00188 m_buffers = buffers;
00189
00190 m_is_playing = false;
00191 m_volume = 1;
00192
00193
00194 m_buffer_length = BUFFER_MILLISECONDS * m_sample_rate / 1000;
00195
00196 fillBuffers();
00197
00198
00199 alSourceQueueBuffers(m_ALsource, BUFFER_COUNT, m_buffers);
00200 }
00201
00202
00203 OALOutputStream::~OALOutputStream() {
00204 m_device->removeStream(this);
00205
00206 alDeleteSources(1, &m_ALsource);
00207 alDeleteBuffers(BUFFER_COUNT, m_buffers);
00208 delete[] m_buffers;
00209 delete[] m_last_sample;
00210 }
00211
00212
00213 void
00214 OALOutputStream::update() {
00215
00216 ALint processed_buffers;
00217 #ifdef _WIN32 // XXX more OpenAL hacks
00218 alGetSourcei(m_ALsource, AL_BUFFERS_PROCESSED, &processed_buffers);
00219 #else
00220 alGetSourceiv(m_ALsource, AL_BUFFERS_PROCESSED, &processed_buffers);
00221 #endif
00222
00223
00224 if (processed_buffers == 0) {
00225 return;
00226 }
00227
00228 int read_size_samples = m_buffer_length;
00229 int read_size_bytes = read_size_samples * m_sample_size;
00230 ALubyte* sample_buffer = new ALubyte[read_size_bytes];
00231
00232 int buffer_length_bytes = read_size_bytes;
00233 while (processed_buffers--) {
00234
00235 if (read(sample_buffer, read_size_samples) == 0) {
00236 stop();
00237 break;
00238 }
00239
00240
00241 ALuint buffer;
00242 alSourceUnqueueBuffers(m_ALsource, 1, &buffer);
00243
00244 alBufferData(
00245 buffer,
00246 m_format,
00247 sample_buffer,
00248 buffer_length_bytes,
00249 m_sample_rate);
00250
00251 alSourceQueueBuffers(m_ALsource, 1, &buffer);
00252 }
00253
00254 delete[] sample_buffer;
00255
00256 AI_Sleep(50);
00257 }
00258
00259
00260 int
00261 OALOutputStream::read(void* samples, int sample_count) {
00262
00263 int samples_read = m_source->read(sample_count, samples);
00264
00265
00266 if (samples_read > 0) {
00267 memcpy(
00268 m_last_sample,
00269 (ALubyte*)samples + (samples_read - 1) * m_sample_size,
00270 m_sample_size);
00271 }
00272
00273
00274 ALubyte* out = (ALubyte*)samples + m_sample_size * samples_read;
00275 int c = sample_count - samples_read;
00276 while (c--) {
00277 memcpy(out, m_last_sample, m_sample_size);
00278 out += m_sample_size;
00279 }
00280
00281 return samples_read;
00282 }
00283
00284
00285 void
00286 OALOutputStream::fillBuffers() {
00287 int samples_to_read = m_buffer_length * BUFFER_COUNT;
00288 int allocate = samples_to_read * m_sample_size;
00289 ALubyte* sample_buffer = new ALubyte[allocate];
00290 read(sample_buffer, samples_to_read);
00291
00292 for (int i = 0; i < BUFFER_COUNT; i++) {
00293 alBufferData(
00294 m_buffers[i],
00295 m_format,
00296 sample_buffer + i * m_buffer_length * m_sample_size,
00297 m_buffer_length * m_sample_size,
00298 m_sample_rate);
00299 }
00300
00301 delete[] sample_buffer;
00302 }
00303
00304
00305 void
00306 OALOutputStream::play() {
00307 alSourcePlay(m_ALsource);
00308 m_is_playing = true;
00309 }
00310
00311
00312 void
00313 OALOutputStream::stop() {
00314 alSourcePause(m_ALsource);
00315 m_is_playing = false;
00316 }
00317
00318
00319 bool
00320 OALOutputStream::isPlaying() {
00321 return m_is_playing;
00322 }
00323
00324
00325 void
00326 OALOutputStream::reset() {
00327 bool is_playing = isPlaying();
00328 if (is_playing) {
00329 stop();
00330 }
00331
00332
00333
00334 if (is_playing) {
00335 play();
00336 }
00337 }
00338
00339
00340 void
00341 OALOutputStream::setRepeat(bool repeat) {
00343 }
00344
00345
00346 bool
00347 OALOutputStream::getRepeat() {
00349 return false;
00350 }
00351
00352
00353 void
00354 OALOutputStream::setVolume(float volume) {
00355 m_volume = volume;
00356 alSourcef(m_ALsource, AL_GAIN, volume);
00357 }
00358
00359
00360 float
00361 OALOutputStream::getVolume() {
00362 return m_volume;
00363 }
00364
00365
00366 void
00367 OALOutputStream::setPan(float pan) {
00369 }
00370
00371
00372 float
00373 OALOutputStream::getPan() {
00375 return 0.0f;
00376 }
00377
00378
00379 void
00380 OALOutputStream::setPitchShift(float shift) {
00382 }
00383
00384
00385 float
00386 OALOutputStream::getPitchShift() {
00388 return 0;
00389 }
00390
00391
00392 bool
00393 OALOutputStream::isSeekable() {
00395 return false;
00396 }
00397
00398
00399 int
00400 OALOutputStream::getLength() {
00402 return 0;
00403 }
00404
00405
00406 void
00407 OALOutputStream::setPosition(int ) {
00409 }
00410
00411
00412 int
00413 OALOutputStream::getPosition() {
00415 return 0;
00416 }
00417
00418 }