00001 #include "../header/OpenAL.h"
00002 #define BUFFER_SIZE (4096 * 4)
00003 #define CHECK (alGetError() == AL_NO_ERROR)
00004
00005 STARTNAMESPACE
00006
00007 SMusicOGG::SMusicOGG(ArrayList<Music*>& musiclist) : list(musiclist){
00008 m_play = false;
00009 m_playing = false;
00010 oggFile = 0;
00011 source = 0;
00012 buffers[0] = 0;
00013 buffers[1] = 0;
00014 }
00015
00016 SMusicOGG::~SMusicOGG(){
00017 free();
00018 }
00019
00020 bool SMusicOGG::isPlaying(){
00021 ALenum state;
00022 alGetSourcei(source, AL_SOURCE_STATE, &state);
00023 return (state == AL_PLAYING);
00024 }
00025
00026 void SMusicOGG::play(){
00027 if((isPlaying()) ||
00028 (stream(buffers[0]) == false) ||
00029 (stream(buffers[1]) == false) ||
00030 (recreate() == false))
00031 return;
00032
00033 if(m_play == false)
00034 list.add(this);
00035 alSourceQueueBuffers(source, 2, buffers);
00036 alSourcePlay(source);
00037 m_play = true;
00038 m_release = false;
00039 }
00040
00041 void SMusicOGG::stop(){
00042 if(m_play)
00043 list.remove(this);
00044 m_play = false;
00045 alSourceStop(source);
00046 empty();
00047 }
00048
00049 void SMusicOGG::pause(){
00050 if(m_play)
00051 list.remove(this);
00052 m_play = false;
00053 alSourcePause(source);
00054 }
00055
00056 void SMusicOGG::resume(){
00057 if(m_play == false)
00058 list.add(this);
00059 m_play = true;
00060 alSourcePlay(source);
00061 }
00062
00063 void SMusicOGG::update(){
00064 ALuint buffer;
00065 union{int processed, state;};
00066 bool active = false;
00067
00068 if(m_release){
00069 if(isPlaying() == false)
00070 stop();
00071 }else{
00072 alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
00073
00074 while(processed--){
00075 alSourceUnqueueBuffers(source, 1, &buffer);
00076 active = stream(buffer);
00077 alSourceQueueBuffers(source, 1, &buffer);
00078 if(CHECK == false)
00079 return;
00080 }
00081
00082
00083 if(active){
00084 alGetSourcei(source, AL_SOURCE_STATE, &state);
00085 if(state != AL_PLAYING)
00086 alSourcePlay(source);
00087 }
00088 }
00089 }
00090
00091 bool SMusicOGG::load(const wchar* file, bool loop, float volume){
00092 m_loop = loop;
00093
00094 if(_wfopen_s(&oggFile, file, TEXT("rb")) != 0)
00095 return false;
00096
00097 if(ov_open(oggFile, &oggStream, NULL, 0) < 0){
00098 fclose(oggFile);
00099 oggFile = 0;
00100 return false;
00101 }
00102
00103 vorbisInfo = ov_info(&oggStream, -1);
00104
00105 format = (vorbisInfo->channels == 1) ?
00106 AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
00107
00108 alGenBuffers(2, buffers);
00109 if(CHECK == false)
00110 return false;
00111 alGenSources(1, &source);
00112 if(CHECK == false)
00113 return false;
00114
00115 alSource3f(source, AL_POSITION, 0.0, 0.0, 0.0);
00116 alSource3f(source, AL_VELOCITY, 0.0, 0.0, 0.0);
00117 alSource3f(source, AL_DIRECTION, 0.0, 0.0, 0.0);
00118 alSourcef (source, AL_ROLLOFF_FACTOR, 0.0 );
00119 alSourcei (source, AL_SOURCE_RELATIVE, AL_TRUE );
00120 alSourcei (source, AL_LOOPING, AL_FALSE );
00121 return true;
00122 }
00123
00124 bool SMusicOGG::recreate(void){
00125 if(oggFile == 0)
00126 return false;
00127 fseek(oggFile, 0, SEEK_SET);
00128 return true;
00129 }
00130
00131 void SMusicOGG::free(){
00132 if(source){
00133 alSourceStop(source);
00134 alDeleteSources(1, &source);
00135 source = 0;
00136 }
00137 if(buffers[0]){
00138 alDeleteBuffers(2, buffers);
00139 buffers[0] = 0;
00140 buffers[1] = 0;
00141 }
00142
00143 ov_clear(&oggStream);
00144 if(oggFile){
00145 fclose(oggFile);
00146 oggFile = 0;
00147 }
00148 }
00149
00150 bool SMusicOGG::stream(ALuint buffer){
00151 char data[BUFFER_SIZE];
00152 int size = 0;
00153 int section;
00154 int result;
00155
00156 while(size < BUFFER_SIZE)
00157 {
00158 result = ov_read(&oggStream, data + size, BUFFER_SIZE - size, 0, 2, 1, §ion);
00159
00160 if(result > 0){
00161 size += result;
00162 }else if(result == 0){
00163 ov_raw_seek(&oggStream, 0);
00164 if(m_loop){
00165 if(size >= BUFFER_SIZE)
00166 break;
00167 }else{
00168 m_release = true;
00169 break;
00170 }
00171 }else{
00172
00173 }
00174 }
00175
00176 if(size == 0)
00177 return false;
00178
00179 alBufferData(buffer, format, data, size, vorbisInfo->rate);
00180
00181 return CHECK;
00182 }
00183
00184 void SMusicOGG::empty(){
00185 ALuint buffer;
00186 int queued;
00187
00188 alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
00189
00190 while(queued--)
00191 alSourceUnqueueBuffers(source, 1, &buffer);
00192 }
00193
00194 ENDNAMESPACE
00195
00196 #undef CHECK