From: Hraban Luyat Date: Sun, 5 Jul 2015 13:42:05 +0000 (+0100) Subject: .Init method for preallocated codecs X-Git-Tag: v2.0.0~102 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=5289d1e143a787603d0dd6d24a7f8c0ebe3511d9;p=go-opus.git .Init method for preallocated codecs --- diff --git a/decoder.go b/decoder.go index 14acf98..16b2628 100644 --- a/decoder.go +++ b/decoder.go @@ -15,6 +15,8 @@ import ( */ import "C" +var errDecUninitialized = fmt.Errorf("opus decoder uninitialized") + type Decoder struct { p *C.struct_OpusDecoder // Same purpose as encoder struct @@ -25,11 +27,23 @@ type Decoder struct { // NewEncoder allocates a new Opus decoder and initializes it with the // appropriate parameters. All related memory is managed by the Go GC. func NewDecoder(sample_rate int, channels int) (*Decoder, error) { + var dec Decoder + err := dec.Init(sample_rate, channels) + if err != nil { + return nil, err + } + return &dec, nil +} + +func (dec *Decoder) Init(sample_rate int, channels int) error { + if dec.p != nil { + return fmt.Errorf("opus decoder already initialized") + } if channels != 1 && channels != 2 { - return nil, fmt.Errorf("Number of channels must be 1 or 2: %d", channels) + return fmt.Errorf("Number of channels must be 1 or 2: %d", channels) } - dec := Decoder{sample_rate: sample_rate} size := C.opus_decoder_get_size(C.int(channels)) + dec.sample_rate = sample_rate dec.mem = make([]byte, size) dec.p = (*C.OpusDecoder)(unsafe.Pointer(&dec.mem[0])) errno := C.opus_decoder_init( @@ -37,12 +51,15 @@ func NewDecoder(sample_rate int, channels int) (*Decoder, error) { C.opus_int32(sample_rate), C.int(channels)) if errno != 0 { - return nil, opuserr(int(errno)) + return opuserr(int(errno)) } - return &dec, nil + return nil } func (dec *Decoder) Decode(data []byte) ([]int16, error) { + if dec.p == nil { + return nil, errDecUninitialized + } if data == nil || len(data) == 0 { return nil, fmt.Errorf("opus: no data supplied") } @@ -62,6 +79,9 @@ func (dec *Decoder) Decode(data []byte) ([]int16, error) { } func (dec *Decoder) DecodeFloat32(data []byte) ([]float32, error) { + if dec.p == nil { + return nil, errDecUninitialized + } if data == nil || len(data) == 0 { return nil, fmt.Errorf("opus: no data supplied") } diff --git a/encoder.go b/encoder.go index 21467f8..5438373 100644 --- a/encoder.go +++ b/encoder.go @@ -15,6 +15,10 @@ import ( */ import "C" +var errEncUninitialized = fmt.Errorf("opus encoder uninitialized") + +// Encoder contains the state of an Opus encoder for libopus. Do not use this +// directly, but call type Encoder struct { p *C.struct_OpusEncoder // Memory for the encoder struct allocated on the Go heap to allow Go GC to @@ -25,25 +29,41 @@ 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) { + var enc Encoder + err := enc.Init(sample_rate, channels, application) + if err != nil { + return nil, err + } + return &enc, nil +} + +// Init initializes a pre-allocated opus encoder. 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 { + if enc.p != nil { + return fmt.Errorf("opus encoder already initialized") + } if channels != 1 && channels != 2 { - return nil, fmt.Errorf("Number of channels must be 1 or 2: %d", channels) + return fmt.Errorf("Number of channels must be 1 or 2: %d", channels) } - var e Encoder size := C.opus_encoder_get_size(C.int(channels)) - e.mem = make([]byte, size) - e.p = (*C.OpusEncoder)(unsafe.Pointer(&e.mem[0])) + enc.mem = make([]byte, size) + enc.p = (*C.OpusEncoder)(unsafe.Pointer(&enc.mem[0])) errno := int(C.opus_encoder_init( - e.p, + enc.p, C.opus_int32(sample_rate), C.int(channels), C.int(application))) if errno != 0 { - return nil, opuserr(int(errno)) + return opuserr(int(errno)) } - return &e, nil + return nil } func (enc *Encoder) Encode(pcm []int16) ([]byte, error) { + if enc.p == nil { + return nil, errEncUninitialized + } if pcm == nil || len(pcm) == 0 { return nil, fmt.Errorf("opus: no data supplied") } @@ -62,6 +82,9 @@ func (enc *Encoder) Encode(pcm []int16) ([]byte, error) { } func (enc *Encoder) EncodeFloat32(pcm []float32) ([]byte, error) { + if enc.p == nil { + return nil, errEncUninitialized + } if pcm == nil || len(pcm) == 0 { return nil, fmt.Errorf("opus: no data supplied") } diff --git a/opus_test.go b/opus_test.go index bdab063..c0d0ead 100644 --- a/opus_test.go +++ b/opus_test.go @@ -38,6 +38,30 @@ func TestDecoderNew(t *testing.T) { } } +func TestEncoderUnitialized(t *testing.T) { + var enc Encoder + _, err := enc.Encode(nil) + if err != errEncUninitialized { + t.Errorf("Expected \"unitialized encoder\" error: %v", err) + } + _, err = enc.EncodeFloat32(nil) + if err != errEncUninitialized { + t.Errorf("Expected \"unitialized encoder\" error: %v", err) + } +} + +func TestDecoderUnitialized(t *testing.T) { + var dec Decoder + _, err := dec.Decode(nil) + if err != errDecUninitialized { + t.Errorf("Expected \"unitialized decoder\" error: %v", err) + } + _, err = dec.DecodeFloat32(nil) + if err != errDecUninitialized { + t.Errorf("Expected \"unitialized decoder\" error: %v", err) + } +} + func TestOpuserr(t *testing.T) { // I scooped this -1 up from opus_defines.h, it's OPUS_BAD_ARG. Not pretty, // but it's better than not testing at all. Again, accessing #defines from