Skip to content

Commit b9345f5

Browse files
authored
Merge pull request #2912 from ivan-mogilko/363--audioplayastype
Script API: Add AudioClip.PlayAsType() and Game.PlayVoiceClipAsType()
2 parents 36900ec + d5a88d9 commit b9345f5

26 files changed

+331
-146
lines changed

Common/ac/common_defines.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,10 @@
129129
// An identifier of a "null font", a pseudo font used when you don't want a text to be drawn
130130
#define FONT_NULL (-1)
131131

132+
#define AUDIOTYPE_UNDEFINED -1
133+
#define AUDIOTYPE_SPEECH 0
134+
#define AUDIOTYPE_LEGACY_AMBIENT_SOUND 1
135+
#define AUDIOTYPE_LEGACY_MUSIC 2
136+
#define AUDIOTYPE_LEGACY_SOUND 3
137+
132138
#endif // __AC_DEFINES_H

Common/ac/dynobj/scriptaudioclip.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,49 @@
1414

1515
#include "ac/dynobj/scriptaudioclip.h"
1616
#include "util/stream.h"
17+
#include "util/string_compat.h"
1718

1819
using namespace AGS::Common;
1920

21+
/*static*/ AudioFileType ScriptAudioClip::GetAudioFileTypeFromExt(const char *ext)
22+
{
23+
if (ags_stricmp(ext, "mp3") == 0)
24+
return eAudioFileMP3;
25+
else if (ags_stricmp(ext, "wav") == 0)
26+
return eAudioFileWAV;
27+
else if (ags_stricmp(ext, "voc") == 0)
28+
return eAudioFileVOC;
29+
else if (ags_stricmp(ext, "mid") == 0)
30+
return eAudioFileMIDI;
31+
else if ((ags_stricmp(ext, "mod") == 0) || (ags_stricmp(ext, "xm") == 0)
32+
|| (ags_stricmp(ext, "s3m") == 0) || (ags_stricmp(ext, "it") == 0))
33+
return eAudioFileMOD;
34+
else if (ags_stricmp(ext, "ogg") == 0)
35+
return eAudioFileOGG;
36+
return eAudioFileUndefined;
37+
}
38+
39+
/*static */ const char *ScriptAudioClip::GetExtFromAudioFileType(AudioFileType filetype)
40+
{
41+
switch (filetype)
42+
{
43+
case eAudioFileOGG:
44+
return "ogg";
45+
case eAudioFileMP3:
46+
return "mp3";
47+
case eAudioFileWAV:
48+
return "wav";
49+
case eAudioFileVOC:
50+
return "voc";
51+
case eAudioFileMIDI:
52+
return "mid";
53+
case eAudioFileMOD:
54+
return "mod";
55+
default:
56+
return "";
57+
}
58+
}
59+
2060
void ScriptAudioClip::ReadFromFile(Stream *in)
2161
{
2262
id = in->ReadInt32();

Common/ac/dynobj/scriptaudioclip.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
#ifndef __AGS_CN_DYNOBJ__SCRIPTAUDIOCLIP_H
1919
#define __AGS_CN_DYNOBJ__SCRIPTAUDIOCLIP_H
2020

21+
#include "ac/common_defines.h"
2122
#include "util/string.h"
2223

2324
namespace AGS { namespace Common { class Stream; } }
2425
using namespace AGS; // FIXME later
2526

26-
enum AudioFileType {
27+
enum AudioFileType
28+
{
29+
eAudioFileUndefined = 0,
2730
eAudioFileOGG = 1,
2831
eAudioFileMP3 = 2,
2932
eAudioFileWAV = 3,
@@ -44,17 +47,21 @@ enum AudioClipBundle
4447
#define LEGACY_AUDIOCLIP_SCRIPTNAMELENGTH 30
4548
#define LEGACY_AUDIOCLIP_FILENAMELENGTH 15
4649

47-
struct ScriptAudioClip {
48-
int id = 0;
50+
struct ScriptAudioClip
51+
{
52+
int id = -1;
4953
Common::String scriptName;
5054
Common::String fileName;
5155
uint8_t bundlingType = kAudioBundle_Undefined;
52-
uint8_t type = 0;
53-
AudioFileType fileType = eAudioFileOGG;
56+
uint8_t type = AUDIOTYPE_UNDEFINED;
57+
AudioFileType fileType = eAudioFileUndefined;
5458
char defaultRepeat = 0;
5559
short defaultPriority = 50;
5660
short defaultVolume = 100;
5761

62+
static AudioFileType GetAudioFileTypeFromExt(const char *ext);
63+
static const char *GetExtFromAudioFileType(AudioFileType filetype);
64+
5865
void ReadFromFile(Common::Stream *in);
5966
};
6067

Common/ac/gamesetupstruct.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ void AdjustFontInfoUsingFlags(FontInfo &finfo, const uint32_t flags)
4444
}
4545
}
4646

47-
ScriptAudioClip* GetAudioClipForOldStyleNumber(GameSetupStruct &game, bool is_music, int num)
47+
const ScriptAudioClip* GetAudioClipForOldStyleNumber(GameSetupStruct &game, bool is_music, int num)
4848
{
4949
String clip_name;
5050
if (is_music)

Common/ac/gamesetupstruct.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,6 @@ void ConvertOldGameStruct (OldGameSetupStruct *ogss, GameSetupStruct *gss);
163163
#endif // OBSOLETE
164164

165165
// Finds an audio clip using legacy convention index
166-
ScriptAudioClip* GetAudioClipForOldStyleNumber(GameSetupStruct &game, bool is_music, int num);
166+
const ScriptAudioClip* GetAudioClipForOldStyleNumber(GameSetupStruct &game, bool is_music, int num);
167167

168168
#endif // __AGS_CN_AC__GAMESETUPSTRUCT_H

Common/core/assetmanager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ struct AssetPath
7272
String Filter;
7373

7474
AssetPath(const String &name = "", const String &filter = "") : Name(name), Filter(filter) {}
75+
76+
operator bool() const { return !Name.IsEmpty(); }
7577
};
7678

7779
// AssetLibEntry describes AssetLibrary registered in the AssetManager,

Common/game/main_game_file.cpp

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -425,43 +425,31 @@ void BuildAudioClipArray(const std::vector<String> &assets, std::vector<ScriptAu
425425
int temp_number;
426426
char temp_extension[10];
427427

428-
// FIXME: use audio type constants instead of obscure numeric literals
429428
for (const String &asset : assets)
430429
{
431430
if (sscanf(asset.GetCStr(), "%5s%d.%3s", temp_name, &temp_number, temp_extension) != 3)
432431
continue;
433432

434-
ScriptAudioClip clip;
435-
if (ags_stricmp(temp_extension, "mp3") == 0)
436-
clip.fileType = eAudioFileMP3;
437-
else if (ags_stricmp(temp_extension, "wav") == 0)
438-
clip.fileType = eAudioFileWAV;
439-
else if (ags_stricmp(temp_extension, "voc") == 0)
440-
clip.fileType = eAudioFileVOC;
441-
else if (ags_stricmp(temp_extension, "mid") == 0)
442-
clip.fileType = eAudioFileMIDI;
443-
else if ((ags_stricmp(temp_extension, "mod") == 0) || (ags_stricmp(temp_extension, "xm") == 0)
444-
|| (ags_stricmp(temp_extension, "s3m") == 0) || (ags_stricmp(temp_extension, "it") == 0))
445-
clip.fileType = eAudioFileMOD;
446-
else if (ags_stricmp(temp_extension, "ogg") == 0)
447-
clip.fileType = eAudioFileOGG;
448-
else
433+
AudioFileType file_type = ScriptAudioClip::GetAudioFileTypeFromExt(temp_extension);
434+
if (file_type == eAudioFileUndefined)
449435
continue;
450436

437+
ScriptAudioClip clip;
438+
clip.fileType = file_type;
451439
if (ags_stricmp(temp_name, "music") == 0)
452440
{
453441
clip.scriptName.Format("aMusic%d", temp_number);
454442
clip.fileName.Format("music%d.%s", temp_number, temp_extension);
455443
clip.bundlingType = (ags_stricmp(temp_extension, "mid") == 0) ? kAudioBundle_GamePak : kAudioBundle_AudioVox;
456-
clip.type = 2;
444+
clip.type = AUDIOTYPE_LEGACY_MUSIC;
457445
clip.defaultRepeat = 1;
458446
}
459447
else if (ags_stricmp(temp_name, "sound") == 0)
460448
{
461449
clip.scriptName.Format("aSound%d", temp_number);
462450
clip.fileName.Format("sound%d.%s", temp_number, temp_extension);
463451
clip.bundlingType = kAudioBundle_GamePak;
464-
clip.type = 3;
452+
clip.type = AUDIOTYPE_LEGACY_SOUND;
465453
clip.defaultRepeat = 0;
466454
}
467455
else
@@ -719,7 +707,7 @@ void RemapLegacySoundNums(GameSetupStruct &game, std::vector<ViewStruct> &views,
719707
game.scoreClipID = -1;
720708
if (game.options[OPT_SCORESOUND] > 0)
721709
{
722-
ScriptAudioClip* clip = GetAudioClipForOldStyleNumber(game, false, game.options[OPT_SCORESOUND]);
710+
const ScriptAudioClip* clip = GetAudioClipForOldStyleNumber(game, false, game.options[OPT_SCORESOUND]);
723711
if (clip)
724712
game.scoreClipID = clip->id;
725713
}

Editor/AGS.Editor/Resources/agsdefns.sh

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2496,6 +2496,10 @@ builtin managed struct AudioChannel {
24962496
/// Changes playback to continue from the specified position in milliseconds.
24972497
import void SeekMs(int position);
24982498
#endif // SCRIPT_API_v36026
2499+
#ifdef SCRIPT_API_v363
2500+
/// Gets which audio type current played clip is representing, or -1 if no clip is being played.
2501+
import readonly attribute AudioType PlayingType;
2502+
#endif // SCRIPT_API_v363
24992503
};
25002504

25012505
builtin managed struct AudioClip {
@@ -2512,13 +2516,17 @@ builtin managed struct AudioClip {
25122516
/// Plays this audio clip, explicitly putting it on the particular channel.
25132517
import AudioChannel* PlayOnChannel(int chan, AudioPriority=SCR_NO_VALUE, RepeatStyle=SCR_NO_VALUE);
25142518
#endif // SCRIPT_API_v360
2519+
#ifdef SCRIPT_API_v363
2520+
/// Plays this audio clip using certain AudioType settings, and optionally putting it on a particular channel.
2521+
import AudioChannel* PlayAsType(AudioType type, int chan=SCR_NO_VALUE, AudioPriority=SCR_NO_VALUE, RepeatStyle=SCR_NO_VALUE);
2522+
#endif // SCRIPT_API_v363
25152523
/// Stops all currently playing instances of this audio clip.
25162524
import void Stop();
25172525
/// Gets the file type of the sound.
25182526
readonly import attribute AudioFileType FileType;
25192527
/// Checks whether this audio file is available on the player's system.
25202528
readonly import attribute bool IsAvailable;
2521-
/// Gets the type of audio that this clip contains.
2529+
/// Gets the audio type that this clip belongs to.
25222530
readonly import attribute AudioType Type;
25232531
#ifdef SCRIPT_API_v350
25242532
/// Gets the clip's ID number.
@@ -3250,6 +3258,8 @@ builtin struct Game {
32503258
import static readonly attribute bool InBlockingWait;
32513259
#endif // SCRIPT_API_v362
32523260
#ifdef SCRIPT_API_v363
3261+
/// Play speech voice-over in non-blocking mode, using certain AudioType settings, and optionally putting it on a particular channel.
3262+
import static AudioChannel* PlayVoiceClipAsType(Character*, int cue, AudioType type, int chan=SCR_NO_VALUE, AudioPriority=SCR_NO_VALUE, RepeatStyle=SCR_NO_VALUE);
32533263
/// Gets/sets game's running speed, in frames per second.
32543264
import static attribute int Speed;
32553265
/// Gets number of game's ticks (updates) passed since the game start.

Engine/ac/audiochannel.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ ScriptAudioClip* AudioChannel_GetPlayingClip(ScriptAudioChannel *channel)
8585
return nullptr;
8686
}
8787

88+
int AudioChannel_GetPlayingType(ScriptAudioChannel *channel)
89+
{
90+
auto *ch = AudioChans::GetChannelIfPlaying(channel->id);
91+
if (ch)
92+
return ch->sourceClipType;
93+
return AUDIOTYPE_UNDEFINED;
94+
}
95+
8896
int AudioChannel_GetPosition(ScriptAudioChannel *channel)
8997
{
9098
auto* ch = AudioChans::GetChannelIfPlaying(channel->id);
@@ -175,7 +183,7 @@ void AudioChannel_Stop(ScriptAudioChannel *channel)
175183
if (channel->id == SCHAN_SPEECH && play.IsNonBlockingVoiceSpeech())
176184
stop_voice_nonblocking();
177185
else
178-
stop_or_fade_out_channel(channel->id, -1, nullptr);
186+
stop_or_fade_out_channel(channel->id, -1);
179187
}
180188

181189
void AudioChannel_Pause(ScriptAudioChannel *channel)
@@ -278,6 +286,11 @@ RuntimeScriptValue Sc_AudioChannel_GetPlayingClip(void *self, const RuntimeScrip
278286
API_OBJCALL_OBJ(ScriptAudioChannel, ScriptAudioClip, ccDynamicAudioClip, AudioChannel_GetPlayingClip);
279287
}
280288

289+
RuntimeScriptValue Sc_AudioChannel_GetPlayingType(void *self, const RuntimeScriptValue *params, int32_t param_count)
290+
{
291+
API_OBJCALL_INT(ScriptAudioChannel, AudioChannel_GetPlayingType);
292+
}
293+
281294
// int | ScriptAudioChannel *channel
282295
RuntimeScriptValue Sc_AudioChannel_GetPosition(void *self, const RuntimeScriptValue *params, int32_t param_count)
283296
{
@@ -378,6 +391,7 @@ void RegisterAudioChannelAPI()
378391
{ "AudioChannel::get_Panning", API_FN_PAIR(AudioChannel_GetPanning) },
379392
{ "AudioChannel::set_Panning", API_FN_PAIR(AudioChannel_SetPanning) },
380393
{ "AudioChannel::get_PlayingClip", API_FN_PAIR(AudioChannel_GetPlayingClip) },
394+
{ "AudioChannel::get_PlayingType", API_FN_PAIR(AudioChannel_GetPlayingType) },
381395
{ "AudioChannel::get_Position", API_FN_PAIR(AudioChannel_GetPosition) },
382396
{ "AudioChannel::get_PositionMs", API_FN_PAIR(AudioChannel_GetPositionMs) },
383397
{ "AudioChannel::get_Volume", API_FN_PAIR(AudioChannel_GetVolume) },

Engine/ac/audiochannel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ int AudioChannel_GetIsPlaying(ScriptAudioChannel *channel);
2626
int AudioChannel_GetPanning(ScriptAudioChannel *channel);
2727
void AudioChannel_SetPanning(ScriptAudioChannel *channel, int newPanning);
2828
ScriptAudioClip* AudioChannel_GetPlayingClip(ScriptAudioChannel *channel);
29+
int AudioChannel_GetPlayingType(ScriptAudioChannel *channel);
2930
int AudioChannel_GetPosition(ScriptAudioChannel *channel);
3031
int AudioChannel_GetPositionMs(ScriptAudioChannel *channel);
3132
int AudioChannel_GetLengthMs(ScriptAudioChannel *channel);

0 commit comments

Comments
 (0)