OSE.cpp 12 KB

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