Conceal a lost voice packet with 20 ms, not 120 ms
A lost packet was concealed by decoding "nothing" into a buffer sized for the longest Opus frame, and Opus fills whatever it is given: every lost packet played 120 ms of made-up audio in place of 20 ms, piling up delay on that speaker's line. Decoders now conceal through their own call that takes the length to make up, and the stream asks for the length of the last packet it got. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -43,29 +43,27 @@ final class NativeOpusDecoder implements OpusDecoder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes an Opus packet to interleaved float PCM.
|
||||
*
|
||||
* @param packet the encoded packet, or {@code null} to request packet-loss
|
||||
* concealment (PLC) for a missing frame
|
||||
* @param packet an Opus packet, at most {@value #MAX_PACKET_BYTES} bytes
|
||||
* @param out output buffer, at least {@code frameSize * channels} long
|
||||
* @return number of samples decoded per channel
|
||||
*/
|
||||
@Override
|
||||
public int decode(byte[] packet, float[] out) {
|
||||
if (closed) throw new IllegalStateException("decoder closed");
|
||||
|
||||
MemorySegment data = MemorySegment.NULL;
|
||||
int len = 0;
|
||||
if (packet != null) {
|
||||
if (packet.length > MAX_PACKET_BYTES) {
|
||||
throw new IllegalArgumentException("packet too large: " + packet.length);
|
||||
}
|
||||
MemorySegment.copy(packet, 0, packetBuffer, ValueLayout.JAVA_BYTE, 0, packet.length);
|
||||
data = packetBuffer;
|
||||
len = packet.length;
|
||||
if (packet.length > MAX_PACKET_BYTES) {
|
||||
throw new IllegalArgumentException("packet too large: " + packet.length);
|
||||
}
|
||||
MemorySegment.copy(packet, 0, packetBuffer, ValueLayout.JAVA_BYTE, 0, packet.length);
|
||||
return decode(packetBuffer, packet.length, out, frameSize);
|
||||
}
|
||||
|
||||
int samples = Opus.decodeFloat(handle, data, len, pcmBuffer, frameSize, 0);
|
||||
@Override
|
||||
public int conceal(float[] out, int frameSize) {
|
||||
return decode(MemorySegment.NULL, 0, out, Math.min(frameSize, this.frameSize));
|
||||
}
|
||||
|
||||
private int decode(MemorySegment data, int len, float[] out, int maxSamples) {
|
||||
if (closed) throw new IllegalStateException("decoder closed");
|
||||
int samples = Opus.decodeFloat(handle, data, len, pcmBuffer, maxSamples, 0);
|
||||
if (samples < 0) {
|
||||
throw new IllegalStateException("opus_decode_float failed: " + Opus.strerror(samples));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user