/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ // Filename : OSE.CPP // Description : Sound Effect Controller // Owner : Gilbert #include #include #include #include #include #define MIN_AUDIO_VOL 10 // ------ Begin Function SERequest::add_request -------// void SERequest::add_request(RelVolume relVolume) { if( req_used < MAX_SE_STORE) { play_vol[req_used] = relVolume; req_used++; } else { // not enough space, remove the min volume one. RelVolume minVolume = relVolume; for( int i = 0; i < MAX_SE_STORE; ++i) { if( play_vol[i].rel_vol < minVolume.rel_vol) { RelVolume temp; // swap volume[i] and minVolume temp = play_vol[i]; play_vol[i] = minVolume; minVolume = temp; } } } } // ------ End Function SERequest::add_request -------// // ------ Begin Function SERequest::max_entry -------// int SERequest::max_entry() { err_when( req_used <= 0); int maxEntry = 0; RelVolume *maxVolume = &play_vol[maxEntry]; for( int i = 1; i < req_used; ++i) { if( maxVolume->rel_vol < play_vol[i].rel_vol) { maxVolume = &play_vol[i]; maxEntry = i; } } return maxEntry; } // ------ End Function SERequest::max_entry -------// // ------ Begin Function SERequest::remove_request -------// void SERequest::remove_request(int slot) { if( slot >= req_used || slot < 0) return; // ---- move element after slot -----/ for( int i = slot+1; i < req_used; ++i) { play_vol[i-1] = play_vol[i]; } req_used--; } // ------ End Function SERequest::remove_request -------// // ------ Begin Function SERequest::clear_request -------// void SERequest::clear_request() { req_used = 0; } // ------ End Function SERequest::clear_request -------// // ------ Begin Function SECtrl::SECtrl -------// SECtrl::SECtrl(Audio *audioPtr) : audio_ptr(audioPtr), res_supp(audioPtr->wav_res) { init_flag = 0; audio_flag = 0; req_pool = NULL; last_cycle = NULL; max_sound_effect = 0; max_supp_effect = 0; total_effect = 0; biased_se = 0; } // ------ End Function SECtrl::SECtrl -------// // ------ Begin Function SECtrl::~SECtrl ------// SECtrl::~SECtrl() { deinit(); } // ------ End Function SECtrl::~SECtrl ------// // ------ Begin Function SECtrl::init -------// void SECtrl::init() { deinit(); audio_flag = audio_ptr->wav_init_flag; if( !audio_flag ) { init_flag = 1; return; } //----- open wave resource file -------// String str; str = DIR_RES; str += "A_WAVE1.RES"; res_wave.init(str,1); // 1-read all into buffer //------- load database information --------// load_info(); // ----- clear last_cycle array and wave_ptr --------// init_flag = 1; clear(); } // ------ End Function SECtrl::init -------// // ------ Begin Function SECtrl::deinit -------// void SECtrl::deinit() { if( init_flag ) { init_flag = 0; if( audio_flag ) { mem_del(req_pool); mem_del(last_cycle); } } } // ------ End Function SECtrl::deinit -------// // ------ Begin Function SECtrl::load_info -------// void SECtrl::load_info() { int count = max_sound_effect = res_wave.rec_count; int suppCount = max_supp_effect = res_supp.rec_count; total_effect = max_sound_effect + max_supp_effect; req_pool = (SERequest *)mem_add(total_effect * sizeof(SERequest) ); last_cycle = (char *)mem_add(total_effect * sizeof(char)); short j; for(j=0; j < count; ++j) { req_pool[j].resx_id = j+1; req_pool[j].wave_ptr = res_wave.get_data(j+1); // wave data pointer last_cycle[j] = 0; } for(short k=0; k < suppCount; ++k, ++j) { req_pool[j].resx_id = k+1; req_pool[j].wave_ptr = NULL; last_cycle[j] = 0; } } // ------ End Function SECtrl::load_info -------// // ------ Begin Function SECtrl::clear -------// void SECtrl::clear() { for( int j = 0; j < total_effect; ++j) { req_pool[j].clear_request(); } } // ------ End Function SECtrl::clear -------// // ------ Begin Function SECtrl::request -------// // // Request to sound an effect // // soundEffect the id of the sound effect, return from SECtrl::search_effect_id // vol volume (0 - 100 max loudness) // pan pan (-10000 = full left; 10000 = full right) // note the request is abolished if vol is 0 or soundEffect is 0 // void SECtrl::request(int soundEffect, RelVolume relVolume) { if( !audio_flag || !config.sound_effect_flag) return; // skip if audio cannot init wave device err_when( soundEffect < 0 || soundEffect > total_effect); if( relVolume.rel_vol >= MIN_AUDIO_VOL && soundEffect) req_pool[soundEffect-1].add_request(relVolume); } void SECtrl::request(char *soundName, RelVolume relVolume) { if( !audio_flag || !config.sound_effect_flag) return; // skip if audio cannot init wave device int soundEffect = search_effect_id(soundName); err_when( soundEffect < 0 || soundEffect > total_effect); if( relVolume.rel_vol >= MIN_AUDIO_VOL && soundEffect) req_pool[soundEffect-1].add_request(relVolume); } // ------ End Function SECtrl::request -------// // ------ Begin Function SECtrl::flush -------// void SECtrl::flush() { err_when(!init_flag); // ##### begin Gilbert 11/11 ######// // err_when(!audio_ptr->init_flag); // ##### end Gilbert 11/11 ######// if( !audio_flag || !config.sound_effect_flag) { clear(); return; // skip if audio cannot init wave device } int chCount = audio_ptr->get_free_wav_ch(); int reqCount = 0, reqSum = 0; int i,j,k; SERequest *seRequest; k = 0; cached_size = 0; for( j = 0, seRequest=req_pool; j < total_effect ; ++j, ++seRequest) { if( seRequest->req_used > 0) { reqCount++; reqSum += seRequest->req_used; } // cached sound effect if( (seRequest->req_used > 0 || last_cycle[j]) && cached_size < MAX_SE_CACHED ) { cached_index[cached_size++] = j; } } if( reqSum <= chCount ) { // --------- enough for all requests --------// // for( j = 0, seRequest=req_pool; j < total_effect; ++j, ++seRequest) for( k = 0; k < cached_size; ++k) { j = cached_index[k]; seRequest = req_pool + j; last_cycle[j] = 0; for( i = seRequest->req_used-1; i >= 0; --i) { if( seRequest->wave_ptr) { audio_ptr->play_resided_wav( seRequest->wave_ptr, seRequest->play_vol[i]); } else { audio_ptr->play_wav( seRequest->resx_id, seRequest->play_vol[i]); } last_cycle[j]++; chCount--; } } reqSum = 0; reqCount = 0; } else if( reqCount <= chCount ) { // --------- one channel for one sound effect --------// for( k = 0; k < cached_size; ++k) { j = cached_index[k]; seRequest = req_pool + j; last_cycle[j] = 0; if( seRequest->req_used > 0) { i = seRequest->max_entry(); if( seRequest->wave_ptr) { audio_ptr->play_resided_wav( seRequest->wave_ptr, seRequest->play_vol[i]); } else { audio_ptr->play_wav( seRequest->resx_id, seRequest->play_vol[i]); } last_cycle[j]++; } } } else { // -------- not enough for each sound effect ------// // ------- one channel for one sound effect --------// for( k = 0; k < cached_size && biased_se > cached_index[k]; ++k); if( k >= cached_size) k = 0; for( int c = 0; chCount > 0 && c < cached_size; ++c) { if( ++k >= cached_size) k = 0; j = cached_index[k]; seRequest = req_pool + j; if( seRequest->req_used > 0 && !last_cycle[j]) { i = seRequest->max_entry(); if( seRequest->wave_ptr ) { audio_ptr->play_resided_wav( seRequest->wave_ptr, seRequest->play_vol[i]); } else { audio_ptr->play_wav( seRequest->resx_id, seRequest->play_vol[i]); } last_cycle[j]++; chCount--; biased_se = j; } else { last_cycle[j] = 0; } } } clear(); } // ------ End Function SECtrl::flush -------// // ------ Begin Function SECtrl::get_effect_name -------// // // return the name of the sound effect // int j the id of the sound effect // char *SECtrl::get_effect_name(int j) { err_when(!init_flag); err_when( j < 1 || j > total_effect ); if( j > max_sound_effect ) return res_supp.data_name(j - max_sound_effect); else return res_wave.data_name(j); } // ------ End Function SECtrl::get_effect_name -------// // ------ Begin Function SECtrl::search_effect_id -------// // // find the sound effect id of an sound effect // // effectName the name of the effect name // int SECtrl::search_effect_id(char *effectName) { err_when(!init_flag); if( !audio_flag ) return 0; // skip if audio cannot init wave device int idx = res_wave.get_index(effectName); if( idx ) return idx; idx = res_supp.get_index(effectName); if( idx ) return idx + max_sound_effect; return 0; } // ------ End Function SECtrl::search_effect_id -------// // ------ Begin Function SECtrl::search_effect_id -------// // // find the sound effect id of an sound effect // // effectName the name of the effect name // len the size of the effectName // int SECtrl::search_effect_id(char *effectName, int len) { err_when(!init_flag); if( !audio_flag) return 0; // skip if audio cannot init wave device char tmpStr[16]; err_when(len >= 16); memcpy(tmpStr, effectName, len); tmpStr[len] = '\0'; m.rtrim(tmpStr); int idx = res_wave.get_index(tmpStr); if( idx ) return idx; idx = res_supp.get_index(tmpStr); if( idx ) return idx + max_sound_effect; return 0; } // ------ End Function SECtrl::search_effect_id -------// /* // ------ Begin Function SECtrl::sound_volume --------// // // calculate the volume from a location // // locX, locY - location x, y relative to the center of screen // [short] limit - volume is zero if dist > limit // [short] drop - volume is dropped (linearly) to zero when dist = drop // drop > limit // const default_vol_limit = 20; const default_vol_drop = 100; long SECtrl::sound_volume(short locX, short locY) { short dist = max( locX >= 0? locX : -locX, locY >= 0? locY:-locY); err_when( default_vol_drop <= default_vol_limit); if( dist > default_vol_limit) return 0; else return 90 - dist * 90 / default_vol_drop; } long SECtrl::sound_volume(short locX, short locY, short limit, short drop) { short dist = max( locX >= 0? locX : -locX, locY >= 0? locY:-locY); err_when( drop <= limit); if( dist > limit) return 0; else return 90 - dist * 90 / drop; } // ------ End Function SECtrl::sound_volume --------// // ------ Begin Function SECtrl::sound_pan --------// // // calculate the pan setting of a location // // short locX, locY - location x, y relative to the center of screen // short drop - panning is set to extreme value when abs(locX) >= drop // const default_pan_drop = 100; long SECtrl::sound_pan(short locX, short locY) { if( locX >= default_pan_drop ) return 10000; if( locX <= -default_pan_drop ) return -10000; return 10000 / default_pan_drop * locX; } long SECtrl::sound_pan(short locX, short locY, short drop) { if( locX >= drop ) return 10000; if( locX <= -drop ) return -10000; return 10000 * locX / drop; } // ------ End Function SECtrl::sound_pan --------// */ // ------- Begin Function SECtrl::immediate_sound ------------// int SECtrl::immediate_sound(char *soundName, RelVolume relVolume) { if( !config.sound_effect_flag ) return 0; int effectId = search_effect_id(soundName); if( effectId ) { SERequest *seRequest = req_pool + effectId-1; if( seRequest->wave_ptr ) return audio_ptr->play_resided_wav( seRequest->wave_ptr, relVolume); else return audio_ptr->play_wav( seRequest->resx_id, relVolume); } return 0; } // ------- End Function SECtrl::immediate_sound ------------//