1 //=============================================================================
2 //
3 // Adventure Game Studio (AGS)
4 //
5 // Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
6 // The full list of copyright holders can be found in the Copyright.txt
7 // file, which is part of this source code distribution.
8 //
9 // The AGS source code is provided under the Artistic License 2.0.
10 // A copy of this license can be found in the file License.txt and at
11 // http://www.opensource.org/licenses/artistic-license-2.0.php
12 //
13 //=============================================================================
14
15 #include <stdio.h>
16 #include "ac/common.h"
17 #include "ac/game.h"
18 #include "ac/gamesetup.h"
19 #include "ac/gamesetupstruct.h"
20 #include "ac/gamestate.h"
21 #include "ac/global_audio.h"
22 #include "ac/lipsync.h"
23 #include "ac/path_helper.h"
24 #include "ac/roomstruct.h"
25 #include "debug/debug_log.h"
26 #include "debug/debugger.h"
27 #include "main/engine.h"
28 #include "media/audio/audio.h"
29 #include "media/audio/sound.h"
30
31 extern GameSetup usetup;
32 extern GameState play;
33 extern GameSetupStruct game;
34 extern roomstruct thisroom;
35 extern SpeechLipSyncLine *splipsync;
36 extern int numLipLines, curLipLine, curLipLinePhoneme;
37
StopAmbientSound(int channel)38 void StopAmbientSound (int channel) {
39 if ((channel < 0) || (channel >= MAX_SOUND_CHANNELS))
40 quit("!StopAmbientSound: invalid channel");
41
42 if (ambient[channel].channel == 0)
43 return;
44
45 stop_and_destroy_channel(channel);
46 ambient[channel].channel = 0;
47 }
48
PlayAmbientSound(int channel,int sndnum,int vol,int x,int y)49 void PlayAmbientSound (int channel, int sndnum, int vol, int x, int y) {
50 // the channel parameter is to allow multiple ambient sounds in future
51 if ((channel < 1) || (channel == SCHAN_SPEECH) || (channel >= MAX_SOUND_CHANNELS))
52 quit("!PlayAmbientSound: invalid channel number");
53 if ((vol < 1) || (vol > 255))
54 quit("!PlayAmbientSound: volume must be 1 to 255");
55
56 ScriptAudioClip *aclip = GetAudioClipForOldStyleNumber(game, false, sndnum);
57 if (aclip && !is_audiotype_allowed_to_play((AudioFileType)aclip->fileType))
58 return;
59
60 // only play the sound if it's not already playing
61 if ((ambient[channel].channel < 1) || (channels[ambient[channel].channel] == NULL) ||
62 (channels[ambient[channel].channel]->done == 1) ||
63 (ambient[channel].num != sndnum)) {
64
65 StopAmbientSound(channel);
66 // in case a normal non-ambient sound was playing, stop it too
67 stop_and_destroy_channel(channel);
68
69 SOUNDCLIP *asound = aclip ? load_sound_and_play(aclip, true) : NULL;
70 if (asound == NULL) {
71 debug_script_warn ("Cannot load ambient sound %d", sndnum);
72 debug_script_log("FAILED to load ambient sound %d", sndnum);
73 return;
74 }
75
76 debug_script_log("Playing ambient sound %d on channel %d", sndnum, channel);
77 ambient[channel].channel = channel;
78 channels[channel] = asound;
79 channels[channel]->priority = 15; // ambient sound higher priority than normal sfx
80 }
81 // calculate the maximum distance away the player can be, using X
82 // only (since X centred is still more-or-less total Y)
83 ambient[channel].maxdist = ((x > thisroom.width / 2) ? x : (thisroom.width - x)) - AMBIENCE_FULL_DIST;
84 ambient[channel].num = sndnum;
85 ambient[channel].x = x;
86 ambient[channel].y = y;
87 ambient[channel].vol = vol;
88 update_ambient_sound_vol();
89 }
90
IsChannelPlaying(int chan)91 int IsChannelPlaying(int chan) {
92 if (play.fast_forward)
93 return 0;
94
95 if ((chan < 0) || (chan >= MAX_SOUND_CHANNELS))
96 quit("!IsChannelPlaying: invalid sound channel");
97
98 if ((channels[chan] != NULL) && (channels[chan]->done == 0))
99 return 1;
100
101 return 0;
102 }
103
IsSoundPlaying()104 int IsSoundPlaying() {
105 if (play.fast_forward)
106 return 0;
107
108 // find if there's a sound playing
109 for (int i = SCHAN_NORMAL; i < numSoundChannels; i++) {
110 if ((channels[i] != NULL) && (channels[i]->done == 0))
111 return 1;
112 }
113
114 return 0;
115 }
116
117 // returns -1 on failure, channel number on success
PlaySoundEx(int val1,int channel)118 int PlaySoundEx(int val1, int channel) {
119
120 if (debug_flags & DBG_NOSFX)
121 return -1;
122
123 ScriptAudioClip *aclip = GetAudioClipForOldStyleNumber(game, false, val1);
124 if (aclip && !is_audiotype_allowed_to_play((AudioFileType)aclip->fileType))
125 return -1; // if sound is off, ignore it
126
127 if ((channel < SCHAN_NORMAL) || (channel >= MAX_SOUND_CHANNELS))
128 quit("!PlaySoundEx: invalid channel specified, must be 3-7");
129
130 // if an ambient sound is playing on this channel, abort it
131 StopAmbientSound(channel);
132
133 if (val1 < 0) {
134 stop_and_destroy_channel (channel);
135 return -1;
136 }
137 // if skipping a cutscene, don't try and play the sound
138 if (play.fast_forward)
139 return -1;
140
141 // that sound is already in memory, play it
142 if (!psp_audio_multithreaded)
143 {
144 if ((last_sound_played[channel] == val1) && (channels[channel] != NULL)) {
145 debug_script_log("Playing sound %d on channel %d; cached", val1, channel);
146 channels[channel]->restart();
147 channels[channel]->set_volume (play.sound_volume);
148 return channel;
149 }
150 }
151
152 // free the old sound
153 stop_and_destroy_channel (channel);
154 debug_script_log("Playing sound %d on channel %d", val1, channel);
155
156 last_sound_played[channel] = val1;
157
158 SOUNDCLIP *soundfx = aclip ? load_sound_and_play(aclip, false) : NULL;
159 if (soundfx == NULL) {
160 debug_script_warn("Sound sample load failure: cannot load sound %d", val1);
161 debug_script_log("FAILED to load sound %d", val1);
162 return -1;
163 }
164
165 channels[channel] = soundfx;
166 channels[channel]->priority = 10;
167 channels[channel]->set_volume (play.sound_volume);
168 return channel;
169 }
170
StopAllSounds(int evenAmbient)171 void StopAllSounds(int evenAmbient) {
172 // backwards-compatible hack -- stop Type 3 (default Sound Type)
173 Game_StopAudio(3);
174
175 if (evenAmbient)
176 Game_StopAudio(1);
177 }
178
PlayMusicResetQueue(int newmus)179 void PlayMusicResetQueue(int newmus) {
180 play.music_queue_size = 0;
181 newmusic(newmus);
182 }
183
SeekMIDIPosition(int position)184 void SeekMIDIPosition (int position) {
185 if (play.silent_midi)
186 midi_seek (position);
187 if (current_music_type == MUS_MIDI) {
188 midi_seek(position);
189 debug_script_log("Seek MIDI position to %d", position);
190 }
191 }
192
GetMIDIPosition()193 int GetMIDIPosition () {
194 if (play.silent_midi)
195 return midi_pos;
196 if (current_music_type != MUS_MIDI)
197 return -1;
198 if (play.fast_forward)
199 return 99999;
200
201 return midi_pos;
202 }
203
IsMusicPlaying()204 int IsMusicPlaying() {
205 // in case they have a "while (IsMusicPlaying())" loop
206 if ((play.fast_forward) && (play.skip_until_char_stops < 0))
207 return 0;
208
209 if (current_music_type != 0) {
210 if (channels[SCHAN_MUSIC] == NULL)
211 current_music_type = 0;
212 else if (channels[SCHAN_MUSIC]->done == 0)
213 return 1;
214 else if ((crossFading > 0) && (channels[crossFading] != NULL))
215 return 1;
216 return 0;
217 }
218
219 return 0;
220 }
221
PlayMusicQueued(int musnum)222 int PlayMusicQueued(int musnum) {
223
224 // Just get the queue size
225 if (musnum < 0)
226 return play.music_queue_size;
227
228 if ((IsMusicPlaying() == 0) && (play.music_queue_size == 0)) {
229 newmusic(musnum);
230 return 0;
231 }
232
233 if (play.music_queue_size >= MAX_QUEUED_MUSIC) {
234 debug_script_log("Too many queued music, cannot add %d", musnum);
235 return 0;
236 }
237
238 if ((play.music_queue_size > 0) &&
239 (play.music_queue[play.music_queue_size - 1] >= QUEUED_MUSIC_REPEAT)) {
240 quit("!PlayMusicQueued: cannot queue music after a repeating tune has been queued");
241 }
242
243 if (play.music_repeat) {
244 debug_script_log("Queuing music %d to loop", musnum);
245 musnum += QUEUED_MUSIC_REPEAT;
246 }
247 else {
248 debug_script_log("Queuing music %d", musnum);
249 }
250
251 play.music_queue[play.music_queue_size] = musnum;
252 play.music_queue_size++;
253
254 if (play.music_queue_size == 1) {
255
256 clear_music_cache();
257
258 cachedQueuedMusic = load_music_from_disk(musnum, (play.music_repeat > 0));
259 }
260
261 return play.music_queue_size;
262 }
263
scr_StopMusic()264 void scr_StopMusic() {
265 play.music_queue_size = 0;
266 stopmusic();
267 }
268
SeekMODPattern(int patnum)269 void SeekMODPattern(int patnum) {
270 if (current_music_type == MUS_MOD && channels[SCHAN_MUSIC]) {
271 channels[SCHAN_MUSIC]->seek (patnum);
272 debug_script_log("Seek MOD/XM to pattern %d", patnum);
273 }
274 }
SeekMP3PosMillis(int posn)275 void SeekMP3PosMillis (int posn) {
276 if (current_music_type) {
277 debug_script_log("Seek MP3/OGG to %d ms", posn);
278 if (crossFading && channels[crossFading])
279 channels[crossFading]->seek (posn);
280 else if (channels[SCHAN_MUSIC])
281 channels[SCHAN_MUSIC]->seek (posn);
282 }
283 }
284
GetMP3PosMillis()285 int GetMP3PosMillis () {
286 // in case they have "while (GetMP3PosMillis() < 5000) "
287 if (play.fast_forward)
288 return 999999;
289
290 if (current_music_type && channels[SCHAN_MUSIC]) {
291 int result = channels[SCHAN_MUSIC]->get_pos_ms();
292 if (result >= 0)
293 return result;
294
295 return channels[SCHAN_MUSIC]->get_pos ();
296 }
297
298 return 0;
299 }
300
SetMusicVolume(int newvol)301 void SetMusicVolume(int newvol) {
302 if ((newvol < kRoomVolumeMin) || (newvol > kRoomVolumeMax))
303 quitprintf("!SetMusicVolume: invalid volume number. Must be from %d to %d.", kRoomVolumeMin, kRoomVolumeMax);
304 thisroom.options[ST_VOLUME]=newvol;
305 update_music_volume();
306 }
307
SetMusicMasterVolume(int newvol)308 void SetMusicMasterVolume(int newvol) {
309 const int min_volume = loaded_game_file_version < kGameVersion_330 ? 0 :
310 -LegacyMusicMasterVolumeAdjustment - (kRoomVolumeMax * LegacyRoomVolumeFactor);
311 if ((newvol < min_volume) | (newvol>100))
312 quitprintf("!SetMusicMasterVolume: invalid volume - must be from %d to %d", min_volume, 100);
313 play.music_master_volume=newvol+LegacyMusicMasterVolumeAdjustment;
314 update_music_volume();
315 }
316
SetSoundVolume(int newvol)317 void SetSoundVolume(int newvol) {
318 if ((newvol<0) | (newvol>255))
319 quit("!SetSoundVolume: invalid volume - must be from 0-255");
320 play.sound_volume = newvol;
321 Game_SetAudioTypeVolume(AUDIOTYPE_LEGACY_AMBIENT_SOUND, (newvol * 100) / 255, VOL_BOTH);
322 Game_SetAudioTypeVolume(AUDIOTYPE_LEGACY_SOUND, (newvol * 100) / 255, VOL_BOTH);
323 update_ambient_sound_vol ();
324 }
325
SetChannelVolume(int chan,int newvol)326 void SetChannelVolume(int chan, int newvol) {
327 if ((newvol<0) || (newvol>255))
328 quit("!SetChannelVolume: invalid volume - must be from 0-255");
329 if ((chan < 0) || (chan >= MAX_SOUND_CHANNELS))
330 quit("!SetChannelVolume: invalid channel id");
331
332 if ((channels[chan] != NULL) && (channels[chan]->done == 0)) {
333 if (chan == ambient[chan].channel) {
334 ambient[chan].vol = newvol;
335 update_ambient_sound_vol();
336 }
337 else
338 channels[chan]->set_volume (newvol);
339 }
340 }
341
SetDigitalMasterVolume(int newvol)342 void SetDigitalMasterVolume (int newvol) {
343 if ((newvol<0) | (newvol>100))
344 quit("!SetDigitalMasterVolume: invalid volume - must be from 0-100");
345 play.digital_master_volume = newvol;
346 set_volume ((newvol * 255) / 100, -1);
347 }
348
GetCurrentMusic()349 int GetCurrentMusic() {
350 return play.cur_music_number;
351 }
352
SetMusicRepeat(int loopflag)353 void SetMusicRepeat(int loopflag) {
354 play.music_repeat=loopflag;
355 }
356
PlayMP3File(const char * filename)357 void PlayMP3File (const char *filename) {
358 if (strlen(filename) >= PLAYMP3FILE_MAX_FILENAME_LEN)
359 quit("!PlayMP3File: filename too long");
360
361 debug_script_log("PlayMP3File %s", filename);
362
363 AssetPath asset_name("", filename);
364
365 int useChan = prepare_for_new_music ();
366 bool doLoop = (play.music_repeat > 0);
367
368 if ((channels[useChan] = my_load_static_ogg(asset_name, 150, doLoop)) != NULL) {
369 channels[useChan]->play();
370 current_music_type = MUS_OGG;
371 play.cur_music_number = 1000;
372 // save the filename (if it's not what we were supplied with)
373 if (filename != &play.playmp3file_name[0])
374 strcpy (play.playmp3file_name, filename);
375 }
376 else if ((channels[useChan] = my_load_static_mp3(asset_name, 150, doLoop)) != NULL) {
377 channels[useChan]->play();
378 current_music_type = MUS_MP3;
379 play.cur_music_number = 1000;
380 // save the filename (if it's not what we were supplied with)
381 if (filename != &play.playmp3file_name[0])
382 strcpy (play.playmp3file_name, filename);
383 }
384 else
385 debug_script_warn ("PlayMP3File: file '%s' not found or cannot play", filename);
386
387 post_new_music_check(useChan);
388
389 update_music_volume();
390 }
391
PlaySilentMIDI(int mnum)392 void PlaySilentMIDI (int mnum) {
393 if (current_music_type == MUS_MIDI)
394 quit("!PlaySilentMIDI: proper midi music is in progress");
395
396 set_volume (-1, 0);
397 play.silent_midi = mnum;
398 play.silent_midi_channel = SCHAN_SPEECH;
399 stop_and_destroy_channel(play.silent_midi_channel);
400 channels[play.silent_midi_channel] = load_sound_clip_from_old_style_number(true, mnum, false);
401 if (channels[play.silent_midi_channel] == NULL)
402 {
403 quitprintf("!PlaySilentMIDI: failed to load aMusic%d", mnum);
404 }
405 channels[play.silent_midi_channel]->play();
406 channels[play.silent_midi_channel]->set_volume_percent(0);
407 }
408
SetSpeechVolume(int newvol)409 void SetSpeechVolume(int newvol) {
410 if ((newvol<0) | (newvol>255))
411 quit("!SetSpeechVolume: invalid volume - must be from 0-255");
412
413 if (channels[SCHAN_SPEECH])
414 channels[SCHAN_SPEECH]->set_volume (newvol);
415
416 play.speech_volume = newvol;
417 }
418
__scr_play_speech(int who,int which)419 void __scr_play_speech(int who, int which) {
420 // *** implement this - needs to call stop_speech as well
421 // to reset the volume
422 quit("PlaySpeech not yet implemented");
423 }
424
425 // 0 = text only
426 // 1 = voice & text
427 // 2 = voice only
SetVoiceMode(int newmod)428 void SetVoiceMode (int newmod) {
429 if ((newmod < 0) | (newmod > 2))
430 quit("!SetVoiceMode: invalid mode number (must be 0,1,2)");
431 // If speech is turned off, store the mode anyway in case the
432 // user adds the VOX file later
433 if (play.want_speech < 0)
434 play.want_speech = (-newmod) - 1;
435 else
436 play.want_speech = newmod;
437 }
438
GetVoiceMode()439 int GetVoiceMode()
440 {
441 return play.want_speech >= 0 ? play.want_speech : -(play.want_speech + 1);
442 }
443
IsVoxAvailable()444 int IsVoxAvailable() {
445 if (play.want_speech < 0)
446 return 0;
447 return 1;
448 }
449
IsMusicVoxAvailable()450 int IsMusicVoxAvailable () {
451 return play.separate_music_lib;
452 }
453
play_speech(int charid,int sndid)454 int play_speech(int charid,int sndid) {
455 stop_and_destroy_channel (SCHAN_SPEECH);
456
457 // don't play speech if we're skipping a cutscene
458 if (play.fast_forward)
459 return 0;
460 if ((play.want_speech < 1) || (speech_file.IsEmpty()))
461 return 0;
462
463 SOUNDCLIP *speechmp3;
464 String script_name;
465
466 if (charid >= 0) {
467 // append the first 4 characters of the script name to the filename
468 if (game.chars[charid].scrname[0] == 'c')
469 script_name.SetString(&game.chars[charid].scrname[1], 4);
470 else
471 script_name.SetString(game.chars[charid].scrname, 4);
472 }
473 else
474 script_name = "NARR";
475
476 // append the speech number and create voice file name
477 String voice_file = String::FromFormat("%s%d", script_name.GetCStr(), sndid);
478
479 int ii; // Compare the base file name to the .pam file name
480 curLipLine = -1; // See if we have voice lip sync for this line
481 curLipLinePhoneme = -1;
482 for (ii = 0; ii < numLipLines; ii++) {
483 if (stricmp(splipsync[ii].filename, voice_file) == 0) {
484 curLipLine = ii;
485 break;
486 }
487 }
488 // if the lip-sync is being used for voice sync, disable
489 // the text-related lipsync
490 if (numLipLines > 0)
491 game.options[OPT_LIPSYNCTEXT] = 0;
492
493 String asset_name = voice_file;
494 asset_name.Append(".wav");
495 speechmp3 = my_load_wave(get_voice_over_assetpath(asset_name), play.speech_volume, 0);
496
497 if (speechmp3 == NULL) {
498 asset_name.ReplaceMid(asset_name.GetLength() - 3, 3, "ogg");
499 speechmp3 = my_load_ogg(get_voice_over_assetpath(asset_name), play.speech_volume);
500 }
501
502 if (speechmp3 == NULL) {
503 asset_name.ReplaceMid(asset_name.GetLength() - 3, 3, "mp3");
504 speechmp3 = my_load_mp3(get_voice_over_assetpath(asset_name), play.speech_volume);
505 }
506
507 if (speechmp3 != NULL) {
508 if (speechmp3->play() == 0)
509 speechmp3 = NULL;
510 }
511
512 if (speechmp3 == NULL) {
513 debug_script_warn("Speech load failure: '%s'", voice_file.GetCStr());
514 curLipLine = -1;
515 return 0;
516 }
517
518 channels[SCHAN_SPEECH] = speechmp3;
519 play.music_vol_was = play.music_master_volume;
520
521 // Negative value means set exactly; positive means drop that amount
522 if (play.speech_music_drop < 0)
523 play.music_master_volume = -play.speech_music_drop;
524 else
525 play.music_master_volume -= play.speech_music_drop;
526
527 apply_volume_drop_modifier(true);
528 update_music_volume();
529 update_music_at = 0;
530 mvolcounter = 0;
531
532 update_ambient_sound_vol();
533
534 // change Sierra w/bgrnd to Sierra without background when voice
535 // is available (for Tierra)
536 if ((game.options[OPT_SPEECHTYPE] == 2) && (play.no_textbg_when_voice > 0)) {
537 game.options[OPT_SPEECHTYPE] = 1;
538 play.no_textbg_when_voice = 2;
539 }
540
541 return 1;
542 }
543
stop_speech()544 void stop_speech() {
545 if (channels[SCHAN_SPEECH] != NULL) {
546 play.music_master_volume = play.music_vol_was;
547 // update the music in a bit (fixes two speeches follow each other
548 // and music going up-then-down)
549 update_music_at = 20;
550 mvolcounter = 1;
551 stop_and_destroy_channel (SCHAN_SPEECH);
552 curLipLine = -1;
553
554 if (play.no_textbg_when_voice == 2) {
555 // set back to Sierra w/bgrnd
556 play.no_textbg_when_voice = 1;
557 game.options[OPT_SPEECHTYPE] = 2;
558 }
559 }
560 }
561