11package cn .ussshenzhou .channel .audio .client .receive ;
22
33import cn .ussshenzhou .channel .audio .client .rt .RayTraceManager ;
4+ import cn .ussshenzhou .channel .audio .client .rt .SourceAudioData ;
45import cn .ussshenzhou .channel .config .ChannelClientConfig ;
5- import cn .ussshenzhou .channel .config .ChannelPlayerConfig ;
6- import cn .ussshenzhou .channel .gui .OutputConfigPanel ;
76import cn .ussshenzhou .channel .util .AudioHelper ;
8- import com .mojang .logging .LogUtils ;
97import io .netty .util .internal .shaded .org .jctools .queues .MpscArrayQueue ;
10- import net .minecraft .client .Minecraft ;
11- import net .minecraft .world .entity .player .Player ;
128import net .minecraft .world .level .Level ;
139import net .minecraft .world .phys .Vec3 ;
1410
1511import javax .annotation .Nullable ;
1612import java .nio .ByteBuffer ;
17- import java .nio .ByteOrder ;
18- import java .util .*;
19-
20- import static org .lwjgl .openal .AL11 .*;
13+ import java .util .List ;
14+
15+ import static org .lwjgl .openal .AL10 .*;
16+ import static org .lwjgl .openal .AL10 .AL_FALSE ;
17+ import static org .lwjgl .openal .AL10 .AL_LOOPING ;
18+ import static org .lwjgl .openal .AL10 .AL_MAX_GAIN ;
19+ import static org .lwjgl .openal .AL10 .AL_PITCH ;
20+ import static org .lwjgl .openal .AL10 .AL_REFERENCE_DISTANCE ;
21+ import static org .lwjgl .openal .AL10 .AL_ROLLOFF_FACTOR ;
22+ import static org .lwjgl .openal .AL10 .alSourcef ;
23+ import static org .lwjgl .openal .AL10 .alSourcei ;
24+ import static org .lwjgl .openal .AL11 .alSource3i ;
2125import static org .lwjgl .openal .EXTEfx .*;
26+ import static org .lwjgl .openal .EXTEfx .AL_AUXILIARY_SEND_FILTER ;
27+
28+ public abstract class Audio {
29+ protected static final int MAX_BUFFER_10MS = 3 * 100 ;
30+ protected int readyBufferMs = 0 ;
31+ protected final int alSource , sampleRate , alDirectFilter , alReverbFilter ;
32+ protected double x , y , z ;
2233
23- /**
24- * @author USS_Shenzhou
25- */
26- public class PlayerAudio {
27- private static final int MAX_BUFFER_10MS = 3 * 100 ;
28- private final MpscArrayQueue <short []> audioBuffer = new MpscArrayQueue <>((int ) (1.1 * MAX_BUFFER_10MS ));
29- private int readyBufferMs = 0 ;
30- public final int alSource , sampleRate , alDirectFilter , alReverbFilter ;
31- public final UUID playerId ;
32- private double x , y , z ;
33-
34- public PlayerAudio (UUID playerId , int sampleRate ) {
35- this .playerId = playerId ;
34+ public Audio (int sampleRate ) {
3635 this .sampleRate = sampleRate ;
3736 this .alSource = alGenSources ();
3837 alSourcef (alSource , AL_GAIN , 1 );
@@ -56,57 +55,29 @@ public PlayerAudio(UUID playerId, int sampleRate) {
5655 }
5756 }
5857
59- public void push (short [] audio ) {
60- int length = sampleRate / 100 ;
61- for (int i = 0 ; i < audio .length / length ; i ++) {
62- audioBuffer .offer (Arrays .copyOfRange (audio , i * length , (i + 1 ) * length ));
63- }
64- }
58+ public void updateSourceParameters (SourceAudioData data , int auxSlot ) {
59+ alFilterf (this .alDirectFilter , AL_LOWPASS_GAIN , data .directGain ());
60+ alFilterf (this .alDirectFilter , AL_LOWPASS_GAINHF , data .directHF ());
61+ alSourcei (this .alSource , AL_DIRECT_FILTER , this .alDirectFilter );
6562
66- @ Nullable
67- public List <ByteBuffer > read (int sizeIn10Ms ) {
68- if (audioBuffer .isEmpty ()) {
69- return null ;
70- }
71- checkTooMuchDelay ();
72- int toRead = Math .min (sizeIn10Ms , audioBuffer .size ());
73- int length = sampleRate / 100 ;
74- List <ByteBuffer > buffers = new ArrayList <>(toRead );
75- for (int i = 0 ; i < toRead ; i ++) {
76- var chunk = audioBuffer .poll ();
77- if (chunk != null ) {
78- var buffer = ByteBuffer .allocateDirect (length * 2 ).order (ByteOrder .LITTLE_ENDIAN );
79- buffer .asShortBuffer ().put (chunk ).rewind ();
80- buffers .add (buffer );
81- }
82- }
83- return buffers ;
84- }
63+ alFilterf (this .alReverbFilter , AL_LOWPASS_GAIN , data .reverbGain ());
64+ alFilterf (this .alReverbFilter , AL_LOWPASS_GAINHF , 1 );
65+ alSource3i (this .alSource , AL_AUXILIARY_SEND_FILTER , auxSlot , 0 , this .alReverbFilter );
8566
86- public void checkTooMuchDelay () {
87- if (audioBuffer .size () >= ChannelClientConfig .get ().networkTolerance * 1.5 / 10 || audioBuffer .size () >= MAX_BUFFER_10MS ) {
88- int targetBufferSize = (int ) (ChannelClientConfig .get ().networkTolerance * 1.1 / 10 );
89- int drop = audioBuffer .size () - targetBufferSize ;
90- for (int i = 0 ; i < drop ; i ++) {
91- audioBuffer .poll ();
92- }
93- }
67+ alSource3f (this .alSource , AL_POSITION , (float ) data .virtualPos ().x , (float ) data .virtualPos ().y , (float ) data .virtualPos ().z );
9468 }
9569
96- public void play () {
70+ public boolean play () {
9771 //TODO close self by last active time
98- var vol = ChannelPlayerConfig .getOrDefault (playerId );
99- alSourcef (alSource , AL_GAIN , AudioHelper .db2factor (vol ));
100- OutputConfigPanel .PlayerVolumePanel .update (playerId , vol );
101-
72+ //TODO use low-pass filter to make underwater effect in 26.2
73+ alSourcef (alSource , AL_GAIN , getGain ());
10274 int processed = alGetSourcei (alSource , AL_BUFFERS_PROCESSED );
10375 while (processed -- > 0 ) {
10476 int buf = alSourceUnqueueBuffers (alSource );
10577 readyBufferMs -= 10 ;
10678 alDeleteBuffers (buf );
10779 }
10880 var pcms = read (MAX_BUFFER_10MS );
109- //TODO use low-pass filter to make underwater effect in 26.2
11081 if (pcms != null ) {
11182 for (ByteBuffer pcm : pcms ) {
11283 int buf = alGenBuffers ();
@@ -123,6 +94,22 @@ public void play() {
12394 alSourcePlay (alSource );
12495 }
12596 }
97+ return false ;
98+ }
99+
100+ protected abstract float getGain ();
101+
102+ @ Nullable
103+ public abstract List <ByteBuffer > read (int sizeIn10Ms );
104+
105+ protected static void checkTooMuchDelay (MpscArrayQueue <short []> buffer ) {
106+ if (buffer .size () >= ChannelClientConfig .get ().networkTolerance * 1.5 / 10 || buffer .size () >= MAX_BUFFER_10MS ) {
107+ int targetBufferSize = (int ) (ChannelClientConfig .get ().networkTolerance * 1.1 / 10 );
108+ int drop = buffer .size () - targetBufferSize ;
109+ for (int i = 0 ; i < drop ; i ++) {
110+ buffer .poll ();
111+ }
112+ }
126113 }
127114
128115 public void close () {
@@ -137,11 +124,7 @@ public void close() {
137124 }
138125
139126 public Vec3 getPos (Level level ) {
140- var player = level .getPlayerByUUID (this .playerId );
141- if (player == null ) {
142- return new Vec3 (x , y , z );
143- }
144- return player .getEyePosition ();
127+ return new Vec3 (x , y , z );
145128 }
146129
147130 public void setPos (double x , double y , double z ) {
@@ -151,15 +134,8 @@ public void setPos(double x, double y, double z) {
151134 }
152135
153136 @ Override
154- public boolean equals (Object other ) {
155- if (!(other instanceof PlayerAudio that )) {
156- return false ;
157- }
158- return playerId == that .playerId ;
159- }
137+ public abstract int hashCode ();
160138
161139 @ Override
162- public int hashCode () {
163- return Objects .hashCode (playerId );
164- }
140+ public abstract boolean equals (Object obj );
165141}
0 commit comments