Skip to content

Commit 3850116

Browse files
committed
Engine: save state of non-audioclip playbacks (such as voice)
1 parent 31ad768 commit 3850116

File tree

11 files changed

+102
-20
lines changed

11 files changed

+102
-20
lines changed

Common/ac/dynobj/scriptaudioclip.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,14 @@ enum AudioFileType {
3232
eAudioFileMOD = 6
3333
};
3434

35-
#define AUCL_BUNDLE_EXE 1
36-
#define AUCL_BUNDLE_VOX 2
35+
// TODO: consider turning this into generic "asset bundle type"?
36+
enum AudioClipBundle
37+
{
38+
kAudioBundle_Undefined = 0,
39+
kAudioBundle_GamePak = 1,
40+
kAudioBundle_AudioVox = 2,
41+
kAudioBundle_SpeechVox = 3
42+
};
3743

3844
#define LEGACY_AUDIOCLIP_SCRIPTNAMELENGTH 30
3945
#define LEGACY_AUDIOCLIP_FILENAMELENGTH 15
@@ -42,7 +48,7 @@ struct ScriptAudioClip {
4248
int id = 0;
4349
Common::String scriptName;
4450
Common::String fileName;
45-
uint8_t bundlingType = AUCL_BUNDLE_EXE;
51+
uint8_t bundlingType = kAudioBundle_Undefined;
4652
uint8_t type = 0;
4753
AudioFileType fileType = eAudioFileOGG;
4854
char defaultRepeat = 0;

Common/game/main_game_file.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,15 +452,15 @@ void BuildAudioClipArray(const std::vector<String> &assets, std::vector<ScriptAu
452452
{
453453
clip.scriptName.Format("aMusic%d", temp_number);
454454
clip.fileName.Format("music%d.%s", temp_number, temp_extension);
455-
clip.bundlingType = (ags_stricmp(temp_extension, "mid") == 0) ? AUCL_BUNDLE_EXE : AUCL_BUNDLE_VOX;
455+
clip.bundlingType = (ags_stricmp(temp_extension, "mid") == 0) ? kAudioBundle_GamePak : kAudioBundle_AudioVox;
456456
clip.type = 2;
457457
clip.defaultRepeat = 1;
458458
}
459459
else if (ags_stricmp(temp_name, "sound") == 0)
460460
{
461461
clip.scriptName.Format("aSound%d", temp_number);
462462
clip.fileName.Format("sound%d.%s", temp_number, temp_extension);
463-
clip.bundlingType = AUCL_BUNDLE_EXE;
463+
clip.bundlingType = kAudioBundle_GamePak;
464464
clip.type = 3;
465465
clip.defaultRepeat = 0;
466466
}

Engine/ac/file.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -892,9 +892,15 @@ String find_assetlib(const String &filename)
892892
return "";
893893
}
894894

895-
AssetPath get_audio_clip_assetpath(int /*bundling_type*/, const String &filename)
896-
{ // NOTE: bundling_type is ignored now
897-
return AssetPath(filename, "audio");
895+
AssetPath get_audio_clip_assetpath(int bundling_type, const String &filename)
896+
{
897+
switch (bundling_type)
898+
{
899+
case kAudioBundle_SpeechVox:
900+
return AssetPath(filename, "voice");
901+
default:
902+
return AssetPath(filename, "audio");
903+
}
898904
}
899905

900906
AssetPath get_voice_over_assetpath(const String &filename)

Engine/ac/global_audio.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,8 @@ static bool play_voice_clip_on_channel(const String &voice_name)
503503

504504
std::unique_ptr<SoundClip> voice_clip(load_sound_clip(apath, "", false));
505505
if (voice_clip != nullptr) {
506+
voice_clip->fileName = apath.Name;
507+
voice_clip->bundlingType = kAudioBundle_SpeechVox;
506508
voice_clip->set_volume255(play.speech_volume);
507509
if (!voice_clip->play())
508510
voice_clip.reset();

Engine/game/savegame.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -573,15 +573,26 @@ static HSaveError RestoreAudio(const RestoredData &r_data)
573573
for (int i = 0; i < TOTAL_AUDIO_CHANNELS; ++i)
574574
{
575575
const RestoredData::ChannelInfo &chan_info = r_data.AudioChans[i];
576-
if (chan_info.ClipID < 0)
576+
if (chan_info.ClipID < 0 && chan_info.FileName.IsEmpty())
577577
continue;
578-
if ((size_t)chan_info.ClipID >= game.audioClips.size())
578+
579+
if (chan_info.ClipID >= 0)
580+
{
581+
if ((size_t)chan_info.ClipID >= game.audioClips.size())
582+
{
583+
return new SavegameError(kSvgErr_GameObjectInitFailed,
584+
String::FromFormat("Invalid audio clip index: %d (clip count: %zu).", chan_info.ClipID, game.audioClips.size()));
585+
}
586+
587+
play_audio_clip_on_channel(i, &game.audioClips[chan_info.ClipID],
588+
chan_info.Priority, chan_info.Repeat, chan_info.Pos);
589+
}
590+
else
579591
{
580-
return new SavegameError(kSvgErr_GameObjectInitFailed,
581-
String::FromFormat("Invalid audio clip index: %d (clip count: %zu).", chan_info.ClipID, game.audioClips.size()));
592+
auto sound = load_sound_clip(chan_info.FileName, chan_info.BundlingType, chan_info.Repeat);
593+
if (sound)
594+
play_sound_on_channel(std::move(sound), i, chan_info.Priority, chan_info.Repeat, chan_info.Pos);
582595
}
583-
play_audio_clip_on_channel(i, &game.audioClips[chan_info.ClipID],
584-
chan_info.Priority, chan_info.Repeat, chan_info.Pos);
585596

586597
auto* ch = AudioChans::GetChannel(i);
587598
if (ch != nullptr)

Engine/game/savegame_components.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@ enum AudioSvgVersion
467467
kAudioSvgVersion_35026 = 1, // source position settings
468468
kAudioSvgVersion_36009 = 2, // up number of channels
469469
kAudioSvgVersion_36130 = 3060130, // playback state
470+
kAudioSvgVersion_36215 = 3060215, // clips referenced by filename
470471
};
471472

472473
HSaveError WriteAudio(Stream *out)
@@ -483,13 +484,17 @@ HSaveError WriteAudio(Stream *out)
483484
out->WriteInt32(play.default_audio_type_volumes[i]);
484485
}
485486

486-
// Audio clips and crossfade
487+
// Audio playbacks (from channels)
487488
for (int i = 0; i < TOTAL_AUDIO_CHANNELS; i++)
488489
{
489490
auto* ch = AudioChans::GetChannelIfPlaying(i);
490-
if ((ch != nullptr) && (ch->sourceClipID >= 0))
491+
if (ch)
491492
{
492493
out->WriteInt32(ch->sourceClipID);
494+
// kAudioSvgVersion_36215
495+
StrUtil::WriteString(ch->fileName, out);
496+
out->WriteInt8(ch->bundlingType);
497+
//
493498
out->WriteInt32(ch->get_pos());
494499
out->WriteInt32(ch->priority);
495500
out->WriteInt32(ch->repeat ? 1 : 0);
@@ -513,9 +518,13 @@ HSaveError WriteAudio(Stream *out)
513518
}
514519
else
515520
{
516-
out->WriteInt32(-1);
521+
out->WriteInt32(-1); // no clip id
522+
out->WriteInt32(0); // empty string (fileName)
523+
out->WriteInt8(kAudioBundle_Undefined);
517524
}
518525
}
526+
527+
// Crossfading
519528
out->WriteInt32(crossFading);
520529
out->WriteInt32(crossFadeVolumePerStep);
521530
out->WriteInt32(crossFadeStep);
@@ -567,7 +576,14 @@ HSaveError ReadAudio(Stream *in, int32_t cmp_ver, soff_t cmp_size, const Preserv
567576
RestoredData::ChannelInfo &chan_info = r_data.AudioChans[i];
568577
chan_info.Pos = 0;
569578
chan_info.ClipID = in->ReadInt32();
570-
if (chan_info.ClipID >= 0)
579+
580+
if (cmp_ver >= kAudioSvgVersion_36215)
581+
{
582+
chan_info.FileName = StrUtil::ReadString(in);
583+
chan_info.BundlingType = in->ReadInt8();
584+
}
585+
586+
if (chan_info.ClipID >= 0 || !chan_info.FileName.IsEmpty())
571587
{
572588
chan_info.Pos = in->ReadInt32();
573589
if (chan_info.Pos < 0)
@@ -1755,7 +1771,7 @@ ComponentHandler ComponentHandlers[] =
17551771
},
17561772
{
17571773
"Audio",
1758-
kAudioSvgVersion_36130,
1774+
kAudioSvgVersion_36215,
17591775
kAudioSvgVersion_Initial,
17601776
kSaveCmp_Audio,
17611777
WriteAudio,

Engine/game/savegame_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ struct RestoredData
187187
struct ChannelInfo
188188
{
189189
int ClipID = -1;
190+
String FileName;
191+
uint8_t BundlingType = kAudioBundle_Undefined;
190192
int Flags = 0;
191193
int Pos = 0;
192194
int Priority = 0;

Engine/media/audio/audio.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,21 @@ std::unique_ptr<SoundClip> load_sound_clip(ScriptAudioClip *audioClip, bool repe
263263
soundClip->set_volume100(audioClip->defaultVolume);
264264
soundClip->sourceClipID = audioClip->id;
265265
soundClip->sourceClipType = audioClip->type;
266+
soundClip->fileName = asset_name.Name;
267+
soundClip->bundlingType = audioClip->bundlingType;
268+
}
269+
return soundClip;
270+
}
271+
272+
std::unique_ptr<SoundClip> load_sound_clip(const String &filename, uint8_t bundleType, bool repeat)
273+
{
274+
AssetPath asset_name = get_audio_clip_assetpath(bundleType, filename);
275+
std::unique_ptr<SoundClip> soundClip = load_sound_clip(asset_name, nullptr, repeat);
276+
if (soundClip != nullptr)
277+
{
278+
soundClip->set_volume100(100);
279+
soundClip->fileName = asset_name.Name;
280+
soundClip->bundlingType = bundleType;
266281
}
267282
return soundClip;
268283
}
@@ -429,6 +444,20 @@ ScriptAudioChannel* play_audio_clip_on_channel(int channel, ScriptAudioClip *cli
429444
return &scrAudioChannel[channel];
430445
}
431446

447+
ScriptAudioChannel *play_sound_on_channel(std::unique_ptr<SoundClip> &&sound, int channel, int priority, int repeat, int fromOffset)
448+
{
449+
if (sound->play_from(fromOffset) == 0)
450+
{
451+
debug_script_log("Failed to play sound file %s", sound->fileName.GetCStr());
452+
return nullptr;
453+
}
454+
455+
sound->repeat = repeat;
456+
sound->priority = priority;
457+
AudioChans::SetChannel(channel, std::move(sound));
458+
return &scrAudioChannel[channel];
459+
}
460+
432461
void remove_clips_of_type_from_queue(int audioType)
433462
{
434463
int aa;

Engine/media/audio/audio.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616

1717
#include <array>
1818
#include <memory>
19-
#include "media/audio/audiodefines.h"
19+
#include "ac/timer.h"
2020
#include "ac/dynobj/scriptaudioclip.h"
2121
#include "ac/dynobj/scriptaudiochannel.h"
2222
#include "media/audio/ambientsound.h"
23+
#include "media/audio/audiodefines.h"
2324
#include "media/audio/soundclip.h"
25+
#include "util/string.h"
2426
#include "util/time_util.h"
2527

2628
class AudioChans
@@ -53,7 +55,9 @@ void update_clip_default_volume(ScriptAudioClip *audioClip);
5355
void start_fading_in_new_track_if_applicable(int fadeInChannel, ScriptAudioClip *newSound);
5456
void stop_or_fade_out_channel(int fadeOutChannel, int fadeInChannel = -1, ScriptAudioClip *newSound = nullptr);
5557
std::unique_ptr<SoundClip> load_sound_clip(ScriptAudioClip *audioClip, bool repeat);
58+
std::unique_ptr<SoundClip> load_sound_clip(const AGS::Common::String &filename, uint8_t bundleType, bool repeat);
5659
ScriptAudioChannel* play_audio_clip_on_channel(int channel, ScriptAudioClip *clip, int priority, int repeat, int fromOffset, std::unique_ptr<SoundClip> &&cachedClip = nullptr);
60+
ScriptAudioChannel *play_sound_on_channel(std::unique_ptr<SoundClip> &&sound, int channel, int priority, int repeat, int fromOffset);
5761
void remove_clips_of_type_from_queue(int audioType);
5862
void update_queued_clips_volume(int audioType, int new_vol);
5963
// Checks if speech voice-over is currently playing, and reapply volume drop to all other active clips

Engine/media/audio/soundclip.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//
1313
//=============================================================================
1414
#include <cmath>
15+
#include "ac/dynobj/scriptaudioclip.h"
1516
#include "media/audio/soundclip.h"
1617
#include "media/audio/audio_core.h"
1718

@@ -22,6 +23,7 @@ SoundClip::SoundClip(int slot, int snd_type, bool loop)
2223
{
2324
sourceClipID = -1;
2425
sourceClipType = 0;
26+
bundlingType = kAudioBundle_Undefined;
2527
priority = 50;
2628
vol255 = 0;
2729
vol100 = 0;

0 commit comments

Comments
 (0)