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 "util/wgt2allg.h"
17 #include "media/audio/audio.h"
18 #include "ac/gamesetupstruct.h"
19 #include "ac/dynobj/cc_audioclip.h"
20 #include "ac/dynobj/cc_audiochannel.h"
21 #include "ac/gamestate.h"
22 #include "script/script_runtime.h"
23 #include "ac/audiochannel.h"
24 #include "ac/audioclip.h"
25 #include "ac/gamesetup.h"
26 #include "ac/path_helper.h"
27 #include "media/audio/sound.h"
28 #include "debug/debug_log.h"
29 #include "debug/debugger.h"
30 #include "ac/common.h"
31 #include "ac/file.h"
32 #include "ac/global_audio.h"
33 #include "ac/roomstruct.h"
34 #include <math.h>
35 #include "util/stream.h"
36 #include "core/assetmanager.h"
37 
38 using namespace AGS::Common;
39 
40 AGS::Engine::Mutex _audio_mutex;
41 volatile bool _audio_doing_crossfade;
42 
43 extern GameSetupStruct game;
44 extern GameSetup usetup;
45 extern GameState play;
46 extern roomstruct thisroom;
47 extern CharacterInfo*playerchar;
48 
49 extern volatile int switching_away_from_game;
50 
51 #if !defined(IOS_VERSION) && !defined(PSP_VERSION) && !defined(ANDROID_VERSION)
52 volatile int psp_audio_multithreaded = 0;
53 #endif
54 
55 ScriptAudioChannel scrAudioChannel[MAX_SOUND_CHANNELS + 1];
56 char acaudio_buffer[256];
57 int reserved_channel_count = 0;
58 
59 AGS::Engine::Thread audioThread;
60 
calculate_reserved_channel_count()61 void calculate_reserved_channel_count()
62 {
63     int reservedChannels = 0;
64     for (int i = 0; i < game.audioClipTypeCount; i++)
65     {
66         reservedChannels += game.audioClipTypes[i].reservedChannels;
67     }
68     reserved_channel_count = reservedChannels;
69 }
70 
update_clip_default_volume(ScriptAudioClip * audioClip)71 void update_clip_default_volume(ScriptAudioClip *audioClip)
72 {
73     if (play.default_audio_type_volumes[audioClip->type] >= 0)
74     {
75         audioClip->defaultVolume = play.default_audio_type_volumes[audioClip->type];
76     }
77 }
78 
start_fading_in_new_track_if_applicable(int fadeInChannel,ScriptAudioClip * newSound)79 void start_fading_in_new_track_if_applicable(int fadeInChannel, ScriptAudioClip *newSound)
80 {
81     int crossfadeSpeed = game.audioClipTypes[newSound->type].crossfadeSpeed;
82     if (crossfadeSpeed > 0)
83     {
84         update_clip_default_volume(newSound);
85         play.crossfade_in_volume_per_step = crossfadeSpeed;
86         play.crossfade_final_volume_in = newSound->defaultVolume;
87         play.crossfading_in_channel = fadeInChannel;
88     }
89 }
90 
move_track_to_crossfade_channel(int currentChannel,int crossfadeSpeed,int fadeInChannel,ScriptAudioClip * newSound)91 void move_track_to_crossfade_channel(int currentChannel, int crossfadeSpeed, int fadeInChannel, ScriptAudioClip *newSound)
92 {
93     stop_and_destroy_channel(SPECIAL_CROSSFADE_CHANNEL);
94     channels[SPECIAL_CROSSFADE_CHANNEL] = channels[currentChannel];
95     channels[currentChannel] = NULL;
96 
97     play.crossfading_out_channel = SPECIAL_CROSSFADE_CHANNEL;
98     play.crossfade_step = 0;
99     play.crossfade_initial_volume_out = channels[SPECIAL_CROSSFADE_CHANNEL]->get_volume();
100     play.crossfade_out_volume_per_step = crossfadeSpeed;
101 
102     play.crossfading_in_channel = fadeInChannel;
103     if (newSound != NULL)
104     {
105         start_fading_in_new_track_if_applicable(fadeInChannel, newSound);
106     }
107 }
108 
stop_or_fade_out_channel(int fadeOutChannel,int fadeInChannel,ScriptAudioClip * newSound)109 void stop_or_fade_out_channel(int fadeOutChannel, int fadeInChannel, ScriptAudioClip *newSound)
110 {
111     ScriptAudioClip *sourceClip = AudioChannel_GetPlayingClip(&scrAudioChannel[fadeOutChannel]);
112     if ((sourceClip != NULL) && (game.audioClipTypes[sourceClip->type].crossfadeSpeed > 0))
113     {
114         move_track_to_crossfade_channel(fadeOutChannel, game.audioClipTypes[sourceClip->type].crossfadeSpeed, fadeInChannel, newSound);
115     }
116     else
117     {
118         stop_and_destroy_channel(fadeOutChannel);
119     }
120 }
121 
122 
find_free_audio_channel(ScriptAudioClip * clip,int priority,bool interruptEqualPriority)123 int find_free_audio_channel(ScriptAudioClip *clip, int priority, bool interruptEqualPriority)
124 {
125     int lowestPrioritySoFar = 9999999;
126     int lowestPriorityID = -1;
127     int channelToUse = -1;
128 
129     if (!interruptEqualPriority)
130         priority--;
131 
132     int startAtChannel = reserved_channel_count;
133     int endBeforeChannel = MAX_SOUND_CHANNELS;
134 
135     if (game.audioClipTypes[clip->type].reservedChannels > 0)
136     {
137         startAtChannel = 0;
138         for (int i = 0; i < clip->type; i++)
139         {
140             startAtChannel += game.audioClipTypes[i].reservedChannels;
141         }
142         endBeforeChannel = startAtChannel + game.audioClipTypes[clip->type].reservedChannels;
143     }
144 
145     for (int i = startAtChannel; i < endBeforeChannel; i++)
146     {
147         if ((channels[i] == NULL) || (channels[i]->done))
148         {
149             channelToUse = i;
150             stop_and_destroy_channel(i);
151             break;
152         }
153         if ((channels[i]->priority < lowestPrioritySoFar) &&
154             (channels[i]->soundType == clip->type))
155         {
156             lowestPrioritySoFar = channels[i]->priority;
157             lowestPriorityID = i;
158         }
159     }
160 
161     if ((channelToUse < 0) && (lowestPriorityID >= 0) &&
162         (lowestPrioritySoFar <= priority))
163     {
164         stop_or_fade_out_channel(lowestPriorityID, lowestPriorityID, clip);
165         channelToUse = lowestPriorityID;
166     }
167     else if ((channelToUse >= 0) && (play.crossfading_in_channel < 1))
168     {
169         start_fading_in_new_track_if_applicable(channelToUse, clip);
170     }
171     return channelToUse;
172 }
173 
is_audiotype_allowed_to_play(AudioFileType type)174 bool is_audiotype_allowed_to_play(AudioFileType type)
175 {
176     return type == eAudioFileMIDI && usetup.midicard != MIDI_NONE ||
177            type != eAudioFileMIDI && usetup.digicard != DIGI_NONE;
178 }
179 
load_sound_clip(ScriptAudioClip * audioClip,bool repeat)180 SOUNDCLIP *load_sound_clip(ScriptAudioClip *audioClip, bool repeat)
181 {
182     if (!is_audiotype_allowed_to_play((AudioFileType)audioClip->fileType))
183     {
184         return NULL;
185     }
186 
187     update_clip_default_volume(audioClip);
188 
189     SOUNDCLIP *soundClip = NULL;
190     AssetPath asset_name = get_audio_clip_assetpath(audioClip->bundlingType, audioClip->fileName);
191     switch (audioClip->fileType)
192     {
193     case eAudioFileOGG:
194         soundClip = my_load_static_ogg(asset_name, audioClip->defaultVolume, repeat);
195         break;
196     case eAudioFileMP3:
197         soundClip = my_load_static_mp3(asset_name, audioClip->defaultVolume, repeat);
198         break;
199     case eAudioFileWAV:
200     case eAudioFileVOC:
201         soundClip = my_load_wave(asset_name, audioClip->defaultVolume, repeat);
202         break;
203     case eAudioFileMIDI:
204         soundClip = my_load_midi(asset_name, repeat);
205         break;
206     case eAudioFileMOD:
207 #ifndef PSP_NO_MOD_PLAYBACK
208         soundClip = my_load_mod(asset_name, repeat);
209 #else
210         soundClip = NULL;
211 #endif
212         break;
213     default:
214         quitprintf("AudioClip.Play: invalid audio file type encountered: %d", audioClip->fileType);
215     }
216     if (soundClip != NULL)
217     {
218         soundClip->set_volume_percent(audioClip->defaultVolume);
219         soundClip->soundType = audioClip->type;
220         soundClip->sourceClip = audioClip;
221     }
222     return soundClip;
223 }
224 
audio_update_polled_stuff()225 void audio_update_polled_stuff()
226 {
227     play.crossfade_step++;
228 
229     if (play.crossfading_out_channel > 0)
230     {
231         if (channels[play.crossfading_out_channel] == NULL)
232             quitprintf("Crossfade out channel is %d but channel has gone", play.crossfading_out_channel);
233 
234         int newVolume = channels[play.crossfading_out_channel]->get_volume() - play.crossfade_out_volume_per_step;
235         if (newVolume > 0)
236         {
237             AudioChannel_SetVolume(&scrAudioChannel[play.crossfading_out_channel], newVolume);
238         }
239         else
240         {
241             stop_and_destroy_channel(play.crossfading_out_channel);
242             play.crossfading_out_channel = 0;
243         }
244     }
245 
246     if (play.crossfading_in_channel > 0)
247     {
248         int newVolume = channels[play.crossfading_in_channel]->get_volume() + play.crossfade_in_volume_per_step;
249         if (newVolume > play.crossfade_final_volume_in)
250         {
251             newVolume = play.crossfade_final_volume_in;
252         }
253 
254         AudioChannel_SetVolume(&scrAudioChannel[play.crossfading_in_channel], newVolume);
255 
256         if (newVolume >= play.crossfade_final_volume_in)
257         {
258             play.crossfading_in_channel = 0;
259         }
260     }
261 
262     if (play.new_music_queue_size > 0)
263     {
264         for (int i = 0; i < play.new_music_queue_size; i++)
265         {
266             ScriptAudioClip *clip = &game.audioClips[play.new_music_queue[i].audioClipIndex];
267             int channel = find_free_audio_channel(clip, clip->defaultPriority, false);
268             if (channel >= 0)
269             {
270                 QueuedAudioItem itemToPlay = play.new_music_queue[i];
271 
272                 play.new_music_queue_size--;
273                 for (int j = i; j < play.new_music_queue_size; j++)
274                 {
275                     play.new_music_queue[j] = play.new_music_queue[j + 1];
276                 }
277 
278                 play_audio_clip_on_channel(channel, clip, itemToPlay.priority, itemToPlay.repeat, 0, itemToPlay.cachedClip);
279                 i--;
280             }
281         }
282     }
283 }
284 
285 // Applies a volume drop modifier to the clip, in accordance to its audio type
apply_volume_drop_to_clip(SOUNDCLIP * clip)286 void apply_volume_drop_to_clip(SOUNDCLIP *clip)
287 {
288     int audiotype = ((ScriptAudioClip*)clip->sourceClip)->type;
289     clip->apply_volume_modifier(-(game.audioClipTypes[audiotype].volume_reduction_while_speech_playing * 255 / 100));
290 }
291 
queue_audio_clip_to_play(ScriptAudioClip * clip,int priority,int repeat)292 void queue_audio_clip_to_play(ScriptAudioClip *clip, int priority, int repeat)
293 {
294     if (play.new_music_queue_size >= MAX_QUEUED_MUSIC) {
295         debug_script_log("Too many queued music, cannot add %s", clip->scriptName);
296         return;
297     }
298 
299     SOUNDCLIP *cachedClip = load_sound_clip(clip, (repeat != 0));
300     if (cachedClip != NULL)
301     {
302         play.new_music_queue[play.new_music_queue_size].audioClipIndex = clip->id;
303         play.new_music_queue[play.new_music_queue_size].priority = priority;
304         play.new_music_queue[play.new_music_queue_size].repeat = (repeat != 0);
305         play.new_music_queue[play.new_music_queue_size].cachedClip = cachedClip;
306         play.new_music_queue_size++;
307     }
308 
309     if (!psp_audio_multithreaded)
310       update_polled_mp3();
311 }
312 
play_audio_clip_on_channel(int channel,ScriptAudioClip * clip,int priority,int repeat,int fromOffset,SOUNDCLIP * soundfx)313 ScriptAudioChannel* play_audio_clip_on_channel(int channel, ScriptAudioClip *clip, int priority, int repeat, int fromOffset, SOUNDCLIP *soundfx)
314 {
315     if (soundfx == NULL)
316     {
317         soundfx = load_sound_clip(clip, (repeat) ? true : false);
318     }
319     if (soundfx == NULL)
320     {
321         debug_script_log("AudioClip.Play: unable to load sound file");
322         if (play.crossfading_in_channel == channel)
323         {
324             play.crossfading_in_channel = 0;
325         }
326         return NULL;
327     }
328     soundfx->priority = priority;
329 
330     if (play.crossfading_in_channel == channel)
331     {
332         soundfx->set_volume_percent(0);
333     }
334 
335     // Mute the audio clip if fast-forwarding the cutscene
336     if (play.fast_forward)
337     {
338         soundfx->set_mute(true);
339 
340         // CHECKME!!
341         // [IKM] According to the 3.2.1 logic the clip will restore
342         // its value after cutscene, but only if originalVolAsPercentage
343         // is not zeroed. Something I am not sure about: why does it
344         // disable the clip under condition that there's more than one
345         // channel for this audio type? It does not even check if
346         // anything of this type is currently playing.
347         if (game.audioClipTypes[clip->type].reservedChannels != 1)
348             soundfx->set_volume_percent(0);
349     }
350 
351     if (soundfx->play_from(fromOffset) == 0)
352     {
353         debug_script_log("AudioClip.Play: failed to play sound file");
354         return NULL;
355     }
356 
357     // Apply volume drop if any speech voice-over is currently playing
358     // NOTE: there is a confusing logic in sound clip classes, that they do not use
359     // any modifiers when begin playing, therefore we must apply this only after
360     // playback was started.
361     if (!play.fast_forward && channels[SCHAN_SPEECH])
362         apply_volume_drop_to_clip(soundfx);
363 
364     last_sound_played[channel] = -1;
365     channels[channel] = soundfx;
366     return &scrAudioChannel[channel];
367 }
368 
remove_clips_of_type_from_queue(int audioType)369 void remove_clips_of_type_from_queue(int audioType)
370 {
371     int aa;
372     for (aa = 0; aa < play.new_music_queue_size; aa++)
373     {
374         ScriptAudioClip *clip = &game.audioClips[play.new_music_queue[aa].audioClipIndex];
375         if (clip->type == audioType)
376         {
377             play.new_music_queue_size--;
378             for (int bb = aa; bb < play.new_music_queue_size; bb++)
379                 play.new_music_queue[bb] = play.new_music_queue[bb + 1];
380             aa--;
381         }
382     }
383 }
384 
update_queued_clips_volume(int audioType,int new_vol)385 void update_queued_clips_volume(int audioType, int new_vol)
386 {
387     for (int i = 0; i < play.new_music_queue_size; ++i)
388     {
389         // NOTE: if clip is uncached, the volume will be set from defaults when it is loaded
390         SOUNDCLIP *sndclip = play.new_music_queue[i].cachedClip;
391         if (sndclip)
392         {
393             ScriptAudioClip *clip = &game.audioClips[play.new_music_queue[i].audioClipIndex];
394             if (clip->type == audioType)
395                 sndclip->set_volume_percent(new_vol);
396         }
397     }
398 }
399 
play_audio_clip(ScriptAudioClip * clip,int priority,int repeat,int fromOffset,bool queueIfNoChannel)400 ScriptAudioChannel* play_audio_clip(ScriptAudioClip *clip, int priority, int repeat, int fromOffset, bool queueIfNoChannel)
401 {
402     if (!queueIfNoChannel)
403         remove_clips_of_type_from_queue(clip->type);
404 
405     if (priority == SCR_NO_VALUE)
406         priority = clip->defaultPriority;
407     if (repeat == SCR_NO_VALUE)
408         repeat = clip->defaultRepeat;
409 
410     int channel = find_free_audio_channel(clip, priority, !queueIfNoChannel);
411     if (channel < 0)
412     {
413         if (queueIfNoChannel)
414             queue_audio_clip_to_play(clip, priority, repeat);
415         else
416             debug_script_log("AudioClip.Play: no channels available to interrupt PRI:%d TYPE:%d", priority, clip->type);
417 
418         return NULL;
419     }
420 
421     return play_audio_clip_on_channel(channel, clip, priority, repeat, fromOffset);
422 }
423 
play_audio_clip_by_index(int audioClipIndex)424 ScriptAudioChannel* play_audio_clip_by_index(int audioClipIndex)
425 {
426     if ((audioClipIndex >= 0) && (audioClipIndex < game.audioClipCount))
427         return AudioClip_Play(&game.audioClips[audioClipIndex], SCR_NO_VALUE, SCR_NO_VALUE);
428     else
429         return NULL;
430 }
431 
stop_and_destroy_channel_ex(int chid,bool resetLegacyMusicSettings)432 void stop_and_destroy_channel_ex(int chid, bool resetLegacyMusicSettings) {
433     if ((chid < 0) || (chid > MAX_SOUND_CHANNELS))
434         quit("!StopChannel: invalid channel ID");
435 
436     if (channels[chid] != NULL) {
437         channels[chid]->destroy();
438         delete channels[chid];
439         channels[chid] = NULL;
440     }
441 
442     if (play.crossfading_in_channel == chid)
443         play.crossfading_in_channel = 0;
444     if (play.crossfading_out_channel == chid)
445         play.crossfading_out_channel = 0;
446 
447     // destroyed an ambient sound channel
448     if (ambient[chid].channel > 0)
449         ambient[chid].channel = 0;
450 
451     if ((chid == SCHAN_MUSIC) && (resetLegacyMusicSettings))
452     {
453         play.cur_music_number = -1;
454         current_music_type = 0;
455     }
456 }
457 
stop_and_destroy_channel(int chid)458 void stop_and_destroy_channel (int chid)
459 {
460     stop_and_destroy_channel_ex(chid, true);
461 }
462 
463 
464 
465 // ***** BACKWARDS COMPATIBILITY WITH OLD AUDIO SYSTEM ***** //
466 
get_old_style_number_for_sound(int sound_number)467 int get_old_style_number_for_sound(int sound_number)
468 {
469     int audio_clip_id = 0;
470 
471     if (game.IsLegacyAudioSystem())
472     {
473         // No sound assigned.
474         if (sound_number < 1)
475             return 0;
476 
477         // Sound number is not yet updated to audio clip id.
478         if (sound_number <= 0x10000000)
479             return sound_number;
480 
481         // Remove audio clip id flag.
482         audio_clip_id = sound_number - 0x10000000;
483     }
484     else
485         audio_clip_id = sound_number;
486 
487     if (audio_clip_id >= 0)
488     {
489         int old_style_number = 0;
490         if (sscanf(game.audioClips[audio_clip_id].scriptName, "aSound%d", &old_style_number) == 1)
491             return old_style_number;
492     }
493     return 0;
494 }
495 
load_sound_clip_from_old_style_number(bool isMusic,int indexNumber,bool repeat)496 SOUNDCLIP *load_sound_clip_from_old_style_number(bool isMusic, int indexNumber, bool repeat)
497 {
498     ScriptAudioClip* audioClip = GetAudioClipForOldStyleNumber(game, isMusic, indexNumber);
499 
500     if (audioClip != NULL)
501     {
502         return load_sound_clip(audioClip, repeat);
503     }
504 
505     return NULL;
506 }
507 
508 //=============================================================================
509 
510 int last_sound_played[MAX_SOUND_CHANNELS + 1];
511 
force_audiostream_include()512 void force_audiostream_include() {
513     // This should never happen, but the call is here to make it
514     // link the audiostream libraries
515     stop_audio_stream(NULL);
516 }
517 
518 AmbientSound ambient[MAX_SOUND_CHANNELS + 1];  // + 1 just for safety on array iterations
519 
get_volume_adjusted_for_distance(int volume,int sndX,int sndY,int sndMaxDist)520 int get_volume_adjusted_for_distance(int volume, int sndX, int sndY, int sndMaxDist)
521 {
522     int distx = playerchar->x - sndX;
523     int disty = playerchar->y - sndY;
524     // it uses Allegro's "fix" sqrt without the ::
525     int dist = (int)::sqrt((double)(distx*distx + disty*disty));
526 
527     // if they're quite close, full volume
528     int wantvol = volume;
529 
530     if (dist >= AMBIENCE_FULL_DIST)
531     {
532         // get the relative volume
533         wantvol = ((dist - AMBIENCE_FULL_DIST) * volume) / sndMaxDist;
534         // closer is louder
535         wantvol = volume - wantvol;
536     }
537 
538     return wantvol;
539 }
540 
update_directional_sound_vol()541 void update_directional_sound_vol()
542 {
543     for (int chan = 1; chan < MAX_SOUND_CHANNELS; chan++)
544     {
545         if ((channels[chan] != NULL) && (channels[chan]->done == 0) &&
546             (channels[chan]->xSource >= 0))
547         {
548             channels[chan]->apply_directional_modifier(
549                 get_volume_adjusted_for_distance(channels[chan]->vol,
550                 channels[chan]->xSource,
551                 channels[chan]->ySource,
552                 channels[chan]->maximumPossibleDistanceAway) -
553                 channels[chan]->vol);
554         }
555     }
556 }
557 
update_ambient_sound_vol()558 void update_ambient_sound_vol () {
559 
560     for (int chan = 1; chan < MAX_SOUND_CHANNELS; chan++) {
561 
562         AmbientSound *thisSound = &ambient[chan];
563 
564         if (thisSound->channel == 0)
565             continue;
566 
567         int sourceVolume = thisSound->vol;
568 
569         if ((channels[SCHAN_SPEECH] != NULL) && (channels[SCHAN_SPEECH]->done == 0)) {
570             // Negative value means set exactly; positive means drop that amount
571             if (play.speech_music_drop < 0)
572                 sourceVolume = -play.speech_music_drop;
573             else
574                 sourceVolume -= play.speech_music_drop;
575 
576             if (sourceVolume < 0)
577                 sourceVolume = 0;
578             if (sourceVolume > 255)
579                 sourceVolume = 255;
580         }
581 
582         // Adjust ambient volume so it maxes out at overall sound volume
583         int ambientvol = (sourceVolume * play.sound_volume) / 255;
584 
585         int wantvol;
586 
587         if ((thisSound->x == 0) && (thisSound->y == 0)) {
588             wantvol = ambientvol;
589         }
590         else {
591             wantvol = get_volume_adjusted_for_distance(ambientvol, thisSound->x, thisSound->y, thisSound->maxdist);
592         }
593 
594         if (channels[thisSound->channel] == NULL)
595             quit("Internal error: the ambient sound channel is enabled, but it has been destroyed");
596 
597         channels[thisSound->channel]->set_volume(wantvol);
598     }
599 }
600 
load_sound_and_play(ScriptAudioClip * aclip,bool repeat)601 SOUNDCLIP *load_sound_and_play(ScriptAudioClip *aclip, bool repeat)
602 {
603     SOUNDCLIP *soundfx = load_sound_clip(aclip, repeat);
604 
605     if (soundfx != NULL) {
606         if (soundfx->play() == 0)
607             soundfx = NULL;
608     }
609 
610     return soundfx;
611 }
612 
stop_all_sound_and_music()613 void stop_all_sound_and_music()
614 {
615     int a;
616     stopmusic();
617     // make sure it doesn't start crossfading when it comes back
618     crossFading = 0;
619     // any ambient sound will be aborted
620     for (a = 0; a <= MAX_SOUND_CHANNELS; a++)
621         stop_and_destroy_channel(a);
622 }
623 
shutdown_sound()624 void shutdown_sound()
625 {
626     stop_all_sound_and_music();
627 
628 #ifndef PSP_NO_MOD_PLAYBACK
629     if (opts.mod_player)
630         remove_mod_player();
631 #endif
632     remove_sound();
633 }
634 
635 // the sound will only be played if there is a free channel or
636 // it has a priority >= an existing sound to override
play_sound_priority(int val1,int priority)637 int play_sound_priority (int val1, int priority) {
638     int lowest_pri = 9999, lowest_pri_id = -1;
639 
640     // find a free channel to play it on
641     for (int i = SCHAN_NORMAL; i < numSoundChannels; i++) {
642         if (val1 < 0) {
643             // Playing sound -1 means iterate through and stop all sound
644             if ((channels[i] != NULL) && (channels[i]->done == 0))
645                 stop_and_destroy_channel (i);
646         }
647         else if ((channels[i] == NULL) || (channels[i]->done != 0)) {
648             if (PlaySoundEx(val1, i) >= 0)
649                 channels[i]->priority = priority;
650             return i;
651         }
652         else if (channels[i]->priority < lowest_pri) {
653             lowest_pri = channels[i]->priority;
654             lowest_pri_id = i;
655         }
656 
657     }
658     if (val1 < 0)
659         return -1;
660 
661     // no free channels, see if we have a high enough priority
662     // to override one
663     if (priority >= lowest_pri) {
664         if (PlaySoundEx(val1, lowest_pri_id) >= 0) {
665             channels[lowest_pri_id]->priority = priority;
666             return lowest_pri_id;
667         }
668     }
669 
670     return -1;
671 }
672 
play_sound(int val1)673 int play_sound(int val1) {
674     return play_sound_priority(val1, 10);
675 }
676 
677 //=============================================================================
678 
679 
680 
681 int current_music_type = 0;
682 // crossFading is >0 (channel number of new track), or -1 (old
683 // track fading out, no new track)
684 int crossFading = 0, crossFadeVolumePerStep = 0, crossFadeStep = 0;
685 int crossFadeVolumeAtStart = 0;
686 SOUNDCLIP *cachedQueuedMusic = NULL;
687 
688 int musicPollIterator; // long name so it doesn't interfere with anything else
689 
690 volatile int mvolcounter = 0;
691 int update_music_at=0;
692 
693 
694 
695 /*
696 #include "almp3_old.h"
697 ALLEGRO_MP3 *mp3ptr;
698 int mp3vol=128;
699 
700 void amp_setvolume(int newvol) { mp3vol=newvol; }
701 int load_amp(char*namm,int loop) {
702 mp3ptr = new ALLEGRO_MP3(namm);
703 if (mp3ptr == NULL) return 0;
704 if (mp3ptr->get_error_code() != 0) {
705 delete mp3ptr;
706 return 0;
707 }
708 mp3ptr->play(mp3vol, 8192);
709 return 1;
710 }
711 void install_amp() { }
712 void unload_amp() {
713 mp3ptr->stop();
714 delete mp3ptr;
715 }
716 int amp_decode() {
717 mp3ptr->poll();
718 if (mp3ptr->is_finished()) {
719 if (play.music_repeat)
720 mp3ptr->play(mp3vol, 8192);
721 else return -1;
722 }
723 return 0;
724 }
725 */
726 //#endif
727 
clear_music_cache()728 void clear_music_cache() {
729 
730     if (cachedQueuedMusic != NULL) {
731         cachedQueuedMusic->destroy();
732         delete cachedQueuedMusic;
733         cachedQueuedMusic = NULL;
734     }
735 
736 }
737 
play_next_queued()738 void play_next_queued() {
739     // check if there's a queued one to play
740     if (play.music_queue_size > 0) {
741 
742         int tuneToPlay = play.music_queue[0];
743 
744         if (tuneToPlay >= QUEUED_MUSIC_REPEAT) {
745             // Loop it!
746             play.music_repeat++;
747             play_new_music(tuneToPlay - QUEUED_MUSIC_REPEAT, cachedQueuedMusic);
748             play.music_repeat--;
749         }
750         else {
751             // Don't loop it!
752             int repeatWas = play.music_repeat;
753             play.music_repeat = 0;
754             play_new_music(tuneToPlay, cachedQueuedMusic);
755             play.music_repeat = repeatWas;
756         }
757 
758         // don't free the memory, as it has been transferred onto the
759         // main music channel
760         cachedQueuedMusic = NULL;
761 
762         play.music_queue_size--;
763         for (int i = 0; i < play.music_queue_size; i++)
764             play.music_queue[i] = play.music_queue[i + 1];
765 
766         if (play.music_queue_size > 0)
767             cachedQueuedMusic = load_music_from_disk(play.music_queue[0], 0);
768     }
769 
770 }
771 
calculate_max_volume()772 int calculate_max_volume() {
773     // quieter so that sounds can be heard better
774     int newvol=play.music_master_volume + ((int)thisroom.options[ST_VOLUME]) * LegacyRoomVolumeFactor;
775     if (newvol>255) newvol=255;
776     if (newvol<0) newvol=0;
777 
778     if (play.fast_forward)
779         newvol = 0;
780 
781     return newvol;
782 }
783 
784 // add/remove the volume drop to the audio channels while speech is playing
apply_volume_drop_modifier(bool applyModifier)785 void apply_volume_drop_modifier(bool applyModifier)
786 {
787     for (int i = 0; i < MAX_SOUND_CHANNELS; i++)
788     {
789         if (channels[i] && channels[i]->done == 0 && channels[i]->sourceClip != NULL)
790         {
791             if (applyModifier)
792                 apply_volume_drop_to_clip(channels[i]);
793             else
794                 channels[i]->apply_volume_modifier(0); // reset modifier
795         }
796     }
797 }
798 
799 // Checks if speech voice-over is currently playing, and reapply volume drop to all other active clips
update_volume_drop_if_voiceover()800 void update_volume_drop_if_voiceover()
801 {
802     apply_volume_drop_modifier(channels[SCHAN_SPEECH] != NULL);
803 }
804 
805 extern volatile char want_exit;
806 extern int frames_per_second;
807 
update_mp3_thread()808 void update_mp3_thread()
809 {
810 	while (switching_away_from_game) { }
811 	AGS::Engine::MutexLock _lock(_audio_mutex);
812 	for (musicPollIterator = 0; musicPollIterator <= MAX_SOUND_CHANNELS; ++musicPollIterator)
813 	{
814 		if ((channels[musicPollIterator] != NULL) && (channels[musicPollIterator]->done == 0))
815 			channels[musicPollIterator]->poll();
816 	}
817 }
818 
update_mp3()819 void update_mp3()
820 {
821 	if (!psp_audio_multithreaded) update_mp3_thread();
822 }
823 
update_polled_mp3()824 void update_polled_mp3() {
825     update_mp3();
826 
827         if (mvolcounter > update_music_at) {
828             update_music_volume();
829             apply_volume_drop_modifier(false);
830             update_music_at = 0;
831             mvolcounter = 0;
832             update_ambient_sound_vol();
833         }
834 }
835 
836 // Update the music, and advance the crossfade on a step
837 // (this should only be called once per game loop)
update_polled_audio_and_crossfade()838 void update_polled_audio_and_crossfade ()
839 {
840 	update_polled_stuff_if_runtime ();
841 
842 	AGS::Engine::MutexLock _lock(_audio_mutex);
843 
844     _audio_doing_crossfade = true;
845 
846     audio_update_polled_stuff();
847 
848     if (crossFading) {
849         crossFadeStep++;
850         update_music_volume();
851     }
852 
853     // Check if the current music has finished playing
854     if ((play.cur_music_number >= 0) && (play.fast_forward == 0)) {
855         if (IsMusicPlaying() == 0) {
856             // The current music has finished
857             play.cur_music_number = -1;
858             play_next_queued();
859         }
860         else if ((game.options[OPT_CROSSFADEMUSIC] > 0) &&
861             (play.music_queue_size > 0) && (!crossFading)) {
862                 // want to crossfade, and new tune in the queue
863                 int curpos = channels[SCHAN_MUSIC]->get_pos_ms();
864                 int muslen = channels[SCHAN_MUSIC]->get_length_ms();
865                 if ((curpos > 0) && (muslen > 0)) {
866                     // we want to crossfade, and we know how far through
867                     // the tune we are
868                     int takesSteps = calculate_max_volume() / game.options[OPT_CROSSFADEMUSIC];
869                     int takesMs = (takesSteps * 1000) / frames_per_second;
870                     if (curpos >= muslen - takesMs)
871                         play_next_queued();
872                 }
873         }
874     }
875 
876     _audio_doing_crossfade = false;
877 
878 }
879 
880 
stopmusic()881 void stopmusic() {
882 
883     if (crossFading > 0) {
884         // stop in the middle of a new track fading in
885         // Abort the new track, and let the old one finish fading out
886         stop_and_destroy_channel (crossFading);
887         crossFading = -1;
888     }
889     else if (crossFading < 0) {
890         // the music is already fading out
891         if (game.options[OPT_CROSSFADEMUSIC] <= 0) {
892             // If they have since disabled crossfading, stop the fadeout
893             stop_and_destroy_channel(SCHAN_MUSIC);
894             crossFading = 0;
895             crossFadeStep = 0;
896             update_music_volume();
897         }
898     }
899     else if ((game.options[OPT_CROSSFADEMUSIC] > 0)
900         && (channels[SCHAN_MUSIC] != NULL)
901         && (channels[SCHAN_MUSIC]->done == 0)
902         && (current_music_type != 0)
903         && (current_music_type != MUS_MIDI)
904         && (current_music_type != MUS_MOD)) {
905 
906             crossFading = -1;
907             crossFadeStep = 0;
908             crossFadeVolumePerStep = game.options[OPT_CROSSFADEMUSIC];
909             crossFadeVolumeAtStart = calculate_max_volume();
910     }
911     else
912         stop_and_destroy_channel (SCHAN_MUSIC);
913 
914     play.cur_music_number = -1;
915     current_music_type = 0;
916 }
917 
update_music_volume()918 void update_music_volume() {
919 
920     if ((current_music_type) || (crossFading < 0))
921     {
922         // targetVol is the maximum volume we're fading in to
923         // newvol is the starting volume that we faded out from
924         int targetVol = calculate_max_volume();
925         int newvol;
926         if (crossFading)
927             newvol = crossFadeVolumeAtStart;
928         else
929             newvol = targetVol;
930 
931         // fading out old track, target volume is silence
932         if (crossFading < 0)
933             targetVol = 0;
934 
935         if (crossFading) {
936             int curvol = crossFadeVolumePerStep * crossFadeStep;
937 
938             if ((curvol > targetVol) && (curvol > newvol)) {
939                 // it has fully faded to the new track
940                 newvol = targetVol;
941                 stop_and_destroy_channel_ex(SCHAN_MUSIC, false);
942                 if (crossFading > 0) {
943                     channels[SCHAN_MUSIC] = channels[crossFading];
944                     channels[crossFading] = NULL;
945                 }
946                 crossFading = 0;
947             }
948             else {
949                 if (crossFading > 0)
950                     channels[crossFading]->set_volume((curvol > targetVol) ? targetVol : curvol);
951 
952                 newvol -= curvol;
953                 if (newvol < 0)
954                     newvol = 0;
955             }
956         }
957         if (channels[SCHAN_MUSIC])
958             channels[SCHAN_MUSIC]->set_volume (newvol);
959     }
960 }
961 
962 // Ensures crossfader is stable after loading (or failing to load)
963 // new music
post_new_music_check(int newchannel)964 void post_new_music_check (int newchannel) {
965     if ((crossFading > 0) && (channels[crossFading] == NULL)) {
966         crossFading = 0;
967         // Was fading out but then they played invalid music, continue
968         // to fade out
969         if (channels[SCHAN_MUSIC] != NULL)
970             crossFading = -1;
971     }
972 
973 }
974 
975 // Sets up the crossfading for playing the new music track,
976 // and returns the channel number to use
prepare_for_new_music()977 int prepare_for_new_music () {
978     int useChannel = SCHAN_MUSIC;
979 
980     if ((game.options[OPT_CROSSFADEMUSIC] > 0)
981         && (channels[SCHAN_MUSIC] != NULL)
982         && (channels[SCHAN_MUSIC]->done == 0)
983         && (current_music_type != MUS_MIDI)
984         && (current_music_type != MUS_MOD)) {
985 
986             if (crossFading > 0) {
987                 // It's still crossfading to the previous track
988                 stop_and_destroy_channel_ex(SCHAN_MUSIC, false);
989                 channels[SCHAN_MUSIC] = channels[crossFading];
990                 channels[crossFading] = NULL;
991                 crossFading = 0;
992                 update_music_volume();
993             }
994             else if (crossFading < 0) {
995                 // an old track is still fading out, no new music yet
996                 // Do nothing, and keep the current crossfade step
997             }
998             else {
999                 // start crossfading
1000                 crossFadeStep = 0;
1001                 crossFadeVolumePerStep = game.options[OPT_CROSSFADEMUSIC];
1002                 crossFadeVolumeAtStart = calculate_max_volume();
1003             }
1004             useChannel = SPECIAL_CROSSFADE_CHANNEL;
1005             crossFading = useChannel;
1006     }
1007     else {
1008         // crossfading is now turned off
1009         stopmusic();
1010         // ensure that any traces of old tunes fading are eliminated
1011         // (otherwise the new track will be faded out)
1012         crossFading = 0;
1013     }
1014 
1015     // Just make sure, because it will be overwritten in a sec
1016     if (channels[useChannel] != NULL)
1017         stop_and_destroy_channel (useChannel);
1018 
1019     return useChannel;
1020 }
1021 
get_audio_clip_for_music(int mnum)1022 ScriptAudioClip *get_audio_clip_for_music(int mnum)
1023 {
1024     if (mnum >= QUEUED_MUSIC_REPEAT)
1025         mnum -= QUEUED_MUSIC_REPEAT;
1026     return GetAudioClipForOldStyleNumber(game, true, mnum);
1027 }
1028 
load_music_from_disk(int mnum,bool doRepeat)1029 SOUNDCLIP *load_music_from_disk(int mnum, bool doRepeat) {
1030 
1031     if (mnum >= QUEUED_MUSIC_REPEAT) {
1032         mnum -= QUEUED_MUSIC_REPEAT;
1033         doRepeat = true;
1034     }
1035 
1036     SOUNDCLIP *loaded = load_sound_clip_from_old_style_number(true, mnum, doRepeat);
1037 
1038     if ((loaded == NULL) && (mnum > 0))
1039     {
1040         debug_script_warn("Music %d not found",mnum);
1041         debug_script_log("FAILED to load music %d", mnum);
1042     }
1043 
1044     return loaded;
1045 }
1046 
1047 
play_new_music(int mnum,SOUNDCLIP * music)1048 void play_new_music(int mnum, SOUNDCLIP *music) {
1049     if (debug_flags & DBG_NOMUSIC)
1050         return;
1051 
1052     if ((play.cur_music_number == mnum) && (music == NULL)) {
1053         debug_script_log("PlayMusic %d but already playing", mnum);
1054         return;  // don't play the music if it's already playing
1055     }
1056 
1057     ScriptAudioClip *aclip = get_audio_clip_for_music(mnum);
1058     if (aclip && !is_audiotype_allowed_to_play((AudioFileType)aclip->fileType))
1059         return;
1060 
1061     int useChannel = SCHAN_MUSIC;
1062     debug_script_log("Playing music %d", mnum);
1063 
1064     if (mnum<0) {
1065         stopmusic();
1066         return;
1067     }
1068 
1069     if (play.fast_forward) {
1070         // while skipping cutscene, don't change the music
1071         play.end_cutscene_music = mnum;
1072         return;
1073     }
1074 
1075     useChannel = prepare_for_new_music ();
1076 
1077     play.cur_music_number=mnum;
1078     current_music_type = 0;
1079     channels[useChannel] = NULL;
1080 
1081     play.current_music_repeating = play.music_repeat;
1082     // now that all the previous music is unloaded, load in the new one
1083 
1084     if (music != NULL) {
1085         channels[useChannel] = music;
1086         music = NULL;
1087     }
1088     else {
1089         channels[useChannel] = load_music_from_disk(mnum, (play.music_repeat > 0));
1090     }
1091 
1092     if (channels[useChannel] != NULL) {
1093 
1094         if (channels[useChannel]->play() == 0)
1095             channels[useChannel] = NULL;
1096         else
1097             current_music_type = channels[useChannel]->get_sound_type();
1098     }
1099 
1100     post_new_music_check(useChannel);
1101 
1102     update_music_volume();
1103 
1104 }
1105 
newmusic(int mnum)1106 void newmusic(int mnum) {
1107     play_new_music(mnum, NULL);
1108 }
1109