diff --git a/autogen/convert_constants.py b/autogen/convert_constants.py index 1b1d3cb19..fd214b72a 100644 --- a/autogen/convert_constants.py +++ b/autogen/convert_constants.py @@ -56,6 +56,7 @@ in_files = [ "include/PR/gbi.h", "include/PR/gbi_extension.h", "src/engine/surface_load.h", + "src/pc/lua/utils/smlua_audio_utils.h", ] exclude_constants = { @@ -77,6 +78,7 @@ include_constants = { "include/geo_commands.h": [ "BACKGROUND" ], "include/level_commands.h": [ "WARP_CHECKPOINT", "WARP_NO_CHECKPOINT" ], "src/audio/external.h": [ "SEQ_PLAYER", "DS_" ], + "src/pc/lua/utils/smlua_audio_utils.h": ["MOD_AUDIO_CHANNEL"], "src/pc/mods/mod_storage.h": [ "MAX_KEYS", "MAX_KEY_VALUE_LENGTH" ], "include/PR/gbi.h": [ "^G_NOOP$", diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index de75db5d8..22942ec37 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -97,7 +97,7 @@ override_field_invisible = { "FnGraphNode": [ "luaTokenIndex" ], "Object": [ "firstSurface" ], "Animation": [ "unusedBoneCount" ], - "ModAudio": [ "sound", "decoder", "buffer", "bufferSize", "sampleCopiesTail" ], + "ModAudio": [ "sound", "decoder", "buffer", "bufferSize", "sampleCopiesTail", "volChannel" ], "Painting": [ "normalDisplayList", "textureMaps", "rippleDisplayList", "ripples" ], "DialogEntry": [ "str" ], "ModFsFile": [ "data", "capacity" ], diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index da3fa0573..0825c31b0 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -8171,6 +8171,18 @@ VALID_BUTTONS = (A_BUTTON | B_BUTTON | Z_TRIG | START_BUTTON | U_JPAD | D_JPAD | --- @type integer C_BUTTONS = (U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS ) +--- @type integer +MOD_AUDIO_CHANNEL_MASTER = 0 + +--- @type integer +MOD_AUDIO_CHANNEL_MUSIC = 1 + +--- @type integer +MOD_AUDIO_CHANNEL_SFX = 2 + +--- @type integer +MOD_AUDIO_CHANNEL_ENV = 3 + HOOK_UPDATE = 0 --- @type LuaHookedEventType HOOK_MARIO_UPDATE = 1 --- @type LuaHookedEventType HOOK_BEFORE_MARIO_UPDATE = 2 --- @type LuaHookedEventType diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 398012557..37531004a 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -10334,6 +10334,20 @@ function audio_stream_set_volume(audio, volume) -- ... end +--- @param audio ModAudio +--- @return integer +--- Gets the volume channel of an `audio` stream +function audio_stream_get_volume_channel(audio) + -- ... +end + +--- @param audio ModAudio +--- @param channel integer +--- Sets the volume channel of an `audio` stream +function audio_stream_set_volume_channel(audio, channel) + -- ... +end + --- @param filename string --- @return ModAudio --- Loads an `audio` sample diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 23c52dca7..668e3a358 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -1212,6 +1212,7 @@ --- @field public looping boolean --- @field public frequency number --- @field public volume number +--- @field public channel integer --- @class ModFs --- @field public mod Mod diff --git a/docs/lua/constants.md b/docs/lua/constants.md index df90c089e..78590ed1e 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -79,6 +79,7 @@ - [seq_ids.h](#seq_idsh) - [enum SeqId](#enum-SeqId) - [sm64.h](#sm64h) +- [smlua_audio_utils.h](#smlua_audio_utilsh) - [smlua_hooks.h](#smlua_hooksh) - [enum LuaHookedEventType](#enum-LuaHookedEventType) - [enum LuaHookedEventReturn](#enum-LuaHookedEventReturn) @@ -3486,6 +3487,16 @@
+## [smlua_audio_utils.h](#smlua_audio_utils.h) +- MOD_AUDIO_CHANNEL_MASTER +- MOD_AUDIO_CHANNEL_MUSIC +- MOD_AUDIO_CHANNEL_SFX +- MOD_AUDIO_CHANNEL_ENV + +[:arrow_up_small:](#) + +
+ ## [smlua_hooks.h](#smlua_hooks.h) ### [enum LuaHookedEventType](#LuaHookedEventType) diff --git a/docs/lua/functions-6.md b/docs/lua/functions-6.md index 30ecdc81f..8c21d8868 100644 --- a/docs/lua/functions-6.md +++ b/docs/lua/functions-6.md @@ -5947,6 +5947,53 @@ Sets the volume of an `audio` stream
+## [audio_stream_get_volume_channel](#audio_stream_get_volume_channel) + +### Description +Gets the volume channel of an `audio` stream + +### Lua Example +`local integerValue = audio_stream_get_volume_channel(audio)` + +### Parameters +| Field | Type | +| ----- | ---- | +| audio | [ModAudio](structs.md#ModAudio) | + +### Returns +- `integer` + +### C Prototype +`u8 audio_stream_get_volume_channel(struct ModAudio *audio);` + +[:arrow_up_small:](#) + +
+ +## [audio_stream_set_volume_channel](#audio_stream_set_volume_channel) + +### Description +Sets the volume channel of an `audio` stream + +### Lua Example +`audio_stream_set_volume_channel(audio, channel)` + +### Parameters +| Field | Type | +| ----- | ---- | +| audio | [ModAudio](structs.md#ModAudio) | +| channel | `integer` | + +### Returns +- None + +### C Prototype +`void audio_stream_set_volume_channel(struct ModAudio *audio, u8 channel);` + +[:arrow_up_small:](#) + +
+ ## [audio_sample_load](#audio_sample_load) ### Description diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 242183052..fd2fb18b3 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1849,6 +1849,8 @@ - [audio_stream_set_frequency](functions-6.md#audio_stream_set_frequency) - [audio_stream_get_volume](functions-6.md#audio_stream_get_volume) - [audio_stream_set_volume](functions-6.md#audio_stream_set_volume) + - [audio_stream_get_volume_channel](functions-6.md#audio_stream_get_volume_channel) + - [audio_stream_set_volume_channel](functions-6.md#audio_stream_set_volume_channel) - [audio_sample_load](functions-6.md#audio_sample_load) - [audio_sample_destroy](functions-6.md#audio_sample_destroy) - [audio_sample_stop](functions-6.md#audio_sample_stop) diff --git a/docs/lua/structs.md b/docs/lua/structs.md index b14ade940..c7b911d43 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -1768,6 +1768,7 @@ | looping | `boolean` | | | frequency | `number` | | | volume | `number` | | +| channel | `integer` | | [:arrow_up_small:](#) diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index 5464829c4..303565be5 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -1494,18 +1494,19 @@ static struct LuaObjectField sModFields[LUA_MOD_FIELD_COUNT] = { { "size", LVT_U64, offsetof(struct Mod, size), true, LOT_NONE }, }; -#define LUA_MOD_AUDIO_FIELD_COUNT 10 +#define LUA_MOD_AUDIO_FIELD_COUNT 11 static struct LuaObjectField sModAudioFields[LUA_MOD_AUDIO_FIELD_COUNT] = { - { "baseVolume", LVT_F32, offsetof(struct ModAudio, baseVolume), false, LOT_NONE }, - { "file", LVT_PROPERTY, .get = "return_self" }, - { "filepath", LVT_STRING_P, offsetof(struct ModAudio, filepath), true, LOT_NONE }, - { "frequency", LVT_PROPERTY, .get = "audio_stream_get_frequency", .set = "audio_stream_set_frequency" }, - { "isStream", LVT_BOOL, offsetof(struct ModAudio, isStream), true, LOT_NONE }, - { "loaded", LVT_BOOL, offsetof(struct ModAudio, loaded), true, LOT_NONE }, - { "looping", LVT_PROPERTY, .get = "audio_stream_get_looping", .set = "audio_stream_set_looping" }, - { "position", LVT_PROPERTY, .get = "audio_stream_get_position", .set = "audio_stream_set_position" }, - { "relativePath", LVT_STRING_P, offsetof(struct ModAudio, relativePath), true, LOT_NONE }, - { "volume", LVT_PROPERTY, .get = "audio_stream_get_volume", .set = "audio_stream_set_volume" }, + { "baseVolume", LVT_F32, offsetof(struct ModAudio, baseVolume), false, LOT_NONE }, + { "channel", LVT_PROPERTY, .get = "audio_stream_get_volume_channel", .set = "audio_stream_set_volume_channel" }, + { "file", LVT_PROPERTY, .get = "return_self" }, + { "filepath", LVT_STRING_P, offsetof(struct ModAudio, filepath), true, LOT_NONE }, + { "frequency", LVT_PROPERTY, .get = "audio_stream_get_frequency", .set = "audio_stream_set_frequency" }, + { "isStream", LVT_BOOL, offsetof(struct ModAudio, isStream), true, LOT_NONE }, + { "loaded", LVT_BOOL, offsetof(struct ModAudio, loaded), true, LOT_NONE }, + { "looping", LVT_PROPERTY, .get = "audio_stream_get_looping", .set = "audio_stream_set_looping" }, + { "position", LVT_PROPERTY, .get = "audio_stream_get_position", .set = "audio_stream_set_position" }, + { "relativePath", LVT_STRING_P, offsetof(struct ModAudio, relativePath), true, LOT_NONE }, + { "volume", LVT_PROPERTY, .get = "audio_stream_get_volume", .set = "audio_stream_set_volume" }, }; #define LUA_MOD_FS_FIELD_COUNT 15 diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 9285bef76..80c6dcb85 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -3495,6 +3495,10 @@ char gSmluaConstants[] = "" "ACT_RELEASING_BOWSER=0x00000392\n" "VALID_BUTTONS=(A_BUTTON | B_BUTTON | Z_TRIG | START_BUTTON | U_JPAD | D_JPAD | L_JPAD | R_JPAD | L_TRIG | R_TRIG | X_BUTTON | Y_BUTTON | U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS )\n" "C_BUTTONS=(U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS )\n" +"MOD_AUDIO_CHANNEL_MASTER=0\n" +"MOD_AUDIO_CHANNEL_MUSIC=1\n" +"MOD_AUDIO_CHANNEL_SFX=2\n" +"MOD_AUDIO_CHANNEL_ENV=3\n" "HOOK_UPDATE=0\n" "HOOK_MARIO_UPDATE=1\n" "HOOK_BEFORE_MARIO_UPDATE=2\n" diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 736f2dbb2..d5d8acca7 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -30774,6 +30774,42 @@ int smlua_func_audio_stream_set_volume(lua_State* L) { return 1; } +int smlua_func_audio_stream_get_volume_channel(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "audio_stream_get_volume_channel", 1, top); + return 0; + } + + struct ModAudio* audio = (struct ModAudio*)smlua_to_cobject(L, 1, LOT_MODAUDIO); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "audio_stream_get_volume_channel"); return 0; } + + lua_pushinteger(L, audio_stream_get_volume_channel(audio)); + + return 1; +} + +int smlua_func_audio_stream_set_volume_channel(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "audio_stream_set_volume_channel", 2, top); + return 0; + } + + struct ModAudio* audio = (struct ModAudio*)smlua_to_cobject(L, 1, LOT_MODAUDIO); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "audio_stream_set_volume_channel"); return 0; } + u8 channel = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "audio_stream_set_volume_channel"); return 0; } + + audio_stream_set_volume_channel(audio, channel); + + return 1; +} + int smlua_func_audio_sample_load(lua_State* L) { if (L == NULL) { return 0; } @@ -38680,6 +38716,8 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "audio_stream_set_frequency", smlua_func_audio_stream_set_frequency); smlua_bind_function(L, "audio_stream_get_volume", smlua_func_audio_stream_get_volume); smlua_bind_function(L, "audio_stream_set_volume", smlua_func_audio_stream_set_volume); + smlua_bind_function(L, "audio_stream_get_volume_channel", smlua_func_audio_stream_get_volume_channel); + smlua_bind_function(L, "audio_stream_set_volume_channel", smlua_func_audio_stream_set_volume_channel); smlua_bind_function(L, "audio_sample_load", smlua_func_audio_sample_load); smlua_bind_function(L, "audio_sample_destroy", smlua_func_audio_sample_destroy); smlua_bind_function(L, "audio_sample_stop", smlua_func_audio_sample_stop); diff --git a/src/pc/lua/utils/smlua_audio_utils.c b/src/pc/lua/utils/smlua_audio_utils.c index 09a81633f..7686f9094 100644 --- a/src/pc/lua/utils/smlua_audio_utils.c +++ b/src/pc/lua/utils/smlua_audio_utils.c @@ -363,10 +363,24 @@ struct ModAudio* audio_load_internal(const char* filename, bool isStream) { audio->buffer = buffer; audio->bufferSize = size; audio->isStream = isStream; + audio->baseVolume = 1.0f; + audio->volChannel = MOD_AUDIO_CHANNEL_MUSIC; audio->loaded = true; return audio; } +static f32 get_audio_volume(struct ModAudio* audio) { + f32 volume = audio->baseVolume; + if (audio->volChannel == MOD_AUDIO_CHANNEL_MUSIC) { + volume *= (f32)configMusicVolume / 127.0f * (f32)gLuaVolumeLevel / 127.0f; + } else if (audio->volChannel == MOD_AUDIO_CHANNEL_SFX) { + volume *= (f32)configSfxVolume / 127.0f * (f32)gLuaVolumeSfx / 127.0f; + } else if (audio->volChannel == MOD_AUDIO_CHANNEL_ENV) { + volume *= (f32)configEnvVolume / 127.0f * (f32)gLuaVolumeEnv / 127.0f; + } + return gMasterVolume * volume; +} + struct ModAudio* audio_stream_load(const char* filename) { return audio_load_internal(filename, true); } @@ -388,6 +402,7 @@ void audio_stream_play(struct ModAudio* audio, bool restart, f32 volume) { ma_sound_set_volume(&audio->sound, gMasterVolume * musicVolume * volume); } audio->baseVolume = volume; + ma_sound_set_volume(&audio->sound, get_audio_volume(audio)); if (restart || !ma_sound_is_playing(&audio->sound)) { ma_sound_seek_to_pcm_frame(&audio->sound, 0); } ma_sound_start(&audio->sound); } @@ -473,14 +488,9 @@ f32 audio_stream_get_volume(struct ModAudio* audio) { void audio_stream_set_volume(struct ModAudio* audio, f32 volume) { if (!audio_sanity_check(audio, true, "set stream volume for")) { return; } - - if (configMuteFocusLoss && !WAPI.has_focus()) { - ma_sound_set_volume(&audio->sound, 0); - } else { - f32 musicVolume = (f32)configMusicVolume / 127.0f * (f32)gLuaVolumeLevel / 127.0f; - ma_sound_set_volume(&audio->sound, gMasterVolume * musicVolume * volume); - } + audio->baseVolume = volume; + ma_sound_set_volume(&audio->sound, get_audio_volume(audio)); } // void audio_stream_set_speed(struct ModAudio* audio, f32 initial_freq, f32 speed, bool pitch) { @@ -489,6 +499,28 @@ void audio_stream_set_volume(struct ModAudio* audio, f32 volume) { // bassh_set_speed(audio->handle, initial_freq, speed, pitch); // } +u8 audio_stream_get_volume_channel(struct ModAudio* audio) { + if (!audio_sanity_check(audio, true, "get stream volume channel from")) { + return 0; + } + + return audio->volChannel; +} + +void audio_stream_set_volume_channel(struct ModAudio* audio, u8 channel) { + if (!audio_sanity_check(audio, true, "set stream volume channel for")) { + return; + } + + if (channel > MOD_AUDIO_CHANNEL_ENV) { + LOG_LUA_LINE("Tried to set volume channel to invalid value: %d", channel); + return; + } + + audio->volChannel = channel; + ma_sound_set_volume(&audio->sound, get_audio_volume(audio)); +} + ////////////////////////////////////// // MA calls the end callback from its audio thread diff --git a/src/pc/lua/utils/smlua_audio_utils.h b/src/pc/lua/utils/smlua_audio_utils.h index 78a078410..880f80558 100644 --- a/src/pc/lua/utils/smlua_audio_utils.h +++ b/src/pc/lua/utils/smlua_audio_utils.h @@ -15,6 +15,11 @@ u8 smlua_audio_utils_allocate_sequence(void); // mod sounds // //////////////// +#define MOD_AUDIO_CHANNEL_MASTER 0 +#define MOD_AUDIO_CHANNEL_MUSIC 1 +#define MOD_AUDIO_CHANNEL_SFX 2 +#define MOD_AUDIO_CHANNEL_ENV 3 + struct ModAudioSampleCopies { ma_sound sound; ma_decoder decoder; @@ -35,12 +40,14 @@ struct ModAudio { struct ModAudioSampleCopies* sampleCopiesTail; bool isStream; f32 baseVolume; + u8 volChannel; bool loaded; PROPERTY(position, audio_stream_get_position, audio_stream_set_position); PROPERTY(looping, audio_stream_get_looping, audio_stream_set_looping); PROPERTY(frequency, audio_stream_get_frequency, audio_stream_set_frequency); PROPERTY(volume, audio_stream_get_volume, audio_stream_set_volume); + PROPERTY(channel, audio_stream_get_volume_channel, audio_stream_set_volume_channel); PROPERTY(file, return_self, NULL); // compatibility band-aid }; @@ -73,6 +80,10 @@ void audio_stream_set_frequency(struct ModAudio* audio, f32 freq); f32 audio_stream_get_volume(struct ModAudio* audio); /* |description|Sets the volume of an `audio` stream|descriptionEnd| */ void audio_stream_set_volume(struct ModAudio* audio, f32 volume); +/* |description|Gets the volume channel of an `audio` stream|descriptionEnd| */ +u8 audio_stream_get_volume_channel(struct ModAudio *audio); +/* |description|Sets the volume channel of an `audio` stream|descriptionEnd| */ +void audio_stream_set_volume_channel(struct ModAudio *audio, u8 channel); void audio_sample_destroy_pending_copies(void); /* |description|Loads an `audio` sample|descriptionEnd| */