00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "audio/sound_file.hpp"
00018 #include "audio/sound_manager.hpp"
00019 #include "audio/stream_sound_source.hpp"
00020 #include "supertux/timer.hpp"
00021 #include "util/log.hpp"
00022
00023 StreamSoundSource::StreamSoundSource() :
00024 file(0),
00025 fade_state(NoFading),
00026 fade_start_time(),
00027 fade_time(),
00028 looping(false)
00029 {
00030 alGenBuffers(STREAMFRAGMENTS, buffers);
00031 SoundManager::check_al_error("Couldn't allocate audio buffers: ");
00032
00033 sound_manager->register_for_update( this );
00034 }
00035
00036 StreamSoundSource::~StreamSoundSource()
00037 {
00038
00039 sound_manager->remove_from_update( this );
00040 delete file;
00041 stop();
00042 alDeleteBuffers(STREAMFRAGMENTS, buffers);
00043 SoundManager::check_al_error("Couldn't delete audio buffers: ");
00044 }
00045
00046 void
00047 StreamSoundSource::set_sound_file(SoundFile* newfile)
00048 {
00049 delete file;
00050 file = newfile;
00051
00052 ALint queued;
00053 alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
00054 for(size_t i = 0; i < STREAMFRAGMENTS - queued; ++i) {
00055 if(fillBufferAndQueue(buffers[i]) == false)
00056 break;
00057 }
00058 }
00059
00060 void
00061 StreamSoundSource::update()
00062 {
00063 ALint processed = 0;
00064 alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
00065 for(ALint i = 0; i < processed; ++i) {
00066 ALuint buffer;
00067 alSourceUnqueueBuffers(source, 1, &buffer);
00068 SoundManager::check_al_error("Couldn't unqueue audio buffer: ");
00069
00070 if(fillBufferAndQueue(buffer) == false)
00071 break;
00072 }
00073
00074 if(!playing()) {
00075 if(processed == 0 || !looping)
00076 return;
00077
00078
00079 log_info << "Restarting audio source because of buffer underrun" << std::endl;
00080 play();
00081 }
00082
00083 if(fade_state == FadingOn) {
00084 float time = real_time - fade_start_time;
00085 if(time >= fade_time) {
00086 set_gain(1.0);
00087 fade_state = NoFading;
00088 } else {
00089 set_gain(time / fade_time);
00090 }
00091 } else if(fade_state == FadingOff) {
00092 float time = real_time - fade_start_time;
00093 if(time >= fade_time) {
00094 stop();
00095 fade_state = NoFading;
00096 } else {
00097 set_gain( (fade_time-time) / fade_time);
00098 }
00099 }
00100 }
00101
00102 void
00103 StreamSoundSource::set_fading(FadeState state, float fade_time)
00104 {
00105 this->fade_state = state;
00106 this->fade_time = fade_time;
00107 this->fade_start_time = real_time;
00108 }
00109
00110 bool
00111 StreamSoundSource::fillBufferAndQueue(ALuint buffer)
00112 {
00113
00114 char* bufferdata = new char[STREAMFRAGMENTSIZE];
00115 size_t bytesread = 0;
00116 do {
00117 bytesread += file->read(bufferdata + bytesread,
00118 STREAMFRAGMENTSIZE - bytesread);
00119
00120 if(bytesread < STREAMFRAGMENTSIZE) {
00121 if(looping)
00122 file->reset();
00123 else
00124 break;
00125 }
00126 } while(bytesread < STREAMFRAGMENTSIZE);
00127
00128 if(bytesread > 0) {
00129 ALenum format = SoundManager::get_sample_format(file);
00130 alBufferData(buffer, format, bufferdata, bytesread, file->rate);
00131 SoundManager::check_al_error("Couldn't refill audio buffer: ");
00132
00133 alSourceQueueBuffers(source, 1, &buffer);
00134 SoundManager::check_al_error("Couldn't queue audio buffer: ");
00135 }
00136 delete[] bufferdata;
00137
00138
00139 return bytesread >= STREAMFRAGMENTSIZE;
00140 }
00141
00142