1 /*
2 * Seven Kingdoms: Ancient Adversaries
3 *
4 * Copyright 1997,1998 Enlight Software Ltd.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (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, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 // Filename : OSE.CPP
22 // Description : Sound Effect Controller
23 // Owner : Gilbert
24
25 #include <OSE.h>
26 #include <OAUDIO.h>
27 #include <OGAMESET.h>
28 #include <OMISC.h>
29 #include <OCONFIG.h>
30
31 #define MIN_AUDIO_VOL 10
32
33 // ------ Begin Function SERequest::add_request -------//
add_request(RelVolume relVolume)34 void SERequest::add_request(RelVolume relVolume)
35 {
36 if( req_used < MAX_SE_STORE)
37 {
38 play_vol[req_used] = relVolume;
39 req_used++;
40 }
41 else
42 {
43 // not enough space, remove the MIN volume one.
44 RelVolume minVolume = relVolume;
45 for( int i = 0; i < MAX_SE_STORE; ++i)
46 {
47 if( play_vol[i].rel_vol < minVolume.rel_vol)
48 {
49 RelVolume temp;
50 // swap volume[i] and minVolume
51 temp = play_vol[i];
52 play_vol[i] = minVolume;
53 minVolume = temp;
54 }
55 }
56 }
57 }
58 // ------ End Function SERequest::add_request -------//
59
60
61 // ------ Begin Function SERequest::max_entry -------//
max_entry()62 int SERequest::max_entry()
63 {
64 err_when( req_used <= 0);
65
66 int maxEntry = 0;
67 RelVolume *maxVolume = &play_vol[maxEntry];
68 for( int i = 1; i < req_used; ++i)
69 {
70 if( maxVolume->rel_vol < play_vol[i].rel_vol)
71 {
72 maxVolume = &play_vol[i];
73 maxEntry = i;
74 }
75 }
76
77 return maxEntry;
78 }
79 // ------ End Function SERequest::max_entry -------//
80
81
82 // ------ Begin Function SERequest::remove_request -------//
remove_request(int slot)83 void SERequest::remove_request(int slot)
84 {
85 if( slot >= req_used || slot < 0)
86 return;
87
88 // ---- move element after slot -----/
89 for( int i = slot+1; i < req_used; ++i)
90 {
91 play_vol[i-1] = play_vol[i];
92 }
93 req_used--;
94 }
95 // ------ End Function SERequest::remove_request -------//
96
97
98 // ------ Begin Function SERequest::clear_request -------//
clear_request()99 void SERequest::clear_request()
100 {
101 req_used = 0;
102 }
103 // ------ End Function SERequest::clear_request -------//
104
105
106 // ------ Begin Function SECtrl::SECtrl -------//
SECtrl(Audio * audioPtr)107 SECtrl::SECtrl(Audio *audioPtr) : audio_ptr(audioPtr), res_supp(audioPtr->wav_res)
108 {
109 init_flag = 0;
110 audio_flag = 0;
111 req_pool = NULL;
112 last_cycle = NULL;
113 max_sound_effect = 0;
114 max_supp_effect = 0;
115 total_effect = 0;
116 biased_se = 0;
117 }
118 // ------ End Function SECtrl::SECtrl -------//
119
120
121 // ------ Begin Function SECtrl::~SECtrl ------//
~SECtrl()122 SECtrl::~SECtrl()
123 {
124 deinit();
125 }
126 // ------ End Function SECtrl::~SECtrl ------//
127
128
129 // ------ Begin Function SECtrl::init -------//
init()130 void SECtrl::init()
131 {
132 deinit();
133
134 audio_flag = audio_ptr->wav_init_flag;
135 if( !audio_flag )
136 {
137 init_flag = 1;
138 return;
139 }
140
141 //----- open wave resource file -------//
142
143 String str;
144
145 str = DIR_RES;
146 str += "A_WAVE1.RES";
147
148 res_wave.init(str,1); // 1-read all into buffer
149
150 //------- load database information --------//
151
152 load_info();
153
154 // ----- clear last_cycle array and wave_ptr --------//
155 init_flag = 1;
156 clear();
157 }
158 // ------ End Function SECtrl::init -------//
159
160
161 // ------ Begin Function SECtrl::deinit -------//
deinit()162 void SECtrl::deinit()
163 {
164 if( init_flag )
165 {
166 init_flag = 0;
167 if( audio_flag )
168 {
169 mem_del(req_pool);
170 mem_del(last_cycle);
171 }
172 }
173 }
174 // ------ End Function SECtrl::deinit -------//
175
176
177 // ------ Begin Function SECtrl::load_info -------//
load_info()178 void SECtrl::load_info()
179 {
180 int count = max_sound_effect = res_wave.rec_count;
181 int suppCount = max_supp_effect = res_supp.rec_count;
182 total_effect = max_sound_effect + max_supp_effect;
183
184 req_pool = (SERequest *)mem_add(total_effect * sizeof(SERequest) );
185 last_cycle = (char *)mem_add(total_effect * sizeof(char));
186
187 short j;
188 for(j=0; j < count; ++j)
189 {
190 req_pool[j].resx_id = j+1;
191 req_pool[j].wave_ptr = res_wave.get_data(j+1); // wave data pointer
192 last_cycle[j] = 0;
193 }
194
195 for(short k=0; k < suppCount; ++k, ++j)
196 {
197 req_pool[j].resx_id = k+1;
198 req_pool[j].wave_ptr = NULL;
199 last_cycle[j] = 0;
200 }
201 }
202 // ------ End Function SECtrl::load_info -------//
203
204
205 // ------ Begin Function SECtrl::clear -------//
clear()206 void SECtrl::clear()
207 {
208 for( int j = 0; j < total_effect; ++j)
209 {
210 req_pool[j].clear_request();
211 }
212 }
213 // ------ End Function SECtrl::clear -------//
214
215
216 // ------ Begin Function SECtrl::request -------//
217 //
218 // Request to sound an effect
219 //
220 // <int> soundEffect the id of the sound effect, return from SECtrl::search_effect_id
221 // <long> vol volume (0 - 100 MAX loudness)
222 // <long> pan pan (-10000 = full left; 10000 = full right)
223 // note the request is abolished if vol is 0 or soundEffect is 0
224 //
request(int soundEffect,RelVolume relVolume)225 void SECtrl::request(int soundEffect, RelVolume relVolume)
226 {
227 if( !audio_flag || !config.sound_effect_flag)
228 return; // skip if audio cannot init wave device
229 err_when( soundEffect < 0 || soundEffect > total_effect);
230 if( relVolume.rel_vol >= MIN_AUDIO_VOL && soundEffect)
231 req_pool[soundEffect-1].add_request(relVolume);
232 }
233
234
request(char * soundName,RelVolume relVolume)235 void SECtrl::request(char *soundName, RelVolume relVolume)
236 {
237 if( !audio_flag || !config.sound_effect_flag)
238 return; // skip if audio cannot init wave device
239 int soundEffect = search_effect_id(soundName);
240 err_when( soundEffect < 0 || soundEffect > total_effect);
241 if( relVolume.rel_vol >= MIN_AUDIO_VOL && soundEffect)
242 req_pool[soundEffect-1].add_request(relVolume);
243 }
244 // ------ End Function SECtrl::request -------//
245
246 // ------ Begin Function SECtrl::flush -------//
flush()247 void SECtrl::flush()
248 {
249 err_when(!init_flag);
250 // ##### begin Gilbert 11/11 ######//
251 // err_when(!audio_ptr->init_flag);
252 // ##### end Gilbert 11/11 ######//
253 if( !audio_flag || !config.sound_effect_flag)
254 {
255 clear();
256 return; // skip if audio cannot init wave device
257 }
258 int chCount = audio_ptr->get_free_wav_ch();
259 int reqCount = 0, reqSum = 0;
260 int i,j,k;
261 SERequest *seRequest;
262
263 k = 0;
264 cached_size = 0;
265 for( j = 0, seRequest=req_pool; j < total_effect ; ++j, ++seRequest)
266 {
267 if( seRequest->req_used > 0)
268 {
269 reqCount++;
270 reqSum += seRequest->req_used;
271 }
272
273 // cached sound effect
274 if( (seRequest->req_used > 0 || last_cycle[j]) && cached_size < MAX_SE_CACHED )
275 {
276 cached_index[cached_size++] = j;
277 }
278 }
279
280 if( reqSum <= chCount )
281 {
282 // --------- enough for all requests --------//
283 // for( j = 0, seRequest=req_pool; j < total_effect; ++j, ++seRequest)
284 for( k = 0; k < cached_size; ++k)
285 {
286 j = cached_index[k]; seRequest = req_pool + j;
287
288 last_cycle[j] = 0;
289 for( i = seRequest->req_used-1; i >= 0; --i)
290 {
291 if( seRequest->wave_ptr)
292 {
293 audio_ptr->play_resided_wav( seRequest->wave_ptr,
294 seRequest->play_vol[i]);
295 }
296 else
297 {
298 audio_ptr->play_wav( seRequest->resx_id,
299 seRequest->play_vol[i]);
300 }
301 last_cycle[j]++;
302 chCount--;
303 }
304 }
305 reqSum = 0;
306 reqCount = 0;
307 }
308 else if( reqCount <= chCount )
309 {
310 // --------- one channel for one sound effect --------//
311 for( k = 0; k < cached_size; ++k)
312 {
313 j = cached_index[k]; seRequest = req_pool + j;
314 last_cycle[j] = 0;
315 if( seRequest->req_used > 0)
316 {
317 i = seRequest->max_entry();
318 if( seRequest->wave_ptr)
319 {
320 audio_ptr->play_resided_wav( seRequest->wave_ptr,
321 seRequest->play_vol[i]);
322 }
323 else
324 {
325 audio_ptr->play_wav( seRequest->resx_id,
326 seRequest->play_vol[i]);
327 }
328 last_cycle[j]++;
329 }
330 }
331 }
332 else
333 {
334 // -------- not enough for each sound effect ------//
335
336 // ------- one channel for one sound effect --------//
337 for( k = 0; k < cached_size && biased_se > cached_index[k]; ++k);
338 if( k >= cached_size)
339 k = 0;
340
341 for( int c = 0; chCount > 0 && c < cached_size; ++c)
342 {
343 if( ++k >= cached_size)
344 k = 0;
345 j = cached_index[k]; seRequest = req_pool + j;
346 if( seRequest->req_used > 0 && !last_cycle[j])
347 {
348 i = seRequest->max_entry();
349 if( seRequest->wave_ptr )
350 {
351 audio_ptr->play_resided_wav( seRequest->wave_ptr,
352 seRequest->play_vol[i]);
353 }
354 else
355 {
356 audio_ptr->play_wav( seRequest->resx_id,
357 seRequest->play_vol[i]);
358 }
359 last_cycle[j]++;
360 chCount--;
361 biased_se = j;
362 }
363 else
364 {
365 last_cycle[j] = 0;
366 }
367 }
368 }
369
370 clear();
371 }
372 // ------ End Function SECtrl::flush -------//
373
374
375 // ------ Begin Function SECtrl::get_effect_name -------//
376 //
377 // return the name of the sound effect
378 // int j the id of the sound effect
379 //
get_effect_name(int j)380 char *SECtrl::get_effect_name(int j)
381 {
382 err_when(!init_flag);
383 err_when( j < 1 || j > total_effect );
384 if( j > max_sound_effect )
385 return res_supp.data_name(j - max_sound_effect);
386 else
387 return res_wave.data_name(j);
388 }
389 // ------ End Function SECtrl::get_effect_name -------//
390
391
392 // ------ Begin Function SECtrl::search_effect_id -------//
393 //
394 // find the sound effect id of an sound effect
395 //
396 // <char *> effectName the name of the effect name
397 //
search_effect_id(const char * effectName)398 int SECtrl::search_effect_id(const char *effectName)
399 {
400 err_when(!init_flag);
401 if( !audio_flag )
402 return 0; // skip if audio cannot init wave device
403
404 int idx = res_wave.get_index(effectName);
405 if( idx )
406 return idx;
407
408 idx = res_supp.get_index(effectName);
409 if( idx )
410 return idx + max_sound_effect;
411
412 return 0;
413 }
414 // ------ End Function SECtrl::search_effect_id -------//
415
416
417 // ------ Begin Function SECtrl::search_effect_id -------//
418 //
419 // find the sound effect id of an sound effect
420 //
421 // <char *> effectName the name of the effect name
422 // <int> len the size of the effectName
423 //
search_effect_id(char * effectName,int len)424 int SECtrl::search_effect_id(char *effectName, int len)
425 {
426 err_when(!init_flag);
427 if( !audio_flag)
428 return 0; // skip if audio cannot init wave device
429
430 char tmpStr[16];
431 err_when(len >= 16);
432 memcpy(tmpStr, effectName, len);
433 tmpStr[len] = '\0';
434 misc.rtrim(tmpStr);
435
436 int idx = res_wave.get_index(tmpStr);
437 if( idx )
438 return idx;
439
440 idx = res_supp.get_index(tmpStr);
441 if( idx )
442 return idx + max_sound_effect;
443
444 return 0;
445
446 }
447 // ------ End Function SECtrl::search_effect_id -------//
448
449 /*
450 // ------ Begin Function SECtrl::sound_volume --------//
451 //
452 // calculate the volume from a location
453 //
454 // <short> locX, locY - location x, y relative to the center of screen
455 // [short] limit - volume is zero if dist > limit
456 // [short] drop - volume is dropped (linearly) to zero when dist = drop
457 // drop > limit
458 //
459
460 const default_vol_limit = 20;
461 const default_vol_drop = 100;
462 long SECtrl::sound_volume(short locX, short locY)
463 {
464 short dist = MAX( locX >= 0? locX : -locX, locY >= 0? locY:-locY);
465 err_when( default_vol_drop <= default_vol_limit);
466
467 if( dist > default_vol_limit)
468 return 0;
469 else
470 return 90 - dist * 90 / default_vol_drop;
471 }
472
473
474 long SECtrl::sound_volume(short locX, short locY, short limit, short drop)
475 {
476 short dist = MAX( locX >= 0? locX : -locX, locY >= 0? locY:-locY);
477 err_when( drop <= limit);
478
479 if( dist > limit)
480 return 0;
481 else
482 return 90 - dist * 90 / drop;
483 }
484 // ------ End Function SECtrl::sound_volume --------//
485
486
487 // ------ Begin Function SECtrl::sound_pan --------//
488 //
489 // calculate the pan setting of a location
490 //
491 // short locX, locY - location x, y relative to the center of screen
492 // short drop - panning is set to extreme value when abs(locX) >= drop
493 //
494
495 const default_pan_drop = 100;
496 long SECtrl::sound_pan(short locX, short locY)
497 {
498 if( locX >= default_pan_drop )
499 return 10000;
500 if( locX <= -default_pan_drop )
501 return -10000;
502 return 10000 / default_pan_drop * locX;
503 }
504
505
506 long SECtrl::sound_pan(short locX, short locY, short drop)
507 {
508 if( locX >= drop )
509 return 10000;
510 if( locX <= -drop )
511 return -10000;
512 return 10000 * locX / drop;
513 }
514 // ------ End Function SECtrl::sound_pan --------//
515 */
516
517 // ------- Begin Function SECtrl::immediate_sound ------------//
immediate_sound(const char * soundName,RelVolume relVolume)518 int SECtrl::immediate_sound(const char *soundName, RelVolume relVolume)
519 {
520 if( !config.sound_effect_flag )
521 return 0;
522
523 int effectId = search_effect_id(soundName);
524 if( effectId )
525 {
526 SERequest *seRequest = req_pool + effectId-1;
527 if( seRequest->wave_ptr )
528 return audio_ptr->play_resided_wav( seRequest->wave_ptr, relVolume);
529 else
530 return audio_ptr->play_wav( seRequest->resx_id, relVolume);
531 }
532 return 0;
533 }
534 // ------- End Function SECtrl::immediate_sound ------------//
535