#303: Typo fixes from mathnerd314
[supertux.git] / src / audio / stream_sound_source.cpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #include <config.h>
21 #include <assert.h>
22
23 #include <SDL.h>
24
25 #include "stream_sound_source.hpp"
26 #include "sound_manager.hpp"
27 #include "sound_file.hpp"
28 #include "timer.hpp"
29 #include "log.hpp"
30
31 StreamSoundSource::StreamSoundSource()
32   : file(0), fade_state(NoFading), looping(false)
33 {
34   alGenBuffers(STREAMFRAGMENTS, buffers);
35   SoundManager::check_al_error("Couldn't allocate audio buffers: ");
36   //add me to update list
37   sound_manager->register_for_update( this );
38 }
39
40 StreamSoundSource::~StreamSoundSource()
41 {
42   //don't update me any longer
43   sound_manager->remove_from_update( this );
44   delete file;
45   stop();
46   alDeleteBuffers(STREAMFRAGMENTS, buffers);
47   SoundManager::check_al_error("Couldn't delete audio buffers: ");
48 }
49
50 void
51 StreamSoundSource::set_sound_file(SoundFile* newfile)
52 {
53   delete file;
54   file = newfile;
55
56   ALint queued;
57   alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
58   for(size_t i = 0; i < STREAMFRAGMENTS - queued; ++i) {
59     if(fillBufferAndQueue(buffers[i]) == false)
60       break;
61   }
62 }
63
64 void
65 StreamSoundSource::update()
66 {
67   ALint processed = 0;
68   alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
69   for(ALint i = 0; i < processed; ++i) {
70     ALuint buffer;
71     alSourceUnqueueBuffers(source, 1, &buffer);
72     SoundManager::check_al_error("Couldn't unqueue audio buffer: ");
73
74     if(fillBufferAndQueue(buffer) == false)
75       break;
76   }
77
78   if(!playing()) {
79     if(processed == 0 || !looping)
80       return;
81
82     // we might have to restart the source if we had a buffer underrun
83     log_info << "Restarting audio source because of buffer underrun" << std::endl;
84     play();
85   }
86
87   if(fade_state == FadingOn) {
88     float time = real_time - fade_start_time;
89     if(time >= fade_time) {
90       set_gain(1.0);
91       fade_state = NoFading;
92     } else {
93       set_gain(time / fade_time);
94     }
95   } else if(fade_state == FadingOff) {
96     float time = real_time - fade_start_time;
97     if(time >= fade_time) {
98       stop();
99       fade_state = NoFading;
100     } else {
101       set_gain( (fade_time-time) / fade_time);
102     }
103   }
104 }
105
106 void
107 StreamSoundSource::set_fading(FadeState state, float fade_time)
108 {
109   this->fade_state = state;
110   this->fade_time = fade_time;
111   this->fade_start_time = real_time;
112 }
113
114 bool
115 StreamSoundSource::fillBufferAndQueue(ALuint buffer)
116 {
117   // fill buffer
118   char* bufferdata = new char[STREAMFRAGMENTSIZE];
119   size_t bytesread = 0;
120   do {
121     bytesread += file->read(bufferdata + bytesread,
122         STREAMFRAGMENTSIZE - bytesread);
123     // end of sound file
124     if(bytesread < STREAMFRAGMENTSIZE) {
125       if(looping)
126         file->reset();
127       else
128         break;
129     }
130   } while(bytesread < STREAMFRAGMENTSIZE);
131
132   if(bytesread > 0) {
133     ALenum format = SoundManager::get_sample_format(file);
134     alBufferData(buffer, format, bufferdata, bytesread, file->rate);
135     SoundManager::check_al_error("Couldn't refill audio buffer: ");
136
137     alSourceQueueBuffers(source, 1, &buffer);
138     SoundManager::check_al_error("Couldn't queue audio buffer: ");
139   }
140   delete[] bufferdata;
141
142   // return false if there aren't more buffers to fill
143   return bytesread >= STREAMFRAGMENTSIZE;
144 }