]> Sergey Matveev's repositories - go-opus.git/commitdiff
added new encoder methods & tests
authordh1tw <tobias@dh1tw.de>
Fri, 30 Dec 2016 14:57:37 +0000 (15:57 +0100)
committerdh1tw <tobias@dh1tw.de>
Fri, 30 Dec 2016 14:57:37 +0000 (15:57 +0100)
AUTHORS
encoder.go
encoder_test.go
opus.go

diff --git a/AUTHORS b/AUTHORS
index 850bdfd5ce52f89e317838316abdabacf254e89b..4a6576485c7476f01340c663451c6bf1d76efed7 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,2 +1,3 @@
 Hraban Luyat <hraban@0brg.net>
 Dejian Xu <xudejian2008@gmail.com>
+Tobias Wellnitz <tobias.wellnitz@gmail.com>
index 683ce589eaf6f8d4fedc264e58b7ff08666309ab..3e079309a07f456871dbc8541253c82834e7939c 100644 (file)
@@ -34,9 +34,76 @@ bridge_encoder_get_sample_rate(OpusEncoder *st)
        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.
@@ -50,7 +117,7 @@ type Encoder struct {
 
 // 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 {
@@ -62,7 +129,7 @@ func NewEncoder(sample_rate int, channels int, application Application) (*Encode
 // 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")
        }
@@ -162,3 +229,61 @@ func (enc *Encoder) DTX() bool {
 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
+}
index 15d640c1d529cb12991110f948623f024cbb2c1c..439179141b7528861a4ec293e3a35698dce1557c 100644 (file)
@@ -57,3 +57,118 @@ func TestEncoderSampleRate(t *testing.T) {
                }
        }
 }
+
+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)
+               }
+       }
+}
diff --git a/opus.go b/opus.go
index 9040d7725a423e1517ebf66fc90fa8a01258748e..c0ea7d3f7e5b4908388502fe1247a164cc051e2a 100644 (file)
--- a/opus.go
+++ b/opus.go
@@ -18,15 +18,13 @@ import "C"
 
 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.