Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added 3 more setter / getter for Encoder Settings #8

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 110 additions & 2 deletions encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,56 @@ bridge_encoder_get_sample_rate(OpusEncoder *st)
opus_encoder_ctl(st, OPUS_GET_SAMPLE_RATE(&sample_rate));
return sample_rate;
}

opus_int32
set_bitrate(OpusEncoder *st, opus_int32 bitrate)
{
opus_int32 res;
res = opus_encoder_ctl(st, OPUS_SET_BITRATE(bitrate));
return res;
}

opus_int32
get_bitrate(OpusEncoder *st, opus_int32 *bitrate)
{
int res;
res = opus_encoder_ctl(st, OPUS_GET_BITRATE(bitrate));
return res;
}

opus_int32
set_complexity(OpusEncoder *st, opus_int32 complexity)
{
opus_int32 res;
res = opus_encoder_ctl(st, OPUS_SET_COMPLEXITY(complexity));
return res;
}

opus_int32
get_complexity(OpusEncoder *st, opus_int32 *complexity)
{
int res;
res = opus_encoder_ctl(st, OPUS_GET_COMPLEXITY(complexity));
return res;
}

opus_int32
set_max_bandwidth(OpusEncoder *st, opus_int32 max_bw)
{
opus_int32 res;
res = opus_encoder_ctl(st, OPUS_SET_MAX_BANDWIDTH(max_bw));
return res;
}

opus_int32
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"

Expand All @@ -50,7 +100,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 {
Expand All @@ -62,7 +112,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")
}
Expand Down Expand Up @@ -162,3 +212,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 := int(C.set_bitrate(enc.p, C.opus_int32(bitrate)))
if res < 0 {
return opusError(res)
}
return nil
}

// Bitrate returns the bitrate of the Encoder
func (enc *Encoder) Bitrate() (int, error) {
var bitrate C.opus_int32
res := int(C.get_bitrate(enc.p, &bitrate))
if res < 0 {
return 0, opusError(res)
}
return int(bitrate), nil
}

// SetComplexity sets the encoder's computational complexity
func (enc *Encoder) SetComplexity(complexity int) error {
res := int(C.set_complexity(enc.p, C.opus_int32(complexity)))
if res < 0 {
return opusError(res)
}
return nil
}

// Complexity returns the bitrate of the Encoder
func (enc *Encoder) Complexity() (int, error) {
var complexity C.opus_int32
res := int(C.get_complexity(enc.p, &complexity))
if res < 0 {
return 0, opusError(res)
}
return int(complexity), nil
}

// SetMaxBandwidth configures the maximum bandpass that the encoder will select
// automatically
func (enc *Encoder) SetMaxBandwidth(maxBw int) error {
res := int(C.set_max_bandwidth(enc.p, C.opus_int32(maxBw)))
if res < 0 {
return opusError(res)
}
return nil
}

// MaxBandwidth gets the encoder's configured maximum allowed bandpass.
func (enc *Encoder) MaxBandwidth() (int, error) {
var maxBw C.opus_int32
res := int(C.get_max_bandwidth(enc.p, &maxBw))
if res < 0 {
return 0, opusError(res)
}
return int(maxBw), nil
}
123 changes: 118 additions & 5 deletions encoder_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
// Copyright © 2015, 2016 Authors (see AUTHORS file)
//
// License for use of this code is detailed in the LICENSE file

package opus

import "testing"
import (
"testing"
)

func TestEncoderNew(t *testing.T) {
enc, err := NewEncoder(48000, 1, APPLICATION_VOIP)
Expand Down Expand Up @@ -57,3 +55,118 @@ func TestEncoderSampleRate(t *testing.T) {
}
}
}

func TestEncoder_SetGetBitrate(t *testing.T) {
enc, err := NewEncoder(8000, 1, APPLICATION_AUDIO)
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, APPLICATION_AUDIO)
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, APPLICATION_AUDIO)
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, APPLICATION_AUDIO)
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, APPLICATION_AUDIO)
if err != nil || enc == nil {
t.Errorf("Error creating new encoder: %v", err)
}
vals := []int{OPUS_BANDWIDTH_NARROWBAND,
OPUS_BANDWIDTH_MEDIUMBAND,
OPUS_BANDWIDTH_WIDEBAND,
OPUS_BANDWIDTH_SUPERWIDEBAND,
OPUS_BANDWIDTH_FULLBAND,
}
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)
}
}
}
26 changes: 18 additions & 8 deletions opus.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,27 @@ const int CONST_APPLICATION_RESTRICTED_LOWDELAY = OPUS_APPLICATION_RESTRICTED_LO
*/
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
APPLICATION_VOIP = Application(C.CONST_APPLICATION_VOIP)
APPLICATION_VOIP = C.OPUS_APPLICATION_VOIP
// Optimize encoding for non-voice signals like music
APPLICATION_AUDIO = Application(C.CONST_APPLICATION_AUDIO)
APPLICATION_AUDIO = C.OPUS_APPLICATION_AUDIO
// Optimize encoding for low latency applications
APPLICATION_RESTRICTED_LOWDELAY = Application(C.CONST_APPLICATION_RESTRICTED_LOWDELAY)
APPLICATION_RESTRICTED_LOWDELAY = C.OPUS_APPLICATION_RESTRICTED_LOWDELAY
// Auto bitrate
OPUS_AUTO = C.OPUS_AUTO
// Maximum bitrate
OPUS_BITRATE_MAX = C.OPUS_BITRATE_MAX
//4 kHz passband
OPUS_BANDWIDTH_NARROWBAND = C.OPUS_BANDWIDTH_NARROWBAND
// 6 kHz passband
OPUS_BANDWIDTH_MEDIUMBAND = C.OPUS_BANDWIDTH_MEDIUMBAND
// 8 kHz passband
OPUS_BANDWIDTH_WIDEBAND = C.OPUS_BANDWIDTH_WIDEBAND
// 12 kHz passband
OPUS_BANDWIDTH_SUPERWIDEBAND = C.OPUS_BANDWIDTH_SUPERWIDEBAND
// 20 kHz passband
OPUS_BANDWIDTH_FULLBAND = C.OPUS_BANDWIDTH_FULLBAND
)

const (
Expand Down