00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020 #include "AudioProcess.h"
00021 #include "intrinsics.h"
00022 #include "Object.h"
00023
00024 #include "GameData.h"
00025 #include "SoundFlex.h"
00026 #include "SpeechFlex.h"
00027 #include "AudioSample.h"
00028 #include "AudioMixer.h"
00029
00030 #include "getObject.h"
00031 #include "Item.h"
00032 #include "CameraProcess.h"
00033
00034 #include "IDataSource.h"
00035 #include "ODataSource.h"
00036
00037 using Pentagram::AudioSample;
00038 using Pentagram::AudioMixer;
00039
00040
00041 DEFINE_RUNTIME_CLASSTYPE_CODE(AudioProcess,Process);
00042
00043 AudioProcess * AudioProcess::the_audio_process = 0;
00044
00045 AudioProcess::AudioProcess(void) : paused(0)
00046 {
00047 the_audio_process = this;
00048 type = 1;
00049 }
00050
00051 AudioProcess::~AudioProcess(void)
00052 {
00053 the_audio_process = 0;
00054 }
00055
00056 bool AudioProcess::calculateSoundVolume(ObjId objid, int &lvol, int &rvol) const
00057 {
00058 Item *item = getItem(objid);
00059 if (!item) return false;
00060
00061
00062
00063 sint32 ax, ay, az, ix, iy, iz;
00064 CameraProcess::GetCameraLocation(ax,ay,az);
00065 item->getLocationAbsolute(ix, iy, iz);
00066 ix -= ax; iy -= ay; iz -= az;
00067
00068
00069
00070
00071
00072
00073
00074 int x = (ix - iy)/4;
00075 int y = (ix + iy)/8 - iz;
00076
00077
00078 int limit = 350*350;
00079 int dist = limit-(x*x + y*y);
00080 if (dist < 0) dist = 0;
00081 dist = (dist*256)/limit;
00082
00083 int lbal = 160;
00084 int rbal = 160;
00085
00086 if (x < 0) {
00087 if (x < -160) rbal = 0;
00088 else rbal = x + 160;
00089 }
00090 else if (x > 0) {
00091 if (x > 160) lbal = 0;
00092 else lbal = 160 -x;
00093 }
00094
00095 lvol = (dist*lbal)/160;
00096 rvol = (dist*rbal)/160;
00097
00098 return true;
00099 }
00100
00101 bool AudioProcess::run(const uint32)
00102 {
00103 AudioMixer *mixer = AudioMixer::get_instance();
00104
00105
00106 std::list<SampleInfo>::iterator it;
00107 for (it = sample_info.begin(); it != sample_info.end(); ) {
00108 bool finished = false;
00109 if (!mixer->isPlaying(it->channel)) {
00110 if (it->sfxnum == -1)
00111 finished = !continueSpeech(*it);
00112 else
00113 finished = true;
00114 }
00115
00116 if (finished)
00117 it = sample_info.erase(it);
00118 else {
00119
00120 int lvol = 256, rvol = 256;
00121 if (it->sfxnum != -1 && it->objid) calculateSoundVolume(it->objid, lvol,rvol);
00122 mixer->setVolume(it->channel, (lvol*it->volume)/256,(rvol*it->volume)/256);
00123
00124 ++it;
00125 }
00126 }
00127
00128 return false;
00129 }
00130
00131 bool AudioProcess::continueSpeech(SampleInfo& si)
00132 {
00133 assert(si.sfxnum == -1);
00134
00135 SpeechFlex *speechflex;
00136 speechflex = GameData::get_instance()->getSpeechFlex(si.priority);
00137 if (!speechflex) return false;
00138
00139 if (si.curspeech_end >= si.barked.size()) return false;
00140
00141 si.curspeech_start = si.curspeech_end;
00142 int index = speechflex->getIndexForPhrase(si.barked,
00143 si.curspeech_start,
00144 si.curspeech_end);
00145 if (!index) return false;
00146
00147 AudioSample *sample = speechflex->getSample(index);
00148 if (!sample) return false;
00149
00150
00151 si.channel = -1;
00152 int channel = playSample(sample,200,0);
00153 if (channel == -1)
00154 return false;
00155
00156 si.channel = channel;
00157 return true;
00158 }
00159
00160
00161 void AudioProcess::saveData(ODataSource* ods)
00162 {
00163 Process::saveData(ods);
00164
00165 ods->write1(static_cast<uint8>(sample_info.size()));
00166
00167 std::list<SampleInfo>::iterator it;
00168 for (it = sample_info.begin(); it != sample_info.end(); ++it) {
00169 ods->write2(it->sfxnum);
00170 ods->write2(it->priority);
00171 ods->write2(it->objid);
00172 ods->write2(it->loops);
00173 ods->write4(it->pitch_shift);
00174 ods->write2(it->volume);
00175
00176 if (it->sfxnum == -1)
00177 {
00178 ods->write4(static_cast<uint32>(it->barked.size()));
00179 ods->write(it->barked.c_str(),static_cast<uint32>(it->barked.size()));
00180 }
00181 }
00182 }
00183
00184 bool AudioProcess::loadData(IDataSource* ids, uint32 version)
00185 {
00186 if (!Process::loadData(ids, version)) return false;
00187
00188 uint32 count = ids->read1();
00189
00190 while (count--) {
00191 sint16 sfxnum = ids->read2();
00192 sint16 priority = ids->read2();
00193 sint16 objid = ids->read2();
00194 sint16 loops = ids->read2();
00195 uint32 pitch_shift = ids->read4();
00196 uint16 volume = ids->read2();
00197
00198 if (sfxnum != -1)
00199 playSFX(sfxnum,priority,objid,loops,false,pitch_shift,volume);
00200
00201 else {
00202 uint32 slen = ids->read4();
00203
00204 char* buf = new char[slen+1];
00205 ids->read(buf, slen);
00206 buf[slen] = 0;
00207 std::string text = buf;
00208 delete[] buf;
00209
00210 playSpeech(text,priority,objid,pitch_shift,volume);
00211 }
00212 }
00213
00214 return true;
00215 }
00216
00217 int AudioProcess::playSample(AudioSample* sample, int priority, int loops, uint32 pitch_shift, int lvol, int rvol)
00218 {
00219 AudioMixer *mixer = AudioMixer::get_instance();
00220 int channel = mixer->playSample(sample,loops,priority,false,pitch_shift,lvol,rvol);
00221
00222 if (channel == -1) return channel;
00223
00224
00225 std::list<SampleInfo>::iterator it;
00226 for (it = sample_info.begin(); it != sample_info.end(); ) {
00227 if (it->channel == channel) {
00228 it = sample_info.erase(it);
00229 }
00230 else {
00231 ++it;
00232 }
00233 }
00234
00235 return channel;
00236 }
00237
00238 void AudioProcess::playSFX(int sfxnum, int priority, ObjId objid, int loops,
00239 bool no_duplicates, uint32 pitch_shift, uint16 volume)
00240 {
00241
00242
00243 SoundFlex *soundflx= GameData::get_instance()->getSoundFlex();
00244
00245 AudioMixer *mixer = AudioMixer::get_instance();
00246
00247 if (no_duplicates) {
00248 std::list<SampleInfo>::iterator it;
00249 for (it = sample_info.begin(); it != sample_info.end(); ) {
00250 if (it->sfxnum == sfxnum && it->objid == objid &&
00251 it->loops == loops)
00252 {
00253
00254
00255
00256 if (mixer->isPlaying(it->channel))
00257 {
00258 pout << "Sound already playing" << std::endl;
00259 return;
00260 }
00261 else {
00262 it = sample_info.erase(it);
00263 continue;
00264 }
00265 }
00266
00267 ++it;
00268 }
00269 }
00270
00271 AudioSample *sample = soundflx->getSample(sfxnum);
00272 if (!sample) return;
00273
00274 int lvol=256, rvol=256;
00275 if (objid) calculateSoundVolume(objid, lvol, rvol);
00276
00277 int channel = playSample(sample,priority,loops,pitch_shift,(lvol*volume)/256,(rvol*volume)/256);
00278 if (channel == -1) return;
00279
00280
00281 sample_info.push_back(SampleInfo(sfxnum,priority,objid,loops,channel,pitch_shift,volume));
00282 }
00283
00284 void AudioProcess::stopSFX(int sfxnum, ObjId objid)
00285 {
00286
00287
00288 AudioMixer *mixer = AudioMixer::get_instance();
00289
00290 std::list<SampleInfo>::iterator it;
00291 for (it = sample_info.begin(); it != sample_info.end(); ) {
00292 if (it->sfxnum == sfxnum && it->objid == objid) {
00293 if (mixer->isPlaying(it->channel)) mixer->stopSample(it->channel);
00294 it = sample_info.erase(it);
00295 }
00296 else {
00297 ++it;
00298 }
00299 }
00300 }
00301
00302 bool AudioProcess::isSFXPlaying(int sfxnum)
00303 {
00304
00305
00306 std::list<SampleInfo>::iterator it;
00307 for (it = sample_info.begin(); it != sample_info.end(); ++it) {
00308 if (it->sfxnum == sfxnum)
00309 return true;
00310 }
00311
00312 return false;
00313 }
00314
00315 void AudioProcess::setVolumeSFX(int sfxnum, uint8 volume)
00316 {
00317
00318 AudioMixer *mixer = AudioMixer::get_instance();
00319
00320 std::list<SampleInfo>::iterator it;
00321 for (it = sample_info.begin(); it != sample_info.end(); ++it) {
00322 if (it->sfxnum == sfxnum && it->sfxnum != -1) {
00323 it->volume = volume;
00324
00325 int lvol = 256, rvol = 256;
00326 if (it->objid) calculateSoundVolume(it->objid, lvol,rvol);
00327 mixer->setVolume(it->channel, (lvol*it->volume)/256,(rvol*it->volume)/256);
00328 }
00329 }
00330 }
00331
00332
00333
00334
00335
00336 bool AudioProcess::playSpeech(std::string &barked, int shapenum, ObjId objid, uint32 pitch_shift, uint16 volume)
00337 {
00338 SpeechFlex *speechflex = GameData::get_instance()->getSpeechFlex(shapenum);
00339
00340 if (!speechflex) return false;
00341
00342 AudioMixer *mixer = AudioMixer::get_instance();
00343
00344 std::list<SampleInfo>::iterator it;
00345 for (it = sample_info.begin(); it != sample_info.end();) {
00346
00347 if (it->sfxnum == -1 && it->barked == barked &&
00348 it->priority == shapenum && it->objid == objid) {
00349
00350 if (mixer->isPlaying(it->channel)) {
00351 pout << "Speech already playing" << std::endl;
00352 return true;
00353 }
00354 else {
00355 it = sample_info.erase(it);
00356 continue;
00357 }
00358 }
00359
00360 ++it;
00361 }
00362
00363 uint32 speech_start = 0;
00364 uint32 speech_end;
00365 int index = speechflex->getIndexForPhrase(barked,speech_start,speech_end);
00366 if (!index) return false;
00367
00368 AudioSample *sample = speechflex->getSample(index);
00369 if (!sample) return false;
00370
00371 int channel = playSample(sample,200,0,pitch_shift,volume,volume);
00372
00373 if (channel == -1) return false;
00374
00375
00376 sample_info.push_back(SampleInfo(barked,shapenum,objid,channel,
00377 speech_start,speech_end,pitch_shift,volume));
00378
00379 return true;
00380 }
00381
00382 uint32 AudioProcess::getSpeechLength(std::string &barked, int shapenum) const
00383 {
00384 SpeechFlex *speechflex = GameData::get_instance()->getSpeechFlex(shapenum);
00385 if (!speechflex) return 0;
00386
00387 return speechflex->getSpeechLength(barked);
00388 }
00389
00390
00391 void AudioProcess::stopSpeech(std::string &barked, int shapenum, ObjId objid)
00392 {
00393 AudioMixer *mixer = AudioMixer::get_instance();
00394
00395 std::list<SampleInfo>::iterator it;
00396 for (it = sample_info.begin(); it != sample_info.end(); ) {
00397 if (it->sfxnum == -1 && it->priority == shapenum &&
00398 it->objid == objid && it->barked == barked)
00399 {
00400 if (mixer->isPlaying(it->channel)) mixer->stopSample(it->channel);
00401 it = sample_info.erase(it);
00402 }
00403 else {
00404 ++it;
00405 }
00406 }
00407 }
00408
00409 bool AudioProcess::isSpeechPlaying(std::string &barked, int shapenum)
00410 {
00411 std::list<SampleInfo>::iterator it;
00412 for (it = sample_info.begin(); it != sample_info.end(); ++it) {
00413 if (it->sfxnum == -1 && it->priority == shapenum &&
00414 it->barked == barked)
00415 {
00416 return true;
00417 }
00418 }
00419
00420 return false;
00421 }
00422
00423 void AudioProcess::pauseAllSamples()
00424 {
00425 paused++;
00426 if (paused != 1) return;
00427
00428 AudioMixer *mixer = AudioMixer::get_instance();
00429
00430 std::list<SampleInfo>::iterator it;
00431 for (it = sample_info.begin(); it != sample_info.end(); ) {
00432 if (mixer->isPlaying(it->channel)) {
00433 mixer->setPaused(it->channel,true);
00434 ++it;
00435 }
00436 else {
00437 it = sample_info.erase(it);
00438 }
00439
00440 }
00441
00442 }
00443
00444 void AudioProcess::unpauseAllSamples()
00445 {
00446 paused--;
00447 if (paused != 0) return;
00448
00449 AudioMixer *mixer = AudioMixer::get_instance();
00450
00451 std::list<SampleInfo>::iterator it;
00452 for (it = sample_info.begin(); it != sample_info.end(); ) {
00453 if (mixer->isPlaying(it->channel)) {
00454 mixer->setPaused(it->channel,false);
00455 ++it;
00456 }
00457 else {
00458 it = sample_info.erase(it);
00459 }
00460
00461 }
00462
00463 }
00464
00465 void AudioProcess::stopAllExceptSpeech()
00466 {
00467 AudioMixer *mixer = AudioMixer::get_instance();
00468
00469 std::list<SampleInfo>::iterator it;
00470 for (it = sample_info.begin(); it != sample_info.end(); ) {
00471 if (it->barked.empty()) {
00472 if (mixer->isPlaying(it->channel)) mixer->stopSample(it->channel);
00473 it = sample_info.erase(it);
00474 } else {
00475 ++it;
00476 }
00477 }
00478 }
00479
00480
00481
00482
00483
00484 uint32 AudioProcess::I_playSFX(const uint8* args, unsigned int argsize)
00485 {
00486 ARG_SINT16(sfxnum);
00487
00488 sint16 priority = 0x60;
00489 if (argsize >= 4) {
00490 ARG_SINT16(priority_);
00491 priority = priority_;
00492 }
00493
00494 ObjId objid = 0;
00495 if (argsize == 6) {
00496 ARG_OBJID(objid_);
00497 objid = objid_;
00498 }
00499
00500 AudioProcess *ap = AudioProcess::get_instance();
00501 if(ap) ap->playSFX(sfxnum,priority,objid,0);
00502 else perr << "Error: No AudioProcess" << std::endl;
00503
00504 return 0;
00505 }
00506
00507 uint32 AudioProcess::I_playAmbientSFX(const uint8* args, unsigned int argsize)
00508 {
00509 ARG_SINT16(sfxnum);
00510
00511 sint16 priority = 0x60;
00512 if (argsize >= 4) {
00513 ARG_SINT16(priority_);
00514 priority = priority_;
00515 }
00516
00517 ObjId objid = 0;
00518 if (argsize == 6) {
00519 ARG_OBJID(objid_);
00520 objid = objid_;
00521 }
00522
00523
00524 AudioProcess *ap = AudioProcess::get_instance();
00525 if(ap) ap->playSFX(sfxnum,priority,objid,-1,true);
00526 else perr << "Error: No AudioProcess" << std::endl;
00527
00528 return 0;
00529 }
00530
00531 uint32 AudioProcess::I_isSFXPlaying(const uint8* args, unsigned int argsize)
00532 {
00533 ARG_SINT16(sfxnum);
00534
00535 AudioProcess *ap = AudioProcess::get_instance();
00536 if(ap) return ap->isSFXPlaying(sfxnum);
00537 else perr << "Error: No AudioProcess" << std::endl;
00538 return 0;
00539 }
00540
00541 uint32 AudioProcess::I_setVolumeSFX(const uint8* args, unsigned int )
00542 {
00543
00544 ARG_SINT16(sfxnum);
00545 ARG_UINT8(volume);
00546
00547 AudioProcess *ap = AudioProcess::get_instance();
00548 if(ap) ap->setVolumeSFX(sfxnum, volume);
00549 else perr << "Error: No AudioProcess" << std::endl;
00550
00551 return 0;
00552 }
00553
00554 uint32 AudioProcess::I_stopSFX(const uint8* args, unsigned int argsize)
00555 {
00556 ARG_SINT16(sfxnum);
00557
00558 ObjId objid = 0;
00559 if (argsize == 4) {
00560 ARG_OBJID(objid_);
00561 objid = objid_;
00562 }
00563
00564 AudioProcess *ap = AudioProcess::get_instance();
00565 if(ap) ap->stopSFX(sfxnum,objid);
00566 else perr << "Error: No AudioProcess" << std::endl;
00567
00568 return 0;
00569 }
00570
00571
00572 void AudioProcess::ConCmd_listSFX(const Console::ArgvType &argv)
00573 {
00574 AudioProcess *ap = AudioProcess::get_instance();
00575 if (!ap) {
00576 perr << "Error: No AudioProcess" << std::endl;
00577 return;
00578 }
00579
00580 std::list<SampleInfo>::iterator it;
00581 for (it = ap->sample_info.begin(); it != ap->sample_info.end(); ++it) {
00582 pout.printf("Sample: num %d, obj %d, loop %d, prio %d",
00583 it->sfxnum, it->objid, it->loops, it->priority);
00584 if (!it->barked.empty()) {
00585 pout << ", speech: \"" << it->barked.substr(it->curspeech_start, it->curspeech_end - it->curspeech_start) << "\"";
00586 }
00587 pout << std::endl;
00588 }
00589 }
00590
00591
00592 void AudioProcess::ConCmd_stopSFX(const Console::ArgvType &argv)
00593 {
00594 AudioProcess *ap = AudioProcess::get_instance();
00595 if (!ap) {
00596 perr << "Error: No AudioProcess" << std::endl;
00597 return;
00598 }
00599
00600 switch (argv.size() - 1) {
00601 case 1:
00602 ap->stopSFX(strtol(argv[1].c_str(), 0, 0), 0);
00603 break;
00604 case 2:
00605 ap->stopSFX(strtol(argv[1].c_str(), 0, 0),
00606 strtol(argv[2].c_str(), 0, 0));
00607 break;
00608 default:
00609 pout << "usage: stopSFX <sfxnum> [<objid>]" << std::endl;
00610 break;
00611 }
00612 }
00613
00614
00615 void AudioProcess::ConCmd_playSFX(const Console::ArgvType &argv)
00616 {
00617 AudioProcess *ap = AudioProcess::get_instance();
00618 if (!ap) {
00619 perr << "Error: No AudioProcess" << std::endl;
00620 return;
00621 }
00622
00623 switch (argv.size() - 1) {
00624 case 1:
00625 ap->playSFX(strtol(argv[1].c_str(), 0, 0), 0x60, 0, 0);
00626 break;
00627 default:
00628 pout << "usage: playSFX <sfxnum>" << std::endl;
00629 break;
00630 }
00631 }