Hraban Luyat <hraban@0brg.net>
Dejian Xu <xudejian2008@gmail.com>
+Tobias Wellnitz <tobias.wellnitz@gmail.com>
opus_encoder_ctl(st, OPUS_GET_SAMPLE_RATE(&sample_rate));
return sample_rate;
}
+
+
+int
+bridge_encoder_set_bitrate(OpusEncoder *st, opus_int32 bitrate)
+{
+ int res;
+ res = opus_encoder_ctl(st, OPUS_SET_BITRATE(bitrate));
+ return res;
+}
+
+int
+bridge_encoder_get_bitrate(OpusEncoder *st, opus_int32 *bitrate)
+{
+ int res;
+ res = opus_encoder_ctl(st, OPUS_GET_BITRATE(bitrate));
+ return res;
+}
+
+int
+bridge_encoder_set_complexity(OpusEncoder *st, opus_int32 complexity)
+{
+ int res;
+ res = opus_encoder_ctl(st, OPUS_SET_COMPLEXITY(complexity));
+ return res;
+}
+
+int
+bridge_encoder_get_complexity(OpusEncoder *st, opus_int32 *complexity)
+{
+ int res;
+ res = opus_encoder_ctl(st, OPUS_GET_COMPLEXITY(complexity));
+ return res;
+}
+
+int
+bridge_encoder_set_max_bandwidth(OpusEncoder *st, opus_int32 max_bw)
+{
+ int res;
+ res = opus_encoder_ctl(st, OPUS_SET_MAX_BANDWIDTH(max_bw));
+ return res;
+}
+
+int
+bridge_encoder_get_max_bandwidth(OpusEncoder *st, opus_int32 *max_bw)
+{
+ int res;
+ res = opus_encoder_ctl(st, OPUS_GET_MAX_BANDWIDTH(max_bw));
+ return res;
+}
+
*/
import "C"
+const (
+ // Auto bitrate
+ Auto = C.OPUS_AUTO
+ // Maximum bitrate
+ BitrateMax = C.OPUS_BITRATE_MAX
+ //4 kHz passband
+ BandwidthNarrowband = C.OPUS_BANDWIDTH_NARROWBAND
+ // 6 kHz passband
+ BandwidthMediumBand = C.OPUS_BANDWIDTH_MEDIUMBAND
+ // 8 kHz passband
+ BandwidthWideBand = C.OPUS_BANDWIDTH_WIDEBAND
+ // 12 kHz passband
+ BandwidthSuperWideBand = C.OPUS_BANDWIDTH_SUPERWIDEBAND
+ // 20 kHz passband
+ BandwidthFullband = C.OPUS_BANDWIDTH_FULLBAND
+)
+
var errEncUninitialized = fmt.Errorf("opus encoder uninitialized")
// Encoder contains the state of an Opus encoder for libopus.
// NewEncoder allocates a new Opus encoder and initializes it with the
// appropriate parameters. All related memory is managed by the Go GC.
-func NewEncoder(sample_rate int, channels int, application Application) (*Encoder, error) {
+func NewEncoder(sample_rate int, channels int, application int) (*Encoder, error) {
var enc Encoder
err := enc.Init(sample_rate, channels, application)
if err != nil {
// Init initializes a pre-allocated opus encoder. Unless the encoder has been
// created using NewEncoder, this method must be called exactly once in the
// life-time of this object, before calling any other methods.
-func (enc *Encoder) Init(sample_rate int, channels int, application Application) error {
+func (enc *Encoder) Init(sample_rate int, channels int, application int) error {
if enc.p != nil {
return fmt.Errorf("opus encoder already initialized")
}
func (enc *Encoder) SampleRate() int {
return int(C.bridge_encoder_get_sample_rate(enc.p))
}
+
+// SetBitrate sets the bitrate of the Encoder
+func (enc *Encoder) SetBitrate(bitrate int) error {
+ res := C.bridge_encoder_set_bitrate(enc.p, C.opus_int32(bitrate))
+ if res != C.OPUS_OK {
+ return Error(res)
+ }
+ return nil
+}
+
+// Bitrate returns the bitrate of the Encoder
+func (enc *Encoder) Bitrate() (int, error) {
+ var bitrate C.opus_int32
+ res := C.bridge_encoder_get_bitrate(enc.p, &bitrate)
+ if res != C.OPUS_OK {
+ return 0, Error(res)
+ }
+ return int(bitrate), nil
+}
+
+// SetComplexity sets the encoder's computational complexity
+func (enc *Encoder) SetComplexity(complexity int) error {
+ res := C.bridge_encoder_set_complexity(enc.p, C.opus_int32(complexity))
+ if res != C.OPUS_OK {
+ return Error(res)
+ }
+ return nil
+}
+
+// Complexity returns the bitrate of the Encoder
+func (enc *Encoder) Complexity() (int, error) {
+ var complexity C.opus_int32
+ res := C.bridge_encoder_get_complexity(enc.p, &complexity)
+ if res != C.OPUS_OK {
+ return 0, Error(res)
+ }
+ return int(complexity), nil
+}
+
+// SetMaxBandwidth configures the maximum bandpass that the encoder will select
+// automatically
+func (enc *Encoder) SetMaxBandwidth(maxBw int) error {
+ res := C.bridge_encoder_set_max_bandwidth(enc.p, C.opus_int32(maxBw))
+ if res != C.OPUS_OK {
+ return Error(res)
+ }
+ return nil
+}
+
+// MaxBandwidth gets the encoder's configured maximum allowed bandpass.
+func (enc *Encoder) MaxBandwidth() (int, error) {
+ var maxBw C.opus_int32
+ res := C.bridge_encoder_get_max_bandwidth(enc.p, &maxBw)
+ if res != C.OPUS_OK {
+ return 0, Error(res)
+ }
+ return int(maxBw), nil
+}
}
}
}
+
+func TestEncoder_SetGetBitrate(t *testing.T) {
+ enc, err := NewEncoder(8000, 1, AppVoIP)
+ if err != nil || enc == nil {
+ t.Errorf("Error creating new encoder: %v", err)
+ }
+ vals := []int{500, 100000, 300000}
+ for _, bitrate := range vals {
+ err := enc.SetBitrate(bitrate)
+ if err != nil {
+ t.Error("Error set bitrate:", err)
+ }
+ br, err := enc.Bitrate()
+ if err != nil {
+ t.Error("Error getting bitrate", err)
+ }
+ if br != bitrate {
+ t.Errorf("Unexpected bitrate. Got %d, but expected %d", br, bitrate)
+ }
+ }
+}
+
+func TestEncoder_SetGetInvalidBitrate(t *testing.T) {
+ enc, err := NewEncoder(8000, 1, AppVoIP)
+ if err != nil || enc == nil {
+ t.Errorf("Error creating new encoder: %v", err)
+ }
+ invalidVals := []int{-20, 0}
+ for _, bitrate := range invalidVals {
+ err := enc.SetBitrate(bitrate)
+ if err == nil {
+ t.Errorf("Expected Error invalid bitrate: %d", bitrate)
+ }
+ br, err := enc.Bitrate()
+ if err != nil {
+ t.Error("Error getting bitrate", err)
+ }
+ // default bitrate is 32 kbit/s
+ if br != 32000 {
+ t.Errorf("Unexpected bitrate. Got %d, but expected %d", br, bitrate)
+ }
+ }
+}
+
+func TestEncoder_SetGetComplexity(t *testing.T) {
+ enc, err := NewEncoder(8000, 1, AppVoIP)
+ if err != nil || enc == nil {
+ t.Errorf("Error creating new encoder: %v", err)
+ }
+ vals := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
+ for _, complexity := range vals {
+ err := enc.SetComplexity(complexity)
+ if err != nil {
+ t.Error("Error setting complexity value:", err)
+ }
+ cpx, err := enc.Complexity()
+ if err != nil {
+ t.Error("Error getting complexity value", err)
+ }
+ if cpx != complexity {
+ t.Errorf("Unexpected encoder complexity value. Got %d, but expected %d",
+ cpx, complexity)
+ }
+ }
+}
+
+func TestEncoder_SetGetInvalidComplexity(t *testing.T) {
+ enc, err := NewEncoder(8000, 1, AppVoIP)
+ if err != nil || enc == nil {
+ t.Errorf("Error creating new encoder: %v", err)
+ }
+ invalidVals := []int{-20, 11, 1000}
+ for _, complexity := range invalidVals {
+ err := enc.SetComplexity(complexity)
+ if err == nil {
+ t.Errorf("Expected Error invalid complexity value: %d", complexity)
+ }
+ cpx, err := enc.Complexity()
+ if err != nil {
+ t.Error("Error getting complexity value", err)
+ }
+ // default complexity value is 9
+ if cpx != 9 {
+ t.Errorf("Unexpected complexity value. Got %d, but expected %d",
+ cpx, complexity)
+ }
+ }
+}
+
+func TestEncoder_SetGetMaxBandwidth(t *testing.T) {
+ enc, err := NewEncoder(8000, 1, AppVoIP)
+ if err != nil || enc == nil {
+ t.Errorf("Error creating new encoder: %v", err)
+ }
+ vals := []int{BandwidthNarrowband,
+ BandwidthMediumBand,
+ BandwidthWideBand,
+ BandwidthSuperWideBand,
+ BandwidthFullband,
+ }
+ for _, maxBw := range vals {
+ err := enc.SetMaxBandwidth(maxBw)
+ if err != nil {
+ t.Error("Error setting max Bandwidth:", err)
+ }
+ maxBwRead, err := enc.MaxBandwidth()
+ if err != nil {
+ t.Error("Error getting max Bandwidth", err)
+ }
+ if maxBwRead != maxBw {
+ t.Errorf("Unexpected max Bandwidth value. Got %d, but expected %d",
+ maxBwRead, maxBw)
+ }
+ }
+}
type Application int
-// These variables should be constants, but for interoperability with CGO
-// they're var. Don't change them, though!
-var (
+const (
// Optimize encoding for VoIP
- AppVoIP = Application(C.CONST_APPLICATION_VOIP)
+ AppVoIP = C.OPUS_APPLICATION_VOIP
// Optimize encoding for non-voice signals like music
- AppAudio = Application(C.CONST_APPLICATION_AUDIO)
+ AppAudio = C.OPUS_APPLICATION_AUDIO
// Optimize encoding for low latency applications
- AppRestrictedLowdelay = Application(C.CONST_APPLICATION_RESTRICTED_LOWDELAY)
+ AppRestrictedLowdelay = C.OPUS_APPLICATION_RESTRICTED_LOWDELAY
)
// DEPRECATED -- Don't use these. Will be removed end of 2017.