[proximity chat] muting and per-player volume

This commit is contained in:
Dominicentek 2026-06-01 04:33:46 +02:00
parent 3242b0bf0b
commit 6b0e1b01c9
21 changed files with 247 additions and 31 deletions

View file

@ -67,6 +67,14 @@ ALIGNED8 const Texture texture_microphone_muted[] = {
#include "textures/segment2/custom_microphone_muted.rgba16.inc.c"
};
ALIGNED8 const Texture texture_microphone_red[] = {
#include "textures/segment2/custom_microphone_red.rgba16.inc.c"
};
ALIGNED8 const Texture texture_microphone_red_muted[] = {
#include "textures/segment2/custom_microphone_red_muted.rgba16.inc.c"
};
ALIGNED8 const Texture texture_microphone_warning[] = {
#include "textures/segment2/custom_microphone_warning.rgba16.inc.c"
};

View file

@ -1562,6 +1562,8 @@ extern ALIGNED8 const Texture texture_ping_four[];
extern ALIGNED8 const Texture texture_ping_full[];
extern ALIGNED8 const Texture texture_microphone[];
extern ALIGNED8 const Texture texture_microphone_muted[];
extern ALIGNED8 const Texture texture_microphone_red[];
extern ALIGNED8 const Texture texture_microphone_red_muted[];
extern ALIGNED8 const Texture texture_microphone_warning[];
extern ALIGNED8 const Texture pss_seg7_texture_07000000[];
extern ALIGNED8 const Texture pss_seg7_texture_07000800[];

View file

@ -1191,6 +1191,8 @@ static const struct BuiltinTexInfo sDynosBuiltinTexs[] = {
// Proximity Chat Microphone Icons
define_builtin_tex(texture_microphone, "textures/segment2/custom_microphone.rgba16.png", 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b),
define_builtin_tex(texture_microphone_muted, "textures/segment2/custom_microphone_muted.rgba16.png", 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b),
define_builtin_tex(texture_microphone_red, "textures/segment2/custom_microphone_red.rgba16.png", 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b),
define_builtin_tex(texture_microphone_red_muted, "textures/segment2/custom_microphone_red_muted.rgba16.png", 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b),
define_builtin_tex(texture_microphone_warning, "textures/segment2/custom_microphone_warning.rgba16.png", 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b),
// Goddard

View file

@ -373,6 +373,7 @@ PLAYER = "Hráč"
DYNOS_PACKS = "DynOS packy"
OPTIONS = "Nastavení"
CHEATS = "Cheaty"
PROXIMITY_CHAT = "Proximity chat"
SERVER_SETTINGS = "Nastavení serveru"
RESUME = "Pokračovat"
STOP_HOSTING = "Vypnout server"

View file

@ -373,6 +373,7 @@ PLAYER = "Player"
DYNOS_PACKS = "DynOS Packs"
OPTIONS = "Options"
CHEATS = "Cheats"
PROXIMITY_CHAT = "Proximity Chat"
SERVER_SETTINGS = "Server Settings"
RESUME = "Resume"
STOP_HOSTING = "Stop Hosting"

View file

@ -599,12 +599,13 @@ void render_hud_proxchat(void) {
const Texture* tex = NULL;
if (proxchat_error[0] != PROXCHAT_ERR_NONE) tex = texture_microphone_warning;
else if (*proxchat_player_muted(0) & PROXCHAT_MUTE_GLOBAL) tex = texture_microphone_red_muted;
else if (configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK) {
if (proxchat_muted) tex = texture_microphone_muted;
if (*proxchat_player_muted(0) != PROXCHAT_UNMUTED) tex = texture_microphone_muted;
else tex = texture_microphone;
}
else if (configProxchatActivationMode == PROXCHAT_ACTMODE_THRESHOLD) {
if (proxchat_muted) tex = texture_microphone_muted;
if (*proxchat_player_muted(0) != PROXCHAT_UNMUTED) tex = texture_microphone_muted;
else if (proxchat_player_is_talking(0)) tex = texture_microphone;
else tex = NULL;
}

View file

@ -47,7 +47,7 @@ static void djui_button_destroy(struct DjuiBase* base) {
free(button);
}
struct DjuiButton* djui_button_create(struct DjuiBase* parent, const char* message, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*)) {
static struct DjuiButton* djui_button_create_base(struct DjuiBase* parent, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*)) {
struct DjuiButton* button = calloc(1, sizeof(struct DjuiButton));
struct DjuiBase* base = &button->base;
@ -62,7 +62,18 @@ struct DjuiButton* djui_button_create(struct DjuiBase* parent, const char* messa
djui_base_set_size(&rect->base, 1.0f, 1.0f);
button->rect = rect;
struct DjuiText* text = djui_text_create(&rect->base, message);
djui_base_set_size_type(base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(base, 1.0f, configDjuiThemeCenter ? 50 : 64);
djui_interactable_hook_click(base, on_click);
button->style = style;
return button;
}
struct DjuiButton* djui_button_create(struct DjuiBase* parent, const char* message, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*)) {
struct DjuiButton* button = djui_button_create_base(parent, style, on_click);
struct DjuiText* text = djui_text_create(&button->rect->base, message);
struct DjuiColor color = gDjuiThemes[configDjuiTheme]->interactables.textColor;
djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_RELATIVE);
@ -72,11 +83,19 @@ struct DjuiButton* djui_button_create(struct DjuiBase* parent, const char* messa
djui_text_set_drop_shadow(text, 64, 64, 64, 100);
button->text = text;
djui_base_set_size_type(base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(base, 1.0f, configDjuiThemeCenter ? 50 : 64);
djui_interactable_hook_click(base, on_click);
button->style = style;
djui_button_update_style(base);
djui_button_update_style(&button->base);
return button;
}
struct DjuiButton* djui_image_button_create(struct DjuiBase* parent, const Texture* tex, u16 width, u16 height, u8 fmt, u8 siz, enum DjuiButtonStyle style, void(*on_click)(struct DjuiBase*)) {
struct DjuiButton* button = djui_button_create_base(parent, style, on_click);
struct DjuiImage* icon = djui_image_create(&button->rect->base, tex, width, height, fmt, siz);
djui_base_set_alignment(&icon->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);
button->icon = icon;
djui_button_update_style(&button->base);
return button;
}

View file

@ -4,7 +4,10 @@
struct DjuiButton {
struct DjuiBase base;
struct DjuiRect* rect;
struct DjuiText* text;
union {
struct DjuiText* text;
struct DjuiImage* icon;
};
u8 style;
};
@ -16,5 +19,6 @@ enum DjuiButtonStyle {
void djui_button_set_style(struct DjuiButton* button, enum DjuiButtonStyle style);
struct DjuiButton* djui_button_create(struct DjuiBase* parent, const char* message, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*));
struct DjuiButton* djui_image_button_create(struct DjuiBase* parent, const Texture* tex, u16 width, u16 height, u8 fmt, u8 siz, enum DjuiButtonStyle style, void(*on_click)(struct DjuiBase*));
struct DjuiButton* djui_button_left_create(struct DjuiBase* parent, const char* message, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*));
struct DjuiButton* djui_button_right_create(struct DjuiBase* parent, const char* message, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*));

View file

@ -226,9 +226,14 @@ bool djui_interactable_on_key_down(int scancode) {
if (scancode == (int)configKeyPushToTalk[i]) pressPushToTalk = true;
}
u32* mute_state = proxchat_player_muted(0);
if (pressChat) djui_chat_box_toggle();
if (pressMute && configProxchatActivationMode == PROXCHAT_ACTMODE_THRESHOLD) proxchat_muted ^= 1; // flip
if (pressPushToTalk && configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK) proxchat_muted = false;
if (pressMute && configProxchatActivationMode == PROXCHAT_ACTMODE_THRESHOLD) {
if (*mute_state & PROXCHAT_MUTE_LOCAL) *mute_state &= ~PROXCHAT_MUTE_LOCAL;
else *mute_state |= PROXCHAT_MUTE_LOCAL;
}
if (pressPushToTalk && configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK)
*mute_state &= ~PROXCHAT_MUTE_LOCAL;
return pressChat || pressMute || pressPushToTalk;
}
@ -291,7 +296,8 @@ void djui_interactable_on_key_up(int scancode) {
}
if (toggleConsole) djui_console_toggle();
if (disablePushToTalk && configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK) proxchat_muted = true;
if (disablePushToTalk && configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK)
*proxchat_player_muted(0) |= PROXCHAT_MUTE_LOCAL;
}
if (gDjuiPlayerList != NULL || gDjuiModList != NULL) {

View file

@ -9,6 +9,7 @@
#include "djui_panel_menu.h"
#include "djui_panel_confirm.h"
#include "djui_panel_mod_menu.h"
#include "djui_panel_proximity_chat.h"
#include "pc/pc_main.h"
#include "pc/network/network.h"
#include "pc/lua/smlua_hooks.h"
@ -75,6 +76,9 @@ void djui_panel_pause_create(struct DjuiBase* caller) {
djui_button_create(body, DLANG(PAUSE, SERVER_SETTINGS), DJUI_BUTTON_STYLE_NORMAL, djui_panel_client_server_settings_create);
}
if (gServerSettings.proximityChat)
djui_button_create(body, DLANG(PAUSE, PROXIMITY_CHAT), DJUI_BUTTON_STYLE_NORMAL, djui_panel_proximity_chat_ingame_create);
struct Mod* addedMods[MAX_HOOKED_MOD_MENU_ELEMENTS] = { 0 };
int modCount = 0;
for (int i = 0; i < gHookedModMenuElementsCount; i++) {

View file

@ -4,6 +4,8 @@
#include "pc/configfile.h"
#include "pc/proximity_chat.h"
#include "pc/lua/utils/smlua_audio_utils.h"
#include "pc/network/network.h"
#include "pc/utils/misc.h"
static struct DjuiBase* activation_threshold_slider;
static float threshold;
@ -14,7 +16,10 @@ static void djui_panel_sound_value_change(UNUSED struct DjuiBase* caller) {
static void djui_panel_mode_value_change(UNUSED struct DjuiBase* caller) {
djui_base_set_enabled(activation_threshold_slider, configProxchatActivationMode == PROXCHAT_ACTMODE_THRESHOLD);
proxchat_muted = configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK;
u32* mute_state = proxchat_player_muted(0);
if (configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK) *mute_state |= PROXCHAT_MUTE_LOCAL;
else *mute_state &= ~PROXCHAT_MUTE_LOCAL;
}
static void djui_panel_threshold_value_change(UNUSED struct DjuiBase* caller) {
@ -52,3 +57,119 @@ void djui_panel_proximity_chat_create(struct DjuiBase* caller) {
djui_panel_add(caller, panel, NULL);
}
static struct DjuiImage* djui_texture_create(struct DjuiBase* base, struct TextureInfo* info) {
return djui_image_create(base, info->texture, info->width, info->height, info->format, info->size);
}
static struct DjuiPaginated* sPlayerPaginated;
static struct DjuiFlowLayout* sPlayerLayout;
static struct DjuiInputbox* sSearchInputbox = NULL;
static struct MicButton {
bool global;
s32 player_id;
struct DjuiBase* base;
struct DjuiButton* button;
} sMicButtons[32];
static void toggle_mute(struct DjuiBase* caller) {
struct MicButton* mic = NULL;
for (int i = 0; i < 32 && !mic; i++) {
if (sMicButtons[i].base == caller) mic = &sMicButtons[i];
}
if (!mic) return;
u32* mute_state = proxchat_player_muted(mic->player_id);
if (mic->global) {
if (*mute_state & PROXCHAT_MUTE_GLOBAL) *mute_state &= ~PROXCHAT_MUTE_GLOBAL;
else *mute_state |= PROXCHAT_MUTE_GLOBAL;
dynos_texture_get(*mute_state & PROXCHAT_MUTE_GLOBAL ? "texture_microphone_red_muted" : "texture_microphone_red", &mic->button->icon->textureInfo);
network_send_proxchat_muted(gNetworkPlayers[mic->player_id].globalIndex, *mute_state & PROXCHAT_MUTE_GLOBAL);
}
else {
if (*mute_state & PROXCHAT_MUTE_LOCAL) *mute_state &= ~PROXCHAT_MUTE_LOCAL;
else *mute_state |= PROXCHAT_MUTE_LOCAL;
dynos_texture_get(*mute_state & PROXCHAT_MUTE_LOCAL ? "texture_microphone_muted" : "texture_microphone", &mic->button->icon->textureInfo);
}
}
#define TEXTURE_INFO(tex) (tex).texture, (tex).width, (tex).height, (tex).format, (tex).size
static void djui_panel_proximity_chat_add_players(struct DjuiBase* body) {
s32 button_counter = 0;
for (int i = 1; i < MAX_PLAYERS; i++) {
if (!gNetworkPlayers[i].connected) continue;
if (sSearchInputbox != NULL &&
sSearchInputbox->buffer != NULL &&
!strstr_lowercased(djui_text_get_uncolored_string(NULL, strlen(gNetworkPlayers[i].name) + 1, gNetworkPlayers[i].name), sSearchInputbox->buffer)
) continue;
struct DjuiFlowLayout* layout = djui_flow_layout_create(body);
djui_flow_layout_set_flow_direction(layout, DJUI_FLOW_DIR_RIGHT);
djui_base_set_size_type(&layout->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&layout->base, 1, 32);
djui_base_set_color(&layout->base, 0, 0, 0, 0);
struct DjuiImage* icon = djui_texture_create(&layout->base, &gMarioStates[i].character->hudHeadTexture);
struct DjuiFlowLayout* inner_layout = djui_flow_layout_create(&layout->base);
djui_flow_layout_set_flow_direction(inner_layout, DJUI_FLOW_DIR_LEFT);
djui_base_set_size_type(&inner_layout->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&inner_layout->base, 1, 32);
djui_base_set_color(&inner_layout->base, 0, 0, 0, 0);
struct TextureInfo lmute_tex, gmute_tex;
dynos_texture_get(*proxchat_player_muted(i) & PROXCHAT_MUTE_LOCAL ? "texture_microphone_muted" : "texture_microphone", &lmute_tex);
dynos_texture_get(*proxchat_player_muted(i) & PROXCHAT_MUTE_GLOBAL ? "texture_microphone_red_muted" : "texture_microphone_red", &gmute_tex);
struct DjuiButton* gmute = djui_image_button_create(&inner_layout->base, TEXTURE_INFO(gmute_tex), DJUI_BUTTON_STYLE_NORMAL, toggle_mute);
struct DjuiButton* lmute = djui_image_button_create(&inner_layout->base, TEXTURE_INFO(lmute_tex), DJUI_BUTTON_STYLE_NORMAL, toggle_mute);
struct DjuiSlider* vol = djui_slider_create(&inner_layout->base, gNetworkPlayers[i].name, proxchat_player_volume(i), 0, 100, NULL);
sMicButtons[button_counter++] = (struct MicButton){ .base = &lmute->base, .button = lmute, .player_id = i, .global = false };
sMicButtons[button_counter++] = (struct MicButton){ .base = &gmute->base, .button = gmute, .player_id = i, .global = true };
djui_base_set_alignment(&vol->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_CENTER);
djui_base_set_alignment(&lmute->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_CENTER);
djui_base_set_alignment(&gmute->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_CENTER);
djui_base_set_size(&icon->base, 32, 32);
djui_base_set_size(&lmute->text->base, 32, 32);
djui_base_set_size(&gmute->text->base, 32, 32);
djui_base_set_size_type(&lmute->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE);
djui_base_set_size_type(&gmute->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&lmute->base, 32, 32);
djui_base_set_size(&gmute->base, 32, 32);
djui_base_set_enabled(&gmute->base, gNetworkPlayers[0].moderator || gNetworkPlayers[0].globalIndex == 0);
}
}
static void djui_panel_rebuild_players_list(UNUSED struct DjuiBase* caller) {
djui_base_destroy_children(&sPlayerLayout->base);
sPlayerLayout = sPlayerPaginated->layout;
djui_panel_proximity_chat_add_players(&sPlayerLayout->base);
djui_paginated_calculate_height(sPlayerPaginated);
}
void djui_panel_proximity_chat_ingame_create(struct DjuiBase* caller) {
struct DjuiThreePanel* panel = djui_panel_menu_create(DLANG(PROXCHAT, PROXIMITY_CHAT), false);
struct DjuiBase* body = djui_three_panel_get_body(panel);
{
struct DjuiSearchbox* searchbox = djui_searchbox_create(body, djui_panel_rebuild_players_list);
sSearchInputbox = searchbox->inputbox;
sPlayerPaginated = djui_paginated_create(body, 8);
sPlayerPaginated->showMaxCount = true;
sPlayerLayout = sPlayerPaginated->layout;
djui_panel_proximity_chat_add_players(&sPlayerLayout->base);
djui_paginated_calculate_height(sPlayerPaginated);
djui_button_create(body, DLANG(MENU, BACK), DJUI_BUTTON_STYLE_BACK, djui_panel_proxchat_back);
}
djui_panel_add(caller, panel, NULL);
}

View file

@ -2,3 +2,4 @@
#include "djui.h"
void djui_panel_proximity_chat_create(struct DjuiBase* caller);
void djui_panel_proximity_chat_ingame_create(struct DjuiBase* caller);

View file

@ -70,9 +70,9 @@ static void djui_slider_on_cursor_down(struct DjuiBase* base) {
f32 x = slider->rect->base.elem.x;
f32 w = slider->rect->base.elem.width;
f32 cursorX = gCursorX;
cursorX = fmax(cursorX, x);
cursorX = fmin(cursorX, x + w);
*value = ((cursorX - x) / w) * (max - min) + min;
if (cursorX < x) *value = min;
else if (cursorX > x + w) *value = max;
else *value = ((cursorX - x) / w) * (max - min) + min;
if (base != NULL && base->interactable != NULL && base->interactable->on_value_change != NULL) {
base->interactable->on_value_change(base);
}

View file

@ -173,9 +173,12 @@ void nametags_render(void) {
// render mic icon
if (proxchat_player_is_talking(playerIndex)) {
const char* mic = NULL;
if (*proxchat_player_muted(playerIndex) & PROXCHAT_MUTE_GLOBAL) mic = "texture_microphone_red_muted";
else if (proxchat_player_is_talking(playerIndex)) mic = "texture_microphone";
if (mic) {
struct TextureInfo texture;
dynos_texture_get("texture_microphone", &texture);
dynos_texture_get(mic, &texture);
djui_hud_render_texture_interpolated(&texture,
e->prevPos[0] - prevHalfWidth - 36 * e->prevScale, prevNametagPosY, e->prevScale * 2, e->prevScale * 2,
nametag->pos[0] - currHalfWidth - 36 * nametag->scale, currNametagPosY, nametag->scale * 2, nametag->scale * 2

View file

@ -101,6 +101,7 @@ void packet_process(struct Packet* p) {
case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break;
case PACKET_DEATH: network_receive_death(p); break;
case PACKET_PROXCHAT_FRAME: network_receive_proxchat_frame(p); break;
case PACKET_PROXCHAT_GLOBAL_MUTE: network_receive_proxchat_muted(p); break;
case PACKET_PING: network_receive_ping(p); break;
case PACKET_PONG: network_receive_pong(p); break;

View file

@ -37,6 +37,7 @@ enum PacketType {
PACKET_NETWORK_PLAYERS,
PACKET_DEATH,
PACKET_PROXCHAT_FRAME,
PACKET_PROXCHAT_GLOBAL_MUTE,
PACKET_PING,
PACKET_PONG,
@ -282,6 +283,8 @@ void network_receive_death(struct Packet* p);
// packet_proxchat.c
void network_send_proxchat_frame(void);
void network_receive_proxchat_frame(struct Packet* p);
void network_send_proxchat_muted(s32 globalIndex, bool mute);
void network_receive_proxchat_muted(struct Packet* p);
// packet_ping.c
void network_send_ping(struct NetworkPlayer* toNp);

View file

@ -23,5 +23,31 @@ void network_receive_proxchat_frame(struct Packet* p) {
u8 frame_data[frame_size];
packet_read(p, frame_data, frame_size);
proxchat_decode_audio(p->localIndex, frame_data, frame_size);
proxchat_decode_audio(
network_player_from_global_index(p->orderedFromGlobalId)->localIndex,
frame_data, frame_size
);
}
void network_send_proxchat_muted(s32 globalIndex, bool muted) {
struct Packet p = {};
packet_init(&p, PACKET_PROXCHAT_GLOBAL_MUTE, false, PLMT_NONE);
packet_write(&p, &globalIndex, sizeof(s32));
packet_write(&p, &muted, sizeof(bool));
network_send(&p);
}
void network_receive_proxchat_muted(struct Packet* p) {
s32 globalIndex;
bool muted;
packet_read(p, &globalIndex, sizeof(s32));
packet_read(p, &muted, sizeof(bool));
if (!network_player_from_global_index(p->orderedFromGlobalId)->moderator) return;
if (muted) *proxchat_player_muted(network_player_from_global_index(globalIndex)->localIndex) |= PROXCHAT_MUTE_GLOBAL;
else *proxchat_player_muted(network_player_from_global_index(globalIndex)->localIndex) &= ~PROXCHAT_MUTE_GLOBAL;
}

View file

@ -29,7 +29,7 @@ typedef struct {
} Buffer;
static struct {
bool muted;
u32 muted_state;
u32 volume;
Buffer audio;
union {
@ -40,7 +40,6 @@ static struct {
static bool inited = false;
bool proxchat_muted = false;
bool proxchat_loopback = false;
float proxchat_mic_level = 0;
@ -168,7 +167,8 @@ static void proxchat_callback(const u8* input, u32 bytes) {
if (!inited || gNetworkType == NT_NONE ||
configProxchatActivationMode == PROXCHAT_ACTMODE_DISABLED ||
!gServerSettings.proximityChat || proxchat_muted || is_below_threshold()
!gServerSettings.proximityChat || client->muted_state != PROXCHAT_UNMUTED ||
is_below_threshold()
) {
// drain the pcm buffer
buffer_drain(&client->audio);
@ -202,10 +202,11 @@ void proxchat_init() {
players[i].audio.capacity = FRAME_SIZE * MAX_FRAMES * sizeof(s16);
players[i].audio.dynamic = false;
players[i].volume = 1;
players[i].volume = 100;
}
proxchat_muted = configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK;
if (configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK)
client->muted_state |= PROXCHAT_MUTE_LOCAL;
inited = true;
}
@ -225,6 +226,10 @@ bool proxchat_inited() {
return inited;
}
u32* proxchat_player_muted(s32 id) {
return &players[id].muted_state;
}
u32* proxchat_player_volume(s32 id) {
return &players[id].volume;
}
@ -276,6 +281,12 @@ void proxchat_mix(s16* out_pcm, u32 num_out_samples) {
if (proxchat_num_frames_in_buffer(&players[i].audio) < MIN_FRAMES_REQUIRED) continue;
s16 player_pcm[num_samples];
u32 n = buffer_read(&players[i].audio, sizeof(player_pcm), player_pcm) / sizeof(s16);
memset(player_pcm + n, 0, sizeof(player_pcm) - n * sizeof(s16));
if (players[i].muted_state != PROXCHAT_UNMUTED) continue;
float volume;
float dist = vec3f_dist(gMarioStates[i].pos, gMarioState->pos);
if (dist < FULL_VOL_RADIUS) volume = 1;
@ -298,10 +309,6 @@ void proxchat_mix(s16* out_pcm, u32 num_out_samples) {
float pan_mono = 0.5f + pan * 0.5f * (configProxchatStereoSpread / 100.f);
float vol_right = pan_mono;
float vol_left = 1 - pan_mono;
s16 player_pcm[num_samples];
u32 n = buffer_read(&players[i].audio, sizeof(player_pcm), player_pcm) / sizeof(s16);
memset(player_pcm + n, 0, sizeof(player_pcm) - n * sizeof(s16));
for (s32 s = 0; s < num_samples * 2; s++) {
float pan_factor = s % 2 == 0 ? vol_left : vol_right;

View file

@ -3,7 +3,6 @@
#include "types.h"
extern bool proxchat_muted;
extern bool proxchat_loopback;
extern float proxchat_mic_level;
@ -21,13 +20,20 @@ enum ProxchatActivationMode {
PROXCHAT_ACTMODE_THRESHOLD
};
enum ProxchatMuteState {
PROXCHAT_UNMUTED = 0,
PROXCHAT_MUTE_LOCAL = (1 << 0),
PROXCHAT_MUTE_GLOBAL = (1 << 1),
};
void proxchat_init();
bool proxchat_inited();
void proxchat_shutdown();
const Texture* proxchat_get_microphone_texture();
bool* proxchat_player_muted(s32 id);
u32* proxchat_player_muted(s32 id);
u32* proxchat_player_volume(s32 id);
bool proxchat_player_is_talking(s32 id);

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B