00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifdef _WIN32
00033 #include <windows.h>
00034 #endif
00035
00036 #include <iostream>
00037 #include <vector>
00038 #include <string>
00039
00040 #include <AL/al.h>
00041 #include <AL/alc.h>
00042 #include <AL/alut.h>
00043
00044
00045
00046 #include "syn/Util/AudioFormat.h"
00047 #include "syn/Stream/AudioContext.h"
00048 #include "syn/Stream/AudioOStream.h"
00049 #include "syn/Stream/OpenALAudioOStream.h"
00050
00051 namespace syn
00052 {
00053 OpenALAudioOStream::OpenALAudioOStream() :
00054 mFormat( AL_FORMAT_STEREO16 ),
00055 mIsOpen( false ),
00056 mBufferHackSwitch( 0 ),
00057 mPcount( 0 )
00058 {
00059
00060 mBuffers.resize( 2 );
00061 mSources.resize( 1 );
00062 }
00063
00064 bool OpenALAudioOStream::isPlaying() const
00065 {
00066
00067 if (alIsSource(mSources[0]) == AL_FALSE)
00068 {
00069 return AL_FALSE;
00070 }
00071
00072 ALint source_state = AL_INITIAL;
00073 # ifdef WIN32
00074 alGetSourcei( mSources[0], AL_SOURCE_STATE, &source_state );
00075 # else
00076 alGetSourceiv( mSources[0], AL_SOURCE_STATE, &source_state );
00077 # endif
00078
00079 switch (source_state)
00080 {
00081 case AL_PLAYING:
00082 case AL_PAUSED:
00083 return true;
00084 default:
00085 break;
00086 }
00087
00088 return false;
00089 }
00090
00091
00092 void OpenALAudioOStream::flush()
00093 {
00094
00095 while (this->isPlaying())
00096 {
00097
00098 }
00099 }
00100
00101
00102
00103 bool OpenALAudioOStream::open( const syn::AudioFormat& fmt )
00104 {
00105 if (mIsOpen == true)
00106 {
00107 this->close();
00108 }
00109
00110 ALint error;
00111
00112
00113
00114 mSampRate = fmt.samplingRateHz;
00115 switch (fmt.datatype)
00116 {
00117 case syn::AudioFormat::UNSIGNED8:
00118 std::cout << "[syn] WARNING: UNSIGNED8 unsupported."
00119 << "Could not not open stream\n" << std::flush;
00120 return false;
00121 case syn::AudioFormat::SIGNED8:
00122 if (fmt.channels == 1)
00123 mFormat = AL_FORMAT_MONO8;
00124 else if (fmt.channels == 2)
00125 mFormat = AL_FORMAT_STEREO8;
00126 else
00127 {
00128 std::cout << "[syn] WARNING: Only 1 or 2 channels unsupported. "
00129 << "Could not not open stream\n" << std::flush;
00130 return false;
00131 }
00132 break;
00133 case syn::AudioFormat::UNSIGNED16:
00134 std::cout << "[syn] WARNING: UNSIGNED16 unsupported. "
00135 << "Could not not open stream\n" << std::flush;
00136 return false;
00137 case syn::AudioFormat::SIGNED16:
00138 if (fmt.channels == 1)
00139 mFormat = AL_FORMAT_MONO16;
00140 else if (fmt.channels == 2)
00141 mFormat = AL_FORMAT_STEREO16;
00142 else
00143 {
00144 std::cout << "[syn] WARNING: Only 1 or 2 channels unsupported. "
00145 << "Could not not open stream\n" << std::flush;
00146 return false;
00147 }
00148 break;
00149 case syn::AudioFormat::FLOAT32:
00150 std::cout << "[syn] WARNING: FLOAT32 unsupported."
00151 << "Could not not open stream\n" << std::flush;
00152 return false;
00153 }
00154
00155
00156
00157 alGenBuffers( mBuffers.size(), &mBuffers.front() );
00158 if ((error = alGetError()) != AL_NO_ERROR)
00159 {
00160 std::cout << "alGenBuffers : " << error << "\n" << std::flush;
00161 return false;
00162 }
00163
00164
00165 std::vector<char> junk;
00166 junk.resize( 1024 );
00167 for (unsigned int x = 0; x < mBuffers.size(); x++)
00168 {
00169 alBufferData( mBuffers[x], mFormat, &junk[0],
00170 junk.size(), mSampRate);
00171 if ((error = alGetError()) != AL_NO_ERROR)
00172 std::cout << "[syn] ERROR: alBufferData : " << error << "\n" << std::flush;
00173 }
00174
00175
00176
00177
00178 alGenSources( 1, &mSources[0] );
00179 if ((error = alGetError()) != AL_NO_ERROR)
00180 {
00181 std::cout << "[syn] ERROR: alGenSources 1 : " << error << "\n" << std::flush;
00182 alDeleteBuffers( mBuffers.size(), &mBuffers[0] );
00183 return false;
00184 }
00185
00186
00187 alSourceQueueBuffers( mSources[0], mBuffers.size(), &mBuffers[0] );
00188 if ((error = alGetError()) != AL_NO_ERROR)
00189 std::cout << "[syn] ERROR: alSourceQueueBuffers : " << error << "\n" << std::flush;
00190 mBufferHackSwitch = mBuffers[0];
00191
00192
00193 alSourcei( mSources[0], AL_LOOPING, AL_FALSE );
00194
00195
00196 alSourcePlay( mSources[0] );
00197 if ((error = alGetError()) != AL_NO_ERROR)
00198 std::cout << "[syn] ERROR: alSourcePlay source 0 : " << error << "\n" << std::flush;
00199
00200 mFmt = fmt;
00201 mIsOpen = true;
00202 return true;
00203 }
00204
00205
00206
00207
00208
00209
00210 bool OpenALAudioOStream::canAcceptMoreData() const
00211 {
00212 if (mIsOpen == false)
00213 return false;
00214
00215 if (alIsSource( mSources[0] ) == AL_FALSE)
00216 return false;
00217
00218 if (this->isPlaying() == false)
00219 {
00220
00221
00222
00223
00224
00225
00226 return true;
00227 }
00228
00229 ALuint buffers_processed;
00230 # ifdef WIN32
00231 alGetSourcei( mSources[0], AL_BUFFERS_PROCESSED,
00232 (int*)&buffers_processed );
00233 # else
00234 alGetSourceiv( mSources[0], AL_BUFFERS_PROCESSED,
00235 (int*)&buffers_processed );
00236 # endif
00237
00238
00239
00240
00241
00242
00243 if (buffers_processed >= 1)
00244 return true;
00245 else
00246 return false;
00247 }
00248
00249
00250
00251 bool OpenALAudioOStream::write( const void* const data, int samples )
00252 {
00253 int numBytes = samples * mFmt.sampsize();
00254 mPcount = samples;
00255
00256 if (mIsOpen == false)
00257 return false;
00258
00259
00260
00261
00262
00263 ALint error;
00264
00265
00266
00267 if (this->canAcceptMoreData() == true)
00268 {
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 ALuint buffer_id = 0;
00284
00285 #ifdef UNIX_STREAMING_BUG
00286
00287
00288
00289 buffer_id = mBufferHackSwitch;
00290 alSourceUnqueueBuffers( mSources[0], 1, &buffer_id );
00291 if ((error = alGetError()) != AL_NO_ERROR)
00292 {
00293 std::cout << "[syn] ERROR: alSourceUnqueueBuffers: "
00294 << error << " " << alGetString( error )
00295 << "\n" << std::flush;
00296
00297 return false;
00298 }
00299
00300
00301 if (mBufferHackSwitch == mBuffers[0])
00302 mBufferHackSwitch = mBuffers[1];
00303 else
00304 mBufferHackSwitch = mBuffers[0];
00305 #else // ifndef UNIX_STREAMING_BUG
00306
00307
00308 alSourceUnqueueBuffers( mSources[0], 1, &buffer_id );
00309 if ((error = alGetError()) != AL_NO_ERROR)
00310 {
00311 std::cout << "[syn] ERROR: alSourceUnqueueBuffers 1 : "
00312 << error << " " << alGetString( error ) << "\n"
00313 << std::flush;
00314 return false;
00315 }
00316 #endif // UNIX_STREAMING_BUG
00317
00318
00319
00320
00321 alBufferData( buffer_id, mFormat, const_cast<void*>( data ), numBytes, mSampRate );
00322 if ((error = alGetError()) != AL_NO_ERROR)
00323 {
00324 std::cout << "[syn] ERROR: alBufferData [id:"<<buffer_id<<" sz:"<<numBytes<<"] : "
00325 << error << " " << alGetString( error ) << "\n" << std::flush;
00326 return false;
00327 }
00328
00329
00330 alSourceQueueBuffers( mSources[0], 1, &buffer_id );
00331 if ((error = alGetError()) != AL_NO_ERROR)
00332 {
00333 if (error == AL_INVALID_VALUE)
00334 std::cout << "[syn] ERROR: alSourceQueueBuffers 1 : "
00335 << "AL_INVALID_VALUE\n" << std::flush;
00336 else
00337 std::cout << "[syn] ERROR: alSourceQueueBuffers 1 : "
00338 << error << " " << alGetString( error ) << "\n" << std::flush;
00339 return false;
00340 }
00341
00342
00343
00344 if (this->isPlaying() == false)
00345 {
00346 std::cout << "[syn] WARNING: stream was stopped, "
00347 << "restarting\n" << std::flush;
00348 alSourcePlay( mSources[0] );
00349 }
00350
00351
00352 return true;
00353 }
00354 else
00355 {
00356 return false;
00357 }
00358 }
00359
00360 bool OpenALAudioOStream::close()
00361 {
00362 if (mIsOpen == false)
00363 return false;
00364
00365 ALuint error;
00366 alSourceStopv(1, &mSources[0]);
00367 if ((error = alGetError()) != AL_NO_ERROR)
00368 std::cout << "[syn] ERROR: alSourceStopv 1 : "
00369 << error << "\n" << std::flush;
00370
00371 alDeleteSources(1, &mSources[0]);
00372 if ((error = alGetError()) != AL_NO_ERROR)
00373 std::cout << "[syn] ERROR: alDeleteSources 1 : "
00374 << error << "\n" << std::flush;
00375
00376 alDeleteBuffers(mBuffers.size(), &mBuffers[0]);
00377 if ((error = alGetError()) != AL_NO_ERROR)
00378 std::cout << "[syn] ERROR: alDeleteBuffers : "
00379 << error << "\n" << std::flush;
00380
00381 mIsOpen = false;
00382 return true;
00383 }
00384
00385
00386 void OpenALAudioOStream::resizeBuffers( int numBuffers )
00387 {
00388 if (mIsOpen == true)
00389 {
00390 this->close();
00391 mBuffers.resize( numBuffers );
00392 this->open( mFmt );
00393 }
00394 else
00395 {
00396 mBuffers.resize( numBuffers );
00397 }
00398 }
00399
00400 }