00001 #if 0
00002 #ifdef USE_OPENAL
00003 #include "lugre_sound.h"
00004
00005
00006
00007
00008
00009
00010
00011 #include <boost/shared_ptr.hpp>
00012
00013 #include <AL/al.h>
00014 #include <AL/alut.h>
00015
00016 #include <vorbis/codec.h>
00017 #include <vorbis/vorbisfile.h>
00018
00019 #ifdef WIN32
00020 #include <windows.h>
00021 #endif
00022
00023 #define STREAM_BUFFER_SIZE 1024 * 512 * 4
00024
00025
00026
00027
00028
00029
00030
00031 namespace Lugre {
00032
00033 int giOpenAlLastError = 0;
00034 inline bool _CheckOpenAl(const char *file, const int line){
00035 giOpenAlLastError = alGetError();
00036 if(giOpenAlLastError != AL_NO_ERROR){
00037
00038 return true;
00039 } else {
00040 return false;
00041 }
00042 }
00043
00044 #define CheckOpenAl() _CheckOpenAl(__FILE__,__LINE__)
00045
00046
00047
00048
00049
00050
00052 class cSoundBuffer {
00053 public:
00060 cSoundBuffer(const char *buffer, int size, int channels, int bitrate, int freq){
00061 alGenBuffers(1,(ALuint *)&miId);
00062 CheckOpenAl();
00063 int format;
00064 if(channels == 1){
00065 if(bitrate == 8)format = AL_FORMAT_MONO8;
00066 else format = AL_FORMAT_MONO16;
00067 } else {
00068 if(bitrate == 8)format = AL_FORMAT_STEREO8;
00069 else format = AL_FORMAT_STEREO16;
00070 }
00071 alBufferData(miId,format,buffer,size,freq);
00072 CheckOpenAl();
00073
00074
00075 }
00076
00077 ~cSoundBuffer(){
00078 alDeleteBuffers(1,(ALuint *)&miId);
00079 }
00080
00081 unsigned int GetId(){return miId;}
00082 private:
00083 unsigned int miId;
00084 };
00085 typedef boost::shared_ptr<cSoundBuffer> cSoundBufferPtr;
00086
00087
00088
00089
00090
00092 class cSoundStream {
00093 public:
00095 virtual bool IsFinished() = 0;
00097 virtual int RemainingBytes() = 0;
00099 virtual int FillBuffer(char *buffer, const int size) = 0;
00100
00102 virtual int GetChannels() = 0;
00104 virtual int GetBitrate() = 0;
00106 virtual int GetFrequency() = 0;
00108 int GetFrameSize(){return (GetBitrate() / 8) * GetChannels();}
00109 };
00110
00114
00115 #if defined(WIN32) && !defined(__MINGW32__)
00116
00117 #define STRUCT_PACKED
00118 #else
00119
00120 #define STRUCT_PACKED __attribute__ ((packed))
00121 #endif
00122
00123 struct sRiffWaveHeader {
00124 char riff_riff[4];
00125 unsigned long riff_filelength;
00126 char riff_wave[4];
00127
00128 char fmt_fmt[4];
00129 unsigned long fmt_length;
00130 unsigned short fmt_format;
00131 unsigned short fmt_channels;
00132 unsigned long fmt_sample_rate;
00133 unsigned long fmt_bytes_per_sec;
00134 unsigned short fmt_block_align;
00135 unsigned short fmt_bits_per_sample;
00136
00137 char data_data[4];
00138 unsigned long data_length;
00139 } STRUCT_PACKED;
00140
00141 class cSoundStreamWave : public cSoundStream {
00142 public:
00143 cSoundStreamWave(const char *filename);
00144 ~cSoundStreamWave();
00145 virtual bool IsFinished();
00146 virtual int RemainingBytes();
00147 virtual int FillBuffer(char *buffer, const int size);
00148
00149 virtual int GetChannels();
00150 virtual int GetBitrate();
00151 virtual int GetFrequency();
00152
00153 void CloseFile();
00154
00155 FILE *f;
00156 int miChannels;
00157 int miBitrate;
00158 int miFrequency;
00159 long miTotalSamples;
00160 long miRemainingBytes;
00161 };
00162
00163 int cSoundStreamWave::GetChannels(){return miChannels;}
00164 int cSoundStreamWave::GetBitrate(){return miBitrate;}
00165 int cSoundStreamWave::GetFrequency(){return miFrequency;}
00166
00167 void cSoundStreamWave::CloseFile(){
00168 if(f){
00169 fclose(f);
00170 f = 0;
00171 }
00172 }
00173
00174 int cSoundStreamWave::FillBuffer(char *buffer, const int size){
00175 if(size == 0)return 0;
00176
00177 if(f){
00178 char *p = buffer;
00179 int filled = 0;
00180
00181 while(filled < size){
00182 int ret = fread(p, 1, size - filled, f);
00183 if(ret != size - filled){
00184
00185 CloseFile();
00186 miRemainingBytes = 0;
00187 break;
00188 } else {
00189 filled += ret;
00190 miRemainingBytes -= ret;
00191 }
00192 }
00193
00194 return filled;
00195 } else {
00196 miRemainingBytes = 0;
00197 return 0;
00198 }
00199 }
00200
00201 cSoundStreamWave::cSoundStreamWave(const char *filename) : miChannels(0), miBitrate(0), miFrequency(0) {
00202 f = fopen(filename,"rb");
00203 if(f){
00204
00205 sRiffWaveHeader header;
00206 fread(&header,1,sizeof(header),f);
00207
00208
00209 int samplesize = header.fmt_bits_per_sample / 8;
00210
00211 miTotalSamples = header.data_length / samplesize;
00212 miRemainingBytes = header.data_length;
00213 miChannels = header.fmt_channels;
00214 miFrequency = header.fmt_sample_rate;
00215 miBitrate = header.fmt_bits_per_sample;
00216
00217
00218 } else f = 0;
00219 }
00220
00221 cSoundStreamWave::~cSoundStreamWave(){
00222 CloseFile();
00223 }
00224
00225 int cSoundStreamWave::RemainingBytes(){return miRemainingBytes;}
00226 bool cSoundStreamWave::IsFinished(){return f == 0;}
00227
00228
00232
00233 class cSoundStreamOgg : public cSoundStream {
00234 public:
00235 cSoundStreamOgg(const char *filename);
00236 ~cSoundStreamOgg();
00237 virtual bool IsFinished();
00238 virtual int RemainingBytes();
00239 virtual int FillBuffer(char *buffer, const int size);
00240
00241 virtual int GetChannels();
00242 virtual int GetBitrate();
00243 virtual int GetFrequency();
00244
00245 void CloseFile();
00246
00247 OggVorbis_File vf;
00248 FILE *f;
00249 int miChannels;
00250 int miBitrate;
00251 int miFrequency;
00252 long miTotalSamples;
00253 long miRemainingBytes;
00254 };
00255
00256 int cSoundStreamOgg::GetChannels(){return miChannels;}
00257 int cSoundStreamOgg::GetBitrate(){return miBitrate;}
00258 int cSoundStreamOgg::GetFrequency(){return miFrequency;}
00259
00260 void cSoundStreamOgg::CloseFile(){
00261
00262 ov_clear(&vf);
00263 }
00264
00265 int cSoundStreamOgg::FillBuffer(char *buffer, const int size){
00266
00267 if(size == 0 || miRemainingBytes == 0)return 0;
00268
00269 {
00270 char *p = buffer;
00271 int filled = 0;
00272
00273 while(filled < size){
00274
00275
00276 int section = 0;
00277 long ret = ov_read(&vf, buffer + filled, size - filled, 0, GetBitrate()==8?1:2, 1, §ion);
00278 if(ret == 0){
00279
00280
00281 CloseFile();
00282 miRemainingBytes = 0;
00283 break;
00284 } else if (ret < 0) {
00285
00286 break;
00287
00288
00289 } else {
00290 filled += ret;
00291 miRemainingBytes -= ret;
00292 }
00293 }
00294
00295 return filled;
00296 }
00297 }
00298
00299 cSoundStreamOgg::cSoundStreamOgg(const char *filename) : miChannels(0), miBitrate(0), miFrequency(0), miRemainingBytes(0) {
00300 {
00301 FILE *f = fopen(filename,"rb");
00302 if(ov_open(f, &vf, NULL, 0) < 0) {
00303
00304 } else {
00305
00306 vorbis_info *vi = ov_info(&vf,-1);
00307 miTotalSamples = ov_pcm_total(&vf,-1);
00308 miRemainingBytes = miTotalSamples * 2;
00309 miChannels = vi->channels;
00310 miFrequency = vi->rate;
00311 miBitrate = 16;
00312
00313
00314 }
00315 }
00316 }
00317
00318 cSoundStreamOgg::~cSoundStreamOgg(){
00319 CloseFile();
00320 }
00321
00322 int cSoundStreamOgg::RemainingBytes(){return miRemainingBytes;}
00323 bool cSoundStreamOgg::IsFinished(){return miRemainingBytes <= 0;}
00324
00325
00326
00327
00328
00329 cSoundStream* CreateStreamFromFile(const char* filename) {
00330
00331 const char* p = filename + strlen(filename) - 1;
00332 while(p >= filename && *p != '.')--p;
00333 ++p;
00334
00335
00336
00337 if(strcmp(p,"ogg") == 0)return new cSoundStreamOgg(filename);
00338 if(strcmp(p,"wav") == 0)return new cSoundStreamWave(filename);
00339 return 0;
00340 }
00341
00342
00343
00344
00345
00346
00348 class cSoundSourceOpenAl : public cSoundSource {
00349 public:
00351 cSoundSourceOpenAl();
00353 cSoundSourceOpenAl(const float x,const float y,const float z);
00354
00355 virtual ~cSoundSourceOpenAl();
00356
00358 virtual const bool Play();
00360 virtual const bool IsPlaying();
00362 virtual const bool IsPaused();
00364 virtual void Stop();
00366 virtual void Pause();
00367
00369 virtual void SetVolume(const float volume);
00370 virtual const float GetVolume();
00371
00373 virtual void SetMinMaxDistance(const float min, const float max);
00374 virtual void GetMinMaxDistance(float &min, float &max);
00375
00377
00379 virtual bool Is3D();
00380
00382 virtual void SetPosition(const float x, const float y, const float z);
00384 virtual void SetVelocity(const float x, const float y, const float z);
00385
00387 virtual void GetPosition(float &x, float &y, float &z);
00389 virtual void GetVelocity(float &x, float &y, float &z);
00390
00391 unsigned int miId;
00392 float mfPosition[3];
00393 bool mb3D;
00394 };
00395
00396
00397
00398
00399
00400 class cSoundSystemOpenAl;
00401
00403 class cSoundSourceStream : public cSoundSourceOpenAl {
00404 public:
00406 cSoundSourceStream(cSoundSystemOpenAl *soundSystem, cSoundStream *stream);
00407 cSoundSourceStream(const float x, const float y, const float z, cSoundSystemOpenAl *soundSystem, cSoundStream *stream);
00408
00409 virtual ~cSoundSourceStream();
00411 void Step();
00413 void StreamBuffer(int buffer);
00414
00415 virtual const bool Play();
00416 virtual void Stop();
00417
00419 int RemainingBytes();
00420
00421 private:
00422 cSoundStream *mpStream;
00423 cSoundSystemOpenAl *mpSoundSystem;
00425 int miBufferFormat;
00427 int mlBuffer[2];
00428 };
00429
00430
00431
00432
00433
00434 class cSoundSystemOpenAl : public cSoundSystem {
00435 public:
00436 cSoundSystemOpenAl();
00437
00438 virtual ~cSoundSystemOpenAl();
00439
00441 virtual void SetListenerPosition(const float x, const float y, const float z);
00443 virtual void SetListenerVelocity(const float x, const float y, const float z);
00445 virtual void GetListenerPosition(float &x, float &y, float &z);
00447 virtual void GetListenerVelocity(float &x, float &y, float &z);
00448
00450 virtual void SetVolume(const float volume);
00451 virtual const float GetVolume();
00452
00455 virtual void SetDistanceFactor(const float s);
00456 virtual const float GetDistanceFactor();
00457
00459 virtual cSoundSourceOpenAl *CreateSoundSource(const char *filename);
00461 virtual cSoundSourceOpenAl *CreateSoundSource(const char *buffer, const int size, const int channels, const int bitrate, const int frequency);
00462
00464 virtual cSoundSourceOpenAl *CreateSoundSource3D(const float x, const float y, const float z, const char *filename);
00466 virtual cSoundSourceOpenAl *CreateSoundSource3D(const float x, const float y, const float z, const char *buffer, const int size, const int channels, const int bitrate, const int frequency);
00467
00469 virtual void Step();
00470
00471 std::list<cSoundSourceStream *> mlSourceStream;
00472 };
00473
00477 cSoundSourceStream::cSoundSourceStream(cSoundSystemOpenAl *soundSystem, cSoundStream *stream) : mpSoundSystem(soundSystem) {
00478 alGenBuffers(2,(ALuint *)mlBuffer);
00479 CheckOpenAl();
00480 mpStream = stream;
00481
00482
00483 int channels = mpStream->GetChannels();
00484 int bitrate = mpStream->GetBitrate();
00485 if(channels == 1){
00486 if(bitrate == 8)miBufferFormat = AL_FORMAT_MONO8;
00487 else miBufferFormat = AL_FORMAT_MONO16;
00488 } else {
00489 if(bitrate == 8)miBufferFormat = AL_FORMAT_STEREO8;
00490 else miBufferFormat = AL_FORMAT_STEREO16;
00491 }
00492 }
00493
00494 cSoundSourceStream::cSoundSourceStream(const float x, const float y, const float z, cSoundSystemOpenAl *soundSystem, cSoundStream *stream) : cSoundSourceOpenAl(x,y,z) , mpSoundSystem(soundSystem) {
00495 alGenBuffers(2,(ALuint *)mlBuffer);
00496 CheckOpenAl();
00497 mpStream = stream;
00498
00499
00500 int channels = mpStream->GetChannels();
00501 int bitrate = mpStream->GetBitrate();
00502 if(channels == 1){
00503 if(bitrate == 8)miBufferFormat = AL_FORMAT_MONO8;
00504 else miBufferFormat = AL_FORMAT_MONO16;
00505 } else {
00506 if(bitrate == 8)miBufferFormat = AL_FORMAT_STEREO8;
00507 else miBufferFormat = AL_FORMAT_STEREO16;
00508 }
00509 }
00510
00511 const bool cSoundSourceStream::Play(){
00512
00513 mpSoundSystem->mlSourceStream.push_back(this);
00514
00515
00516 if(RemainingBytes() > 0)StreamBuffer(mlBuffer[0]);
00517 if(RemainingBytes() > 0)StreamBuffer(mlBuffer[1]);
00518
00519 alSourceQueueBuffers(miId, 2, (ALuint *)mlBuffer);
00520 CheckOpenAl();
00521
00522
00523 return cSoundSourceOpenAl::Play();
00524 }
00525
00526 void cSoundSourceStream::Stop(){
00527
00528 cSoundSourceOpenAl::Stop();
00529 }
00530
00531 cSoundSourceStream::~cSoundSourceStream(){
00532 alDeleteBuffers(2,(ALuint *)mlBuffer);
00533 CheckOpenAl();
00534 delete mpStream;
00535 }
00536
00537 char b[STREAM_BUFFER_SIZE];
00538 void cSoundSourceStream::StreamBuffer(int buffer){
00539 int size = mymin(mpStream->RemainingBytes(),STREAM_BUFFER_SIZE);
00540 size = size - (size % mpStream->GetFrameSize());
00541 int frames = size / mpStream->GetFrameSize();
00542 int copied = mpStream->FillBuffer(b, size);
00543
00544
00545
00546 alBufferData(buffer, miBufferFormat, b, copied, mpStream->GetFrequency());
00547 CheckOpenAl();
00548 }
00549
00550
00551 int cSoundSourceStream::RemainingBytes(){
00552 return mpStream->RemainingBytes();
00553 }
00554
00555 void cSoundSourceStream::Step(){
00556 int processed = 0;
00557
00558 if(RemainingBytes() == 0 && IsPlaying() && !IsPaused()){
00559
00560 Stop();
00561 } else if(IsPlaying() && RemainingBytes() > 0){
00562
00563 alGetSourcei(miId, AL_BUFFERS_PROCESSED, &processed);
00564 CheckOpenAl();
00565
00566
00567 while(processed--){
00568 ALuint buffer;
00569 alSourceUnqueueBuffers(miId, 1, &buffer);
00570 CheckOpenAl();
00571 StreamBuffer(buffer);
00572 alSourceQueueBuffers(miId, 1, &buffer);
00573 CheckOpenAl();
00574
00575 }
00576 }
00577 }
00578
00579
00580
00581
00582
00584 class cSoundSourceBuffer : public cSoundSourceOpenAl {
00585 public:
00586 cSoundSourceBuffer(cSoundBufferPtr buffer){
00587 alSourcei(miId,AL_BUFFER,buffer->GetId());
00588 CheckOpenAl();
00589 mpBuffer = buffer;
00590 }
00591 cSoundSourceBuffer(const float x, const float y, const float z, cSoundBufferPtr buffer) : cSoundSourceOpenAl(x,y,z) {
00592 alSourcei(miId,AL_BUFFER,buffer->GetId());
00593 CheckOpenAl();
00594 mpBuffer = buffer;
00595 }
00596 virtual ~cSoundSourceBuffer(){}
00597
00598 private:
00599 cSoundBufferPtr mpBuffer;
00600 };
00601
00602
00603
00604
00605
00606 #define RETURN_ONE_VALUE_F(id,name) float x;alGetSourcef(id,name,&x);CheckOpenAl();return x;
00607 #define RETURN_ONE_VALUE_I(id,name) int x;alGetSourcei(id,name,&x);CheckOpenAl();return x;
00608
00609 cSoundSourceOpenAl::cSoundSourceOpenAl() : mb3D(false) {
00610
00611 alGenSources(1,(ALuint *)&miId);
00612 CheckOpenAl();
00613 }
00614
00615 cSoundSourceOpenAl::cSoundSourceOpenAl(const float x, const float y, const float z) : mb3D(true) {
00616
00617 alGenSources(1,(ALuint *)&miId);
00618 CheckOpenAl();
00619 SetPosition(x,y,z);
00620 }
00621
00622 cSoundSourceOpenAl::~cSoundSourceOpenAl(){
00623 alDeleteSources(1,(ALuint *)&miId);
00624 CheckOpenAl();
00625 }
00626
00628 const bool cSoundSourceOpenAl::Play(){alSourcePlay(miId);CheckOpenAl();return true;}
00630 const bool cSoundSourceOpenAl::IsPlaying(){int x;alGetSourcei(miId,AL_SOURCE_STATE,&x);CheckOpenAl();return x==AL_PLAYING;}
00632 const bool cSoundSourceOpenAl::IsPaused(){int x;alGetSourcei(miId,AL_SOURCE_STATE,&x);CheckOpenAl();return x==AL_PAUSED;}
00634 void cSoundSourceOpenAl::Stop(){alSourceStop(miId);CheckOpenAl();}
00636 void cSoundSourceOpenAl::Pause(){alSourcePause(miId);CheckOpenAl();}
00637
00639 void cSoundSourceOpenAl::SetVolume(const float volume){alSourcef(miId,AL_POSITION,volume);CheckOpenAl();}
00640 const float cSoundSourceOpenAl::GetVolume(){float x;alGetSourcef(miId,AL_POSITION,&x);CheckOpenAl();return x;}
00641
00642 void cSoundSourceOpenAl::SetMinMaxDistance(const float min, const float max){
00643 alSourcef(miId,AL_MAX_DISTANCE,max);CheckOpenAl();}
00644 void cSoundSourceOpenAl::GetMinMaxDistance(float &min, float &max){
00645 alGetSourcef(miId,AL_MAX_DISTANCE,&max);CheckOpenAl();}
00646
00648
00650 bool cSoundSourceOpenAl::Is3D(){return mb3D;}
00651
00653 void cSoundSourceOpenAl::SetPosition(const float x, const float y, const float z){alSource3f(miId,AL_POSITION,x,y,z);CheckOpenAl();}
00655 void cSoundSourceOpenAl::SetVelocity(const float x, const float y, const float z){alSource3f(miId,AL_VELOCITY,x,y,z);CheckOpenAl();}
00656
00658 void cSoundSourceOpenAl::GetPosition(float &x, float &y, float &z){alGetSource3f(miId,AL_POSITION,&x,&y,&z);CheckOpenAl();}
00660 void cSoundSourceOpenAl::GetVelocity(float &x, float &y, float &z){alGetSource3f(miId,AL_VELOCITY,&x,&y,&z);CheckOpenAl();}
00661
00662
00663
00664
00665
00666
00667
00668
00669 cSoundSystemOpenAl::cSoundSystemOpenAl(){
00670 alutInit(0,0);
00671 CheckOpenAl();
00672 }
00673
00674 cSoundSystemOpenAl::~cSoundSystemOpenAl(){
00675 alutExit();
00676 CheckOpenAl();
00677 }
00678
00679 void cSoundSystemOpenAl::Step(){
00680 std::list<cSoundSourceStream *> lDeadSourceStream;
00681
00682 for (std::list<cSoundSourceStream *>::iterator itor=mlSourceStream.begin();itor!=mlSourceStream.end();++itor){
00683 cSoundSourceStream *s = (*itor);
00684 s->Step();
00685
00686
00687 if(!s->IsPlaying()){
00688 lDeadSourceStream.push_back(s);
00689 }
00690 }
00691
00692 while(lDeadSourceStream.size() > 0){
00693
00694 cSoundSourceStream *p = *(lDeadSourceStream.begin());
00695 mlSourceStream.remove(p);
00696 lDeadSourceStream.pop_front();
00697
00698 }
00699 }
00700
00702 void cSoundSystemOpenAl::SetListenerPosition(const float x, const float y, const float z){alListener3f(AL_POSITION,x,y,z);CheckOpenAl();}
00704 void cSoundSystemOpenAl::SetListenerVelocity(const float x, const float y, const float z){alListener3f(AL_VELOCITY,x,y,z);CheckOpenAl();}
00706 void cSoundSystemOpenAl::GetListenerPosition(float &x, float &y, float &z){alGetListener3f(AL_POSITION,&x,&y,&z);CheckOpenAl();}
00708 void cSoundSystemOpenAl::GetListenerVelocity(float &x, float &y, float &z){alGetListener3f(AL_VELOCITY,&x,&y,&z);CheckOpenAl();}
00709
00711 void cSoundSystemOpenAl::SetVolume(const float volume){alListenerf(AL_POSITION,volume);CheckOpenAl();}
00712 const float cSoundSystemOpenAl::GetVolume(){float x;alGetListenerf(AL_VELOCITY,&x);CheckOpenAl();return x;}
00713
00716 void cSoundSystemOpenAl::SetDistanceFactor(const float s){}
00717 const float cSoundSystemOpenAl::GetDistanceFactor(){return 1.0f;}
00718
00720 cSoundSourceOpenAl *cSoundSystemOpenAl::CreateSoundSource(const char *filename){
00721 return new cSoundSourceStream(this, CreateStreamFromFile(filename));
00722 }
00723
00725 cSoundSourceOpenAl *cSoundSystemOpenAl::CreateSoundSource(const char *buffer, const int size, const int channels, const int bitrate, const int frequency){
00726
00727 cSoundBufferPtr pBuffer(new cSoundBuffer(buffer,size,channels,bitrate,frequency));
00728 return new cSoundSourceBuffer(pBuffer);
00729 }
00730
00732 cSoundSourceOpenAl *cSoundSystemOpenAl::CreateSoundSource3D(const float x, const float y, const float z, const char *filename){
00733
00734 return new cSoundSourceStream(x,y,z,this, CreateStreamFromFile(filename));
00735 }
00737 cSoundSourceOpenAl *cSoundSystemOpenAl::CreateSoundSource3D(const float x, const float y, const float z, const char *buffer, const int size, const int channels, const int bitrate, const int frequency){
00738
00739 cSoundBufferPtr pBuffer(new cSoundBuffer(buffer,size,channels,bitrate,frequency));
00740 return new cSoundSourceBuffer(pBuffer);
00741 }
00742
00743 cSoundSystem *CreateSoundSystemOpenAl(const int frequency){
00744
00745 return new cSoundSystemOpenAl();
00746 }
00747
00748 };
00749 #endif
00750 #endif