1717package net .dv8tion .jda .internal .audio ;
1818
1919import com .neovisionaries .ws .client .WebSocket ;
20- import com .sun .jna .ptr .PointerByReference ;
2120import gnu .trove .map .TIntLongMap ;
2221import gnu .trove .map .TIntObjectMap ;
2322import gnu .trove .map .hash .TIntLongHashMap ;
3736import net .dv8tion .jda .internal .managers .AudioManagerImpl ;
3837import net .dv8tion .jda .internal .utils .JDALogger ;
3938import org .slf4j .Logger ;
40- import tomp2p .opuswrapper .Opus ;
4139
4240import javax .annotation .Nonnull ;
4341import java .net .*;
4442import java .nio .Buffer ;
4543import java .nio .ByteBuffer ;
46- import java .nio .IntBuffer ;
47- import java .nio .ShortBuffer ;
4844import java .util .*;
4945import java .util .concurrent .ConcurrentLinkedQueue ;
5046import java .util .concurrent .Executors ;
@@ -65,8 +61,9 @@ public class AudioConnection
6561
6662 protected volatile DatagramSocket udpSocket ;
6763
64+ private final OpusCodecFactory codecFactory = OpusCodecFactoryProvider .getInstance ();
6865 private final TIntLongMap ssrcMap = new TIntLongHashMap ();
69- private final TIntObjectMap <Decoder > opusDecoders = new TIntObjectHashMap <>();
66+ private final TIntObjectMap <OpusDecoder > opusDecoders = new TIntObjectHashMap <>();
7067 private final HashMap <User , Queue <AudioData >> combinedQueue = new HashMap <>();
7168 private final String threadIdentifier ;
7269 private final AudioWebSocket webSocket ;
@@ -76,7 +73,7 @@ public class AudioConnection
7673 protected final Condition readyCondvar = readyLock .newCondition ();
7774
7875 private AudioChannel channel ;
79- private PointerByReference opusEncoder ;
76+ private OpusEncoder opusEncoder ;
8077 private ScheduledExecutorService combinedAudioExecutor ;
8178 private IAudioSendSystem sendSystem ;
8279 private Thread receiveThread ;
@@ -188,11 +185,11 @@ public synchronized void shutdown()
188185 }
189186 if (opusEncoder != null )
190187 {
191- Opus . INSTANCE . opus_encoder_destroy ( opusEncoder );
188+ opusEncoder . close ( );
192189 opusEncoder = null ;
193190 }
194191
195- opusDecoders .valueCollection ().forEach (Decoder ::close );
192+ opusDecoders .valueCollection ().forEach (OpusDecoder ::close );
196193 opusDecoders .clear ();
197194
198195 MiscUtil .locked (readyLock , readyCondvar ::signalAll );
@@ -266,7 +263,7 @@ protected void removeUserSSRC(long userId)
266263 });
267264 if (!modified )
268265 return ;
269- final Decoder decoder = opusDecoders .remove (ssrcRef .get ());
266+ final OpusDecoder decoder = opusDecoders .remove (ssrcRef .get ());
270267 if (decoder != null ) // cleanup decoder
271268 decoder .close ();
272269 }
@@ -290,7 +287,7 @@ protected void updateUserSSRC(int ssrc, long userId)
290287
291288 //Only create a decoder if we are actively handling received audio.
292289 if (receiveThread != null && AudioNatives .ensureOpus ())
293- opusDecoders .put (ssrc , new Decoder (ssrc ));
290+ opusDecoders .put (ssrc , codecFactory . createDecoder (ssrc ));
294291 }
295292 }
296293
@@ -313,7 +310,7 @@ else if (sendHandler == null && sendSystem != null)
313310
314311 if (opusEncoder != null )
315312 {
316- Opus . INSTANCE . opus_encoder_destroy ( opusEncoder );
313+ opusEncoder . close ( );
317314 opusEncoder = null ;
318315 }
319316 }
@@ -336,7 +333,7 @@ else if (receiveHandler == null && receiveThread != null)
336333 combinedAudioExecutor = null ;
337334 }
338335
339- opusDecoders .valueCollection ().forEach (Decoder ::close );
336+ opusDecoders .valueCollection ().forEach (OpusDecoder ::close );
340337 opusDecoders .clear ();
341338 }
342339 else if (receiveHandler != null && !receiveHandler .canReceiveCombined () && combinedAudioExecutor != null )
@@ -379,7 +376,7 @@ private synchronized void setupReceiveThread()
379376
380377 int ssrc = decryptedPacket .getSSRC ();
381378 final long userId = ssrcMap .get (ssrc );
382- Decoder decoder = opusDecoders .get (ssrc );
379+ OpusDecoder decoder = opusDecoders .get (ssrc );
383380 if (userId == ssrcMap .getNoEntryValue ())
384381 {
385382 ByteBuffer audio = decryptedPacket .getEncodedAudio ();
@@ -395,7 +392,7 @@ private synchronized void setupReceiveThread()
395392 {
396393 if (AudioNatives .ensureOpus ())
397394 {
398- opusDecoders .put (ssrc , decoder = new Decoder (ssrc ));
395+ opusDecoders .put (ssrc , decoder = codecFactory . createDecoder (ssrc ));
399396 }
400397 else if (!receiveHandler .canReceiveEncoded ())
401398 {
@@ -565,33 +562,6 @@ else if (sample < Short.MIN_VALUE)
565562 }
566563 }
567564
568- private ByteBuffer encodeToOpus (ByteBuffer rawAudio )
569- {
570- ShortBuffer nonEncodedBuffer = ShortBuffer .allocate (rawAudio .remaining () / 2 );
571- ByteBuffer encoded = ByteBuffer .allocate (4096 );
572- for (int i = rawAudio .position (); i < rawAudio .limit (); i += 2 )
573- {
574- int firstByte = (0x000000FF & rawAudio .get (i )); //Promotes to int and handles the fact that it was unsigned.
575- int secondByte = (0x000000FF & rawAudio .get (i + 1 ));
576-
577- //Combines the 2 bytes into a short. Opus deals with unsigned shorts, not bytes.
578- short toShort = (short ) ((firstByte << 8 ) | secondByte );
579-
580- nonEncodedBuffer .put (toShort );
581- }
582- ((Buffer ) nonEncodedBuffer ).flip ();
583-
584- int result = Opus .INSTANCE .opus_encode (opusEncoder , nonEncodedBuffer , OpusPacket .OPUS_FRAME_SIZE , encoded , encoded .capacity ());
585- if (result <= 0 )
586- {
587- LOG .error ("Received error code from opus_encode(...): {}" , result );
588- return null ;
589- }
590-
591- ((Buffer ) encoded ).position (0 ).limit (result );
592- return encoded ;
593- }
594-
595565 private void setSpeaking (int raw )
596566 {
597567 DataObject obj = DataObject .empty ()
@@ -706,15 +676,13 @@ private ByteBuffer encodeAudio(ByteBuffer rawAudio)
706676 printedError = true ;
707677 return null ;
708678 }
709- IntBuffer error = IntBuffer .allocate (1 );
710- opusEncoder = Opus .INSTANCE .opus_encoder_create (OpusPacket .OPUS_SAMPLE_RATE , OpusPacket .OPUS_CHANNEL_COUNT , Opus .OPUS_APPLICATION_AUDIO , error );
711- if (error .get () != Opus .OPUS_OK && opusEncoder == null )
679+ opusEncoder = codecFactory .createEncoder ();
680+ if (opusEncoder == null )
712681 {
713- LOG .error ("Received error status from opus_encoder_create(...): {}" , error .get ());
714682 return null ;
715683 }
716684 }
717- return encodeToOpus (rawAudio );
685+ return opusEncoder . encode (rawAudio );
718686 }
719687
720688 private DatagramPacket getDatagramPacket (ByteBuffer b )
0 commit comments