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