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| */