1 // Wrapper Library for OpenAL
2 // Author: M.D.Snellgrove
3 // Date: 17/3/2002
4 // History:
5 
6 // Changes by M Snellgrove 26/7/2003
7 //   Conditional Compilation using OpenAL
8 
9 // Changes by Judebert 1/8/2003
10 //   Portability fix for WIN32 systems
11 
12 // Changes by M Snellgrove 5/8/2003
13 //   Code cleanup
14 
15 #include "sampleio.h"
16 
17 // Empty Noaudio sound routines
18 #if AP_AUDIO==AUDIO_NOAUDIO
19 
sampleio()20 sampleio :: sampleio(){}
init(int,char[][255],int,int)21 void sampleio :: init(int, char [][255], int, int){}
close()22 void sampleio :: close(){}
update()23 void sampleio :: update(){}
channel(int,int)24 void sampleio :: channel(int, int){}
loop(int,int)25 void sampleio :: loop(int, int){}
play(int)26 void sampleio :: play(int){}
stop(int)27 void sampleio :: stop(int){}
psource(int,int,bool)28 void sampleio :: psource(int, int, bool){}
volume(int,double)29 void sampleio :: volume(int, double){}
sourceisplaying(ALuint)30 ALboolean sampleio :: sourceisplaying(ALuint){return false;}
31 
32 #endif
33 
34 // OpenAL sound routines
35 #if AP_AUDIO==AUDIO_OPENAL
36 
37 // Constructor
38 
sampleio()39 sampleio :: sampleio(){
40 
41   initdone = false;
42 
43 }
44 
45 // Initialize OpenAL
46 
init(int nsamples,char filenames[][255],int nsources,int npool)47 void sampleio :: init(int nsamples, char filenames[][255], int nsources,
48                       int npool){
49   if (initdone){
50     cerr << "sampleio: call to init when already in use" << endl;
51     exit(1);
52   }
53 
54   initdone = true;
55   numsamples = nsamples;
56   numsources = nsources;
57   numpool = npool;
58   samples = new ALuint[numsamples];
59   sources = new ALuint[numsources+numpool];
60   poolcount = numsources;
61 
62   // Initialize audio device
63   alutInit(0, NULL);
64 
65   ALfloat zeroes[] = { 0.0f, 0.0f,  0.0f };
66   ALfloat back[]   = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f };
67   ALfloat front[]  = { 0.0f, 0.0f,  1.0f, 0.0f, 1.0f, 0.0f };
68   ALfloat position[] = { 0.0f, 0.0f, -4.0f };
69   ALsizei filelen;
70 
71   // Setup Listener
72   alListenerfv(AL_POSITION, zeroes );
73   alListenerfv(AL_VELOCITY, zeroes );
74   alListenerfv(AL_ORIENTATION, front );
75 
76   // Load in samples
77   ALvoid* data;
78   alGenBuffers(numsamples, samples);
79 
80   for (int i = 0; i < numsamples; i++){
81     ALfloat freq;
82     ALboolean fileok;
83     // Evil OpenAL portability fix done here
84     ALenum format;
85     data = alutLoadMemoryFromFile(filenames[i], &format, &filelen, &freq);
86     if (!data){
87       cerr << "sampleio: could not open " << filenames[i] << endl;
88       exit(1);
89     }
90     alBufferData(samples[i], format, data, filelen, freq);
91     free(data);
92   }
93 
94   // Generate Sources
95   alGenSources(numsources+numpool, sources);
96 
97   for(int j=0;j<numsources+numpool;j++){
98     alSourcefv(sources[j], AL_POSITION, position );
99     alSourcefv(sources[j], AL_VELOCITY, zeroes );
100     alSourcefv(sources[j], AL_ORIENTATION, back );
101   }
102 
103 }
104 
105 // Clearup routine
106 
close()107 void sampleio :: close(){
108 
109   if (initdone){
110     delete [] samples;
111     delete [] sources;
112     initdone = false;
113     alutExit();
114   }
115 
116 }
117 
118 // Update method (blank)
119 
update()120 void sampleio :: update(){
121 
122 }
123 
124 // Play a channel
125 
channel(int chan,int sample)126 void sampleio :: channel(int chan, int sample){
127   if (!initdone){
128     cerr << "sampleio: initialize before use" << endl;
129     return;
130   }
131   if ((chan < 0) || (chan >= numsources)){
132     cerr << "sampleio: attempt to play nonexistant source " << chan
133          << endl;
134     return;
135   }
136   if ((sample < 0) || (sample >= numsamples)){
137     cerr << "sampleio: attempt to play nonexistant sample " << sample
138          << endl;
139     return;
140   }
141 
142   psource(chan, sample, false);
143 }
144 
145 // Loop a sample
146 
loop(int chan,int sample)147 void sampleio :: loop(int chan, int sample){
148 
149   if (!initdone){
150     cerr << "sampleio: initialize before use" << endl;
151     return;
152   }
153   if ((chan < 0) || (chan >= numsources)){
154     cerr << "sampleio: attempt to play nonexistant source " << chan
155          << endl;
156     return;
157   }
158   if ((sample < 0) || (sample >= numsamples)){
159     cerr << "sampleio: attempt to play nonexistant sample " << sample
160          << endl;
161     return;
162   }
163   psource(chan, sample, true);
164 
165 }
166 
167 // Play a sample
168 
play(int sample)169 void sampleio :: play(int sample){
170 
171   if (!initdone){
172     cerr << "sampleio: initialize before use" << endl;
173     return;
174   }
175   if (numpool == 0){
176     cerr << "sampleio: attempt to play nonexistant pool " << endl;
177     return;
178   }
179   if ((sample < 0) || (sample >= numsamples)){
180     cerr << "sampleio: attempt to play nonexistant sample " << sample
181          << endl;
182     return;
183   }
184   poolcount++;
185   if (poolcount == numsources + numpool) poolcount = numsources;
186   psource(poolcount, sample, false);
187 
188 }
189 
190 // Stop current sample
191 
stop(int i)192 void sampleio :: stop(int i){
193 
194   if (!initdone){
195     cerr << "sampleio: initialize before use" << endl;
196     return;
197   }
198   if ((i < 0) || (i >= numsources)){
199     cerr << "sampleio: attempt to stop nonexistant source " << i
200          << endl;
201     return;
202   }
203   if (sourceisplaying(sources[i])){
204     alSourceStop(sources[i]);
205   }
206 
207 }
208 
209 // Actaully start a sample
210 
psource(int i,int sample,bool loop)211 void sampleio :: psource(int i, int sample, bool loop){
212 
213   // Stop current sample
214   if (sourceisplaying(sources[i])){
215     alSourceStop(sources[i]);
216   }
217 
218   // Change to new sample
219   alSourcei(sources[i], AL_BUFFER, samples[sample]);
220   if (loop){
221     alSourcei(sources[i], AL_LOOPING, AL_TRUE);
222   }else{
223     alSourcei(sources[i], AL_LOOPING, AL_FALSE);
224   }
225 
226   // Play new sample
227   alSourcePlay(sources[i]);
228 
229 }
230 
231 // Volume control function
232 
volume(int i,double vol)233 void sampleio :: volume(int i, double vol){
234 
235   if (!initdone){
236     cerr << "sampleio: initialize before use" << endl;
237     return;
238   }
239   if ((i < 0) || (i >= numsources)){
240     cerr << "sampleio: attempt to volume nonexistant source " << i
241          << endl;
242     return;
243   }
244   ALfloat volf = ALfloat(vol);
245   alSourcef(sources[i], AL_GAIN, volf);
246 
247 }
248 
249 // Check on playing sources function
250 
sourceisplaying(ALuint sid)251 ALboolean sampleio ::  sourceisplaying(ALuint sid) {
252 
253   ALint state;
254   if(alIsSource(sid) == AL_FALSE){
255     return AL_FALSE;
256   }
257   state = AL_INITIAL;
258 
259   // Evil OpenAL portability fix done here
260 #ifdef _WIN32
261   alGetSourcei(sid, AL_SOURCE_STATE, &state);
262 #else
263   alGetSourceiv(sid, AL_SOURCE_STATE, &state);
264 #endif
265 
266   switch(state) {
267     case AL_PLAYING: case AL_PAUSED:
268       return AL_TRUE;
269     default:
270       break;
271   }
272   return AL_FALSE;
273 
274 }
275 
276 #endif
277