Skip to content

Commit fc5b743

Browse files
committed
player volume
1 parent 359b8da commit fc5b743

18 files changed

Lines changed: 313 additions & 35 deletions

src/main/java/cn/ussshenzhou/channel/Channel.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package cn.ussshenzhou.channel;
22

33
import cn.ussshenzhou.channel.config.ChannelClientConfig;
4+
import cn.ussshenzhou.channel.config.ChannelPlayerConfig;
45
import cn.ussshenzhou.channel.config.ChannelServerConfig;
56
import cn.ussshenzhou.t88.config.ConfigHelper;
7+
import net.neoforged.api.distmarker.Dist;
68
import net.neoforged.bus.api.IEventBus;
79
import net.neoforged.fml.ModContainer;
810
import net.neoforged.fml.common.Mod;
11+
import net.neoforged.fml.loading.FMLEnvironment;
912

1013
/**
1114
* @author USS_Shenzhou
@@ -15,7 +18,10 @@ public class Channel {
1518
public static final String MODID = "channel";
1619

1720
public Channel(IEventBus modEventBus, ModContainer modContainer) {
18-
ConfigHelper.loadConfig(new ChannelClientConfig());
21+
if (FMLEnvironment.dist == Dist.CLIENT) {
22+
ConfigHelper.loadConfig(new ChannelClientConfig());
23+
ConfigHelper.loadConfig(new ChannelPlayerConfig());
24+
}
1925
ConfigHelper.loadConfig(new ChannelServerConfig());
2026
}
2127
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package cn.ussshenzhou.channel.audio;
2+
3+
import cn.ussshenzhou.channel.util.AudioHelper;
4+
import cn.ussshenzhou.t88.gui.util.ITranslatable;
5+
6+
/**
7+
* @author USS_Shenzhou
8+
*/
9+
10+
public enum Unit implements ITranslatable {
11+
DB("Channel.config.unit.db"),
12+
PERCENT("Channel.config.unit.per");
13+
14+
private final String translateKey;
15+
16+
Unit(String translateKey) {
17+
this.translateKey = translateKey;
18+
}
19+
20+
public String get(double db) {
21+
return switch (this) {
22+
case DB -> String.format("%.1f", db) + " dB";
23+
case PERCENT -> String.format("%.2f", AudioHelper.db2factor((float) db) * 100) + "%";
24+
};
25+
}
26+
27+
@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
28+
public String getFS(double value) {
29+
return switch (this) {
30+
case DB -> value == 0 ? "-∞ dBFS" : String.format("%.1f dBFS", value);
31+
case PERCENT -> String.format("%.2f", AudioHelper.db2factor((float) value) * 100) + "%";
32+
};
33+
}
34+
35+
@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
36+
public String getFS90(double value) {
37+
return switch (this) {
38+
case DB -> value == 0 ? "-∞ dBFS" : String.format("%.1f dBFS", value - 90);
39+
case PERCENT -> String.format("%.2f", AudioHelper.db2factor((float) value - 90) * 100) + "%";
40+
};
41+
}
42+
43+
@Override
44+
public String translateKey() {
45+
return translateKey;
46+
}
47+
}

src/main/java/cn/ussshenzhou/channel/audio/client/receive/BaseAudioManager.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.lwjgl.openal.AL;
1111
import org.lwjgl.openal.ALC;
1212

13+
import java.util.UUID;
1314
import java.util.concurrent.ConcurrentHashMap;
1415
import java.util.concurrent.Executors;
1516
import java.util.concurrent.ScheduledExecutorService;
@@ -25,7 +26,7 @@
2526
*/
2627
public abstract class BaseAudioManager {
2728
protected final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
28-
protected final ConcurrentHashMap<Integer, PlayerAudio> playerAudios = new ConcurrentHashMap<>();
29+
protected final ConcurrentHashMap<UUID, PlayerAudio> playerAudios = new ConcurrentHashMap<>();
2930
protected final int BUFFER_LENGTH = 5;
3031
protected long alCtx, alDevice;
3132

@@ -49,7 +50,7 @@ protected void initAL() {
4950
AL.createCapabilities(ALC.createCapabilities(alDevice));
5051
}
5152

52-
public void handle(int from, int sampleRate, byte[] opus) {
53+
public void handle(UUID from, int sampleRate, byte[] opus) {
5354
try {
5455
var decoded = OpusHelper.decode(opus, sampleRate);
5556
var level = Minecraft.getInstance().level;
@@ -58,7 +59,7 @@ public void handle(int from, int sampleRate, byte[] opus) {
5859
}
5960
var fromEntity = level.getEntity(from);
6061
if (fromEntity instanceof Player player) {
61-
playerAudios.compute(player.getId(), (id, old) -> {
62+
playerAudios.compute(player.getUUID(), (id, old) -> {
6263
if (old == null) {
6364
return new PlayerAudio(id, sampleRate);
6465
} else if (old.sampleRate != sampleRate) {
@@ -97,5 +98,5 @@ protected void playing() {
9798
/**
9899
* @return true, if want to remove player and their audio. Must close audio before return true.
99100
*/
100-
protected abstract boolean play(Level level, int playerId, PlayerAudio audio);
101+
protected abstract boolean play(Level level, UUID playerId, PlayerAudio audio);
101102
}

src/main/java/cn/ussshenzhou/channel/audio/client/receive/PlayerAudio.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.nio.ByteOrder;
77
import java.util.Arrays;
88
import java.util.Objects;
9+
import java.util.UUID;
910
import java.util.concurrent.ArrayBlockingQueue;
1011
import java.util.concurrent.BlockingQueue;
1112

@@ -16,9 +17,10 @@
1617
*/
1718
public class PlayerAudio {
1819
private final BlockingQueue<short[]> audioBuffer = new ArrayBlockingQueue<>(20);
19-
protected final int playerId, alSource, sampleRate;
20+
protected final int alSource, sampleRate;
21+
protected final UUID playerId;
2022

21-
public PlayerAudio(int playerId, int sampleRate) {
23+
public PlayerAudio(UUID playerId, int sampleRate) {
2224
this.playerId = playerId;
2325
this.sampleRate = sampleRate;
2426
this.alSource = alGenSources();

src/main/java/cn/ussshenzhou/channel/audio/client/receive/TalkManager.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package cn.ussshenzhou.channel.audio.client.receive;
22

3+
import cn.ussshenzhou.channel.config.ChannelPlayerConfig;
34
import net.minecraft.client.Minecraft;
5+
import net.minecraft.world.entity.player.Player;
46
import net.minecraft.world.level.Level;
57

68
import java.nio.ByteBuffer;
9+
import java.util.UUID;
710

811
import static org.lwjgl.openal.AL10.*;
912
import static org.lwjgl.openal.AL10.AL_BUFFERS_PROCESSED;
@@ -24,7 +27,7 @@
2427
*/
2528
public class TalkManager extends BaseAudioManager {
2629
@Override
27-
protected boolean play(Level level, int playerId, PlayerAudio audio) {
30+
protected boolean play(Level level, UUID playerId, PlayerAudio audio) {
2831
var player = level.getEntity(playerId);
2932
if (player == null) {
3033
audio.close();
@@ -33,6 +36,9 @@ protected boolean play(Level level, int playerId, PlayerAudio audio) {
3336
var partialTick = Minecraft.getInstance().getDeltaTracker().getGameTimeDeltaPartialTick(false);
3437
var pos = player.getEyePosition(partialTick);
3538
alSource3f(audio.alSource, AL_POSITION, (float) pos.x, (float) pos.y, (float) pos.z);
39+
if (player instanceof Player p) {
40+
alSourcef(audio.alSource, AL_GAIN, ChannelPlayerConfig.getOrDefault(p));
41+
}
3642
int processed = alGetSourcei(audio.alSource, AL_BUFFERS_PROCESSED);
3743
while (processed-- > 0) {
3844
int buf = alSourceUnqueueBuffers(audio.alSource);

src/main/java/cn/ussshenzhou/channel/audio/nativ/NvidiaHelper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public static void refresh() {
5959
return;
6060
}
6161
var effect = dereverb ? NVAFX_EFFECT_DEREVERB_DENOISER : NVAFX_EFFECT_DENOISER;
62+
//TODO
6263
try (Arena arena = Arena.ofConfined()) {
6364
var handle = arena.allocate(ValueLayout.ADDRESS);
6465
checkStatus(NvAFX_CreateEffect(effect, handle), "NvAFX_CreateEffect");

src/main/java/cn/ussshenzhou/channel/audio/server/RelayHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ public static void normalTalking(ServerPlayer from, byte[] opusAudio, int sample
1919
to.position().distanceTo(from.position()) < 24 &&
2020
(!from.isSpectator() || to.isSpectator())
2121
)
22-
.forEach(to -> NetworkHelper.sendToPlayer(to, new TalkPacket2C(sampleRate, from.getId(), opusAudio)));
22+
.forEach(to -> NetworkHelper.sendToPlayer(to, new TalkPacket2C(sampleRate, from.getUUID(), opusAudio)));
2323
}
2424
}

src/main/java/cn/ussshenzhou/channel/config/ChannelClientConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import cn.ussshenzhou.channel.audio.NC;
44
import cn.ussshenzhou.channel.audio.Trigger;
55
import cn.ussshenzhou.channel.audio.Vad;
6+
import cn.ussshenzhou.channel.audio.Unit;
67
import cn.ussshenzhou.t88.config.ConfigHelper;
78
import cn.ussshenzhou.t88.config.TConfig;
89

@@ -31,6 +32,7 @@ public class ChannelClientConfig implements TConfig {
3132
public float targetLevel = -5;
3233
public float maxGain = 20;
3334
public String nvidiaDllPath = "";
35+
public Unit unit = Unit.DB;
3436

3537
public static ChannelClientConfig get() {
3638
return ConfigHelper.getConfigRead(ChannelClientConfig.class);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package cn.ussshenzhou.channel.config;
2+
3+
import cn.ussshenzhou.channel.gui.OutputConfigPanel;
4+
import cn.ussshenzhou.t88.config.ConfigHelper;
5+
import cn.ussshenzhou.t88.config.TConfig;
6+
import net.minecraft.world.entity.player.Player;
7+
8+
import java.util.HashMap;
9+
import java.util.function.Consumer;
10+
11+
/**
12+
* @author USS_Shenzhou
13+
*/
14+
@SuppressWarnings("FieldMayBeFinal")
15+
public class ChannelPlayerConfig implements TConfig {
16+
17+
private HashMap<String, Float> playerVolumeAdjust = new HashMap<>();
18+
19+
public static float getOrDefault(Player player) {
20+
float r = get().playerVolumeAdjust.computeIfAbsent(player.getGameProfile().getName(), name -> 0f);
21+
OutputConfigPanel.PlayerVolumePanel.add(player.getUUID(), r);
22+
return r;
23+
}
24+
25+
public static void set(Player player, float db) {
26+
write(thiz -> thiz.playerVolumeAdjust.put(player.getGameProfile().getName(), db));
27+
}
28+
29+
private static ChannelPlayerConfig get() {
30+
return ConfigHelper.getConfigRead(ChannelPlayerConfig.class);
31+
}
32+
33+
private static void write(Consumer<ChannelPlayerConfig> writer) {
34+
ConfigHelper.getConfigWrite(ChannelPlayerConfig.class, writer);
35+
}
36+
}

src/main/java/cn/ussshenzhou/channel/gui/ConfigScreen.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,37 @@
1111
*/
1212
public class ConfigScreen extends TScreen {
1313
private final TLabel title = new TLabel(Component.translatable("channel.config.title"));
14-
private final TTabPageContainer tabs = new TTabPageContainer();
14+
final TTabPageContainer tabs = new TTabPageContainer();
15+
private TTabPageContainer.Tab input, transmit, output, general;
1516

1617
public ConfigScreen() {
1718
super(Component.literal("Channel Mod Config Screen"));
1819
this.add(title);
1920
title.setFontSize((float) (TLabel.STD_FONT_SIZE * 1.5));
20-
2121
this.add(tabs);
22-
var input = tabs.newTab(Component.translatable("channel.config.tab.input"), new InputConfigPanel());
22+
tInit();
23+
}
24+
25+
public void tInit() {
26+
input = tabs.newTab(Component.translatable("channel.config.tab.input"), new InputConfigPanel());
2327
input.setCloseable(false);
24-
var transmit = tabs.newTab(Component.translatable("channel.config.tab.transmit"), new TransmitConfigPanel());
28+
29+
transmit = tabs.newTab(Component.translatable("channel.config.tab.transmit"), new TransmitConfigPanel());
2530
transmit.setCloseable(false);
26-
var output = tabs.newTab(Component.translatable("channel.config.tab.output"), new OutputConfigPanel());
31+
32+
output = tabs.newTab(Component.translatable("channel.config.tab.output"), new OutputConfigPanel());
2733
output.setCloseable(false);
34+
35+
general = tabs.newTab(Component.translatable("channel.config.tab.general"), new GeneralConfigPanel());
36+
general.setCloseable(false);
37+
}
38+
39+
public void forceUpdate() {
40+
this.tabs.removeTab(input);
41+
this.tabs.removeTab(transmit);
42+
this.tabs.removeTab(output);
43+
this.tabs.removeTab(general);
44+
this.tInit();
2845
}
2946

3047
@Override

0 commit comments

Comments
 (0)