Skip to content

Commit

Permalink
EXPERIMENT: IAGSAudioPlayer
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-mogilko committed Feb 10, 2024
1 parent 86ee891 commit 8a07069
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 6 deletions.
58 changes: 57 additions & 1 deletion Engine/plugin/agsplugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
#include "main/engine.h"
#include "main/game_run.h"
#include "media/audio/audio_system.h"
#include "media/audio/openalsource.h"
#include "media/audio/sdldecoder.h"
#include "script/script.h"
#include "script/script_runtime.h"
#include "plugin/plugin_engine.h"
Expand Down Expand Up @@ -97,7 +99,7 @@ extern RuntimeScriptValue GlobalReturnValue;
// **************** PLUGIN IMPLEMENTATION ****************


const int PLUGIN_API_VERSION = 28;
const int PLUGIN_API_VERSION = 29;
struct EnginePlugin
{
EnginePlugin() {
Expand Down Expand Up @@ -827,6 +829,60 @@ ::IAGSStream *IAGSEngine::GetFileStreamByHandle(int32 fhandle)
get_file_stream(fhandle, "IAGSEngine::GetFileStreamByHandle"));
}

class AGSAudioPlayer : public IAGSAudioPlayer
{
public:
AGSAudioPlayer(std::unique_ptr<OpenAlSource> &&src)
: _audioOut(std::move(src))
{
_audioOut->Play();
}
virtual ~AGSAudioPlayer() = default;

// Tells which version of the plugin API this object corresponds to;
// this lets users know which of the following methods are valid to use.
int GetVersion() override
{
return PLUGIN_API_VERSION;
}
void SetConfig(AGSAudioPlayConfig *config) override
{
_audioOut->SetVolume(config->Volume);
}
void Close() override
{
delete this; // darn...
}
void Pause() override
{
_audioOut->Pause();
}
void Resume() override
{
_audioOut->Resume();
}
size_t PutData(AGSAudioFrame *frame) override
{
SoundBuffer buf(frame->Data, frame->DataSize, frame->Timestamp);
size_t put_sz = _audioOut->PutData(buf);
_audioOut->Poll();
return put_sz;
}

private:
std::unique_ptr<OpenAlSource> _audioOut;
};

IAGSAudioPlayer *IAGSEngine::OpenAudioPlayer(AGSAudioFormat *in_format, AGSAudioPlayConfig *config)
{
SDL_AudioFormat sdl_fmt = in_format->Format; // todo convert
int chans = in_format->Channels;
int freq = in_format->Freq;
auto *player = new AGSAudioPlayer(
std::unique_ptr<OpenAlSource>(new OpenAlSource(sdl_fmt, chans, freq)));
return player; // todo: should save somewhere for safe close on exit??
}

// *********** General plugin implementation **********

void pl_stop_plugins() {
Expand Down
69 changes: 64 additions & 5 deletions Engine/plugin/agsplugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,15 +229,15 @@ class IAGSScriptManagedObject {
virtual int Serialize(void *address, char *buffer, int bufsize) = 0;
protected:
IAGSScriptManagedObject() {};
~IAGSScriptManagedObject() {};
virtual ~IAGSScriptManagedObject() {};
};

class IAGSManagedObjectReader {
public:
virtual void Unserialize(int key, const char *serializedData, int dataSize) = 0;
protected:
IAGSManagedObjectReader() {};
~IAGSManagedObjectReader() {};
virtual ~IAGSManagedObjectReader() {};
};

class IAGSFontRenderer {
Expand All @@ -252,7 +252,7 @@ class IAGSFontRenderer {
virtual void EnsureTextValidForFont(char *text, int fontNumber) = 0;
protected:
IAGSFontRenderer() = default;
~IAGSFontRenderer() = default;
virtual ~IAGSFontRenderer() = default;
};

class IAGSFontRenderer2 : public IAGSFontRenderer {
Expand All @@ -263,7 +263,7 @@ class IAGSFontRenderer2 : public IAGSFontRenderer {
virtual int GetLineSpacing(int fontNumber) = 0;
protected:
IAGSFontRenderer2() = default;
~IAGSFontRenderer2() = default;
virtual ~IAGSFontRenderer2() = default;
};

struct AGSRenderMatrixes {
Expand Down Expand Up @@ -375,7 +375,61 @@ class IAGSStream {

protected:
IAGSStream() = default;
~IAGSStream() = default;
virtual ~IAGSStream() = default;
};

#define AGS_AUDIOPLAY_FLD_VOLUME 0x0001

#define AGS_AUDIOFRAME_FLD_DATA 0x0001
#define AGS_AUDIOFRAME_FLD_TIMESTAMP 0x0002

// use sdl2 format for test, but maybe switch to our own custom values just in case?
#define AGS_AUDIOFORMAT_F32 0x8120

struct AGSAudioFormat
{
// Set which fields are valid, see AGS_AUDIOFORMAT_FLD_* flags
uint32_t Fields;
int Format; // s16, s32, f16, f32, etc
int Channels;
int Freq;
};

struct AGSAudioPlayConfig
{
// Set which fields are valid, see AGS_AUDIOPLAY_FLD_* flags
uint32_t Fields;
float Volume;
};

struct AGSAudioFrame
{
// Set which fields are valid, see AGS_AUDIOFRAME_FLD_* flags
uint32_t Fields;
void *Data;
size_t DataSize;
int64_t Timestamp;
};

// Something that plays the sound data
class IAGSAudioPlayer {
public:
// Tells which version of the plugin API this object corresponds to;
// this lets users know which of the following methods are valid to use.
virtual int GetVersion() = 0;
virtual void SetConfig(AGSAudioPlayConfig *config) = 0;
// Flushes and closes the AudioPlayer.
// After calling this the IAGSAudioPlayer pointer becomes INVALID.
virtual void Close() = 0;
virtual void Pause() = 0;
virtual void Resume() = 0;
// *copies* data on call, does not hold the frame (??? need different rule?)
// returns amount of data copied, or 0 if data cannot be accepted at the moment.
virtual size_t PutData(AGSAudioFrame *frame) = 0;

protected:
IAGSAudioPlayer() = default;
~IAGSAudioPlayer() = default;
};


Expand Down Expand Up @@ -652,6 +706,11 @@ class IAGSEngine {
// this stream should not be closed or disposed, doing so will lead to errors in the engine.
// Returns null if handle is invalid.
AGSIFUNC(IAGSStream*) GetFileStreamByHandle(int32 fhandle);

// *** BELOW ARE INTERFACE VERSION 29 AND ABOVE ONLY
// open audio player, telling the format of the sound data that will be SENT into this player by user.
// optionally pass AGSAudioPlayConfig setting playback parameters (these may be reset later).
AGSIFUNC(IAGSAudioPlayer*) OpenAudioPlayer(AGSAudioFormat *in_format, AGSAudioPlayConfig *config);
};


Expand Down

0 comments on commit 8a07069

Please sign in to comment.