Share libopus' encoder controls between bindings
libopus' constants and the encoder settings built on opus_encoder_ctl (clamping, voice/music signal) move into core, so the Android binding reuses them rather than copying them from the desktop's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
package com.ts3client.audio.opus;
|
||||||
|
|
||||||
|
/** An {@link OpusEncoder} configured through libopus' own controls; a binding supplies {@link #ctl}. */
|
||||||
|
public abstract class CtlOpusEncoder implements OpusEncoder {
|
||||||
|
|
||||||
|
/** Calls {@code opus_encoder_ctl(encoder, request, value)}. */
|
||||||
|
protected abstract void ctl(int request, int value);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBitrate(int bitsPerSecond) {
|
||||||
|
ctl(LibOpus.SET_BITRATE_REQUEST, bitsPerSecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setComplexity(int complexity) {
|
||||||
|
ctl(LibOpus.SET_COMPLEXITY_REQUEST, Math.max(0, Math.min(10, complexity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVbr(boolean vbr) {
|
||||||
|
ctl(LibOpus.SET_VBR_REQUEST, vbr ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setInbandFec(boolean fec) {
|
||||||
|
ctl(LibOpus.SET_INBAND_FEC_REQUEST, fec ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setExpectedPacketLoss(int percent) {
|
||||||
|
ctl(LibOpus.SET_PACKET_LOSS_PERC_REQUEST, Math.max(0, Math.min(100, percent)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSignal(Signal signal) {
|
||||||
|
ctl(LibOpus.SET_SIGNAL_REQUEST, signal == Signal.MUSIC ? LibOpus.SIGNAL_MUSIC : LibOpus.SIGNAL_VOICE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.ts3client.audio.opus;
|
||||||
|
|
||||||
|
/** libopus' numeric constants (opus_defines.h), shared by every binding of it. */
|
||||||
|
public final class LibOpus {
|
||||||
|
|
||||||
|
public static final int APPLICATION_VOIP = 2048;
|
||||||
|
public static final int APPLICATION_AUDIO = 2049;
|
||||||
|
|
||||||
|
public static final int SET_BITRATE_REQUEST = 4002;
|
||||||
|
public static final int SET_VBR_REQUEST = 4006;
|
||||||
|
public static final int SET_COMPLEXITY_REQUEST = 4010;
|
||||||
|
public static final int SET_INBAND_FEC_REQUEST = 4012;
|
||||||
|
public static final int SET_PACKET_LOSS_PERC_REQUEST = 4014;
|
||||||
|
public static final int SET_SIGNAL_REQUEST = 4024;
|
||||||
|
public static final int RESET_STATE = 4028;
|
||||||
|
|
||||||
|
public static final int SIGNAL_VOICE = 3001;
|
||||||
|
public static final int SIGNAL_MUSIC = 3002;
|
||||||
|
|
||||||
|
private LibOpus() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int application(OpusCodec.Application application) {
|
||||||
|
return application == OpusCodec.Application.AUDIO ? APPLICATION_AUDIO : APPLICATION_VOIP;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.ts3client.audio.desktop;
|
package com.ts3client.audio.desktop;
|
||||||
|
|
||||||
|
import com.ts3client.audio.opus.LibOpus;
|
||||||
import com.ts3client.audio.opus.OpusCodec;
|
import com.ts3client.audio.opus.OpusCodec;
|
||||||
import com.ts3client.audio.opus.OpusDecoder;
|
import com.ts3client.audio.opus.OpusDecoder;
|
||||||
import com.ts3client.audio.opus.OpusEncoder;
|
import com.ts3client.audio.opus.OpusEncoder;
|
||||||
@@ -9,8 +10,7 @@ public final class NativeOpusCodec implements OpusCodec {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpusEncoder createEncoder(int sampleRate, int frameSize, int channels, Application application) {
|
public OpusEncoder createEncoder(int sampleRate, int frameSize, int channels, Application application) {
|
||||||
int app = application == Application.AUDIO ? Opus.OPUS_APPLICATION_AUDIO : Opus.OPUS_APPLICATION_VOIP;
|
return new NativeOpusEncoder(sampleRate, frameSize, channels, LibOpus.application(application));
|
||||||
return new NativeOpusEncoder(sampleRate, frameSize, channels, app);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.ts3client.audio.desktop;
|
package com.ts3client.audio.desktop;
|
||||||
|
|
||||||
|
import com.ts3client.audio.opus.LibOpus;
|
||||||
import com.ts3client.audio.opus.OpusDecoder;
|
import com.ts3client.audio.opus.OpusDecoder;
|
||||||
|
|
||||||
import java.lang.foreign.Arena;
|
import java.lang.foreign.Arena;
|
||||||
@@ -74,7 +75,7 @@ final class NativeOpusDecoder implements OpusDecoder {
|
|||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
if (closed) return;
|
if (closed) return;
|
||||||
Opus.decoderCtl(handle, Opus.OPUS_RESET_STATE, 0);
|
Opus.decoderCtl(handle, LibOpus.RESET_STATE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.ts3client.audio.desktop;
|
package com.ts3client.audio.desktop;
|
||||||
|
|
||||||
import com.ts3client.audio.opus.OpusEncoder;
|
import com.ts3client.audio.opus.CtlOpusEncoder;
|
||||||
|
|
||||||
import java.lang.foreign.Arena;
|
import java.lang.foreign.Arena;
|
||||||
import java.lang.foreign.MemorySegment;
|
import java.lang.foreign.MemorySegment;
|
||||||
@@ -16,7 +16,7 @@ import java.lang.foreign.ValueLayout;
|
|||||||
* are freed by {@link #close()}; access is serialised by the instance lock, so the
|
* are freed by {@link #close()}; access is serialised by the instance lock, so the
|
||||||
* encoder may be driven from any thread.
|
* encoder may be driven from any thread.
|
||||||
*/
|
*/
|
||||||
final class NativeOpusEncoder implements OpusEncoder {
|
final class NativeOpusEncoder extends CtlOpusEncoder {
|
||||||
|
|
||||||
private static final int MAX_PACKET_BYTES = 4096;
|
private static final int MAX_PACKET_BYTES = 4096;
|
||||||
|
|
||||||
@@ -47,36 +47,7 @@ final class NativeOpusEncoder implements OpusEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBitrate(int bitsPerSecond) {
|
protected void ctl(int request, int value) {
|
||||||
ctl(Opus.OPUS_SET_BITRATE_REQUEST, bitsPerSecond);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setComplexity(int complexity) {
|
|
||||||
ctl(Opus.OPUS_SET_COMPLEXITY_REQUEST, Math.max(0, Math.min(10, complexity)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setVbr(boolean vbr) {
|
|
||||||
ctl(Opus.OPUS_SET_VBR_REQUEST, vbr ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setInbandFec(boolean fec) {
|
|
||||||
ctl(Opus.OPUS_SET_INBAND_FEC_REQUEST, fec ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setExpectedPacketLoss(int percent) {
|
|
||||||
ctl(Opus.OPUS_SET_PACKET_LOSS_PERC_REQUEST, Math.max(0, Math.min(100, percent)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSignal(Signal signal) {
|
|
||||||
ctl(Opus.OPUS_SET_SIGNAL_REQUEST, signal == Signal.MUSIC ? Opus.OPUS_SIGNAL_MUSIC : Opus.OPUS_SIGNAL_VOICE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ctl(int request, int value) {
|
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (closed) return;
|
if (closed) return;
|
||||||
int r = Opus.encoderCtl(handle, request, value);
|
int r = Opus.encoderCtl(handle, request, value);
|
||||||
|
|||||||
@@ -30,25 +30,6 @@ public final class Opus {
|
|||||||
private Opus() {
|
private Opus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- application types (opus_defines.h) ----
|
|
||||||
public static final int OPUS_APPLICATION_VOIP = 2048;
|
|
||||||
public static final int OPUS_APPLICATION_AUDIO = 2049;
|
|
||||||
public static final int OPUS_APPLICATION_RESTRICTED_LOWDELAY = 2051;
|
|
||||||
|
|
||||||
// ---- CTL request codes ----
|
|
||||||
public static final int OPUS_SET_BITRATE_REQUEST = 4002;
|
|
||||||
public static final int OPUS_SET_VBR_REQUEST = 4006;
|
|
||||||
public static final int OPUS_SET_COMPLEXITY_REQUEST = 4010;
|
|
||||||
public static final int OPUS_SET_INBAND_FEC_REQUEST = 4012;
|
|
||||||
public static final int OPUS_SET_PACKET_LOSS_PERC_REQUEST = 4014;
|
|
||||||
public static final int OPUS_SET_SIGNAL_REQUEST = 4024;
|
|
||||||
public static final int OPUS_RESET_STATE = 4028;
|
|
||||||
|
|
||||||
// ---- signal hints ----
|
|
||||||
public static final int OPUS_AUTO = -1000;
|
|
||||||
public static final int OPUS_SIGNAL_VOICE = 3001;
|
|
||||||
public static final int OPUS_SIGNAL_MUSIC = 3002;
|
|
||||||
|
|
||||||
private static final ValueLayout.OfInt INT = ValueLayout.JAVA_INT;
|
private static final ValueLayout.OfInt INT = ValueLayout.JAVA_INT;
|
||||||
private static final java.lang.foreign.AddressLayout PTR = ValueLayout.ADDRESS;
|
private static final java.lang.foreign.AddressLayout PTR = ValueLayout.ADDRESS;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user