From: Hraban Luyat Date: Wed, 22 Jul 2015 05:52:38 +0000 (+0100) Subject: Let user pass the target buffers (noalloc) X-Git-Tag: v2.0.0~79 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=b6c362cf3b96075bbad96ea1778138e90201b012;p=go-opus.git Let user pass the target buffers (noalloc) --- diff --git a/decoder.go b/decoder.go index 16b2628..94e9838 100644 --- a/decoder.go +++ b/decoder.go @@ -56,15 +56,18 @@ func (dec *Decoder) Init(sample_rate int, channels int) error { return nil } -func (dec *Decoder) Decode(data []byte) ([]int16, error) { +// Decode encoded Opus data into the supplied buffer. On success, returns the +// number of samples correctly written to the target buffer. +func (dec *Decoder) Decode(data []byte, pcm []int16) (int, error) { if dec.p == nil { - return nil, errDecUninitialized + return 0, errDecUninitialized } - if data == nil || len(data) == 0 { - return nil, fmt.Errorf("opus: no data supplied") + if len(data) == 0 { + return 0, fmt.Errorf("opus: no data supplied") + } + if len(pcm) == 0 { + return 0, fmt.Errorf("opus: target buffer empty") } - // I don't know how big this frame will be, but this is the limit - pcm := make([]int16, xMAX_FRAME_SIZE_MS*dec.sample_rate/1000) n := int(C.opus_decode( dec.p, (*C.uchar)(&data[0]), @@ -73,19 +76,23 @@ func (dec *Decoder) Decode(data []byte) ([]int16, error) { C.int(cap(pcm)), 0)) if n < 0 { - return nil, opuserr(n) + return 0, opuserr(n) } - return pcm[:n], nil + return n, nil } -func (dec *Decoder) DecodeFloat32(data []byte) ([]float32, error) { +// Decode encoded Opus data into the supplied buffer. On success, returns the +// number of samples correctly written to the target buffer. +func (dec *Decoder) DecodeFloat32(data []byte, pcm []float32) (int, error) { if dec.p == nil { - return nil, errDecUninitialized + return 0, errDecUninitialized + } + if len(data) == 0 { + return 0, fmt.Errorf("opus: no data supplied") } - if data == nil || len(data) == 0 { - return nil, fmt.Errorf("opus: no data supplied") + if len(pcm) == 0 { + return 0, fmt.Errorf("opus: target buffer empty") } - pcm := make([]float32, xMAX_FRAME_SIZE_MS*dec.sample_rate/1000) n := int(C.opus_decode_float( dec.p, (*C.uchar)(&data[0]), @@ -94,7 +101,7 @@ func (dec *Decoder) DecodeFloat32(data []byte) ([]float32, error) { C.int(cap(pcm)), 0)) if n < 0 { - return nil, opuserr(n) + return 0, opuserr(n) } - return pcm[:n], nil + return n, nil } diff --git a/encoder.go b/encoder.go index 58a541b..e6e3ae4 100644 --- a/encoder.go +++ b/encoder.go @@ -60,14 +60,18 @@ func (enc *Encoder) Init(sample_rate int, channels int, application Application) return nil } -func (enc *Encoder) Encode(pcm []int16) ([]byte, error) { +// Encode raw PCM data and store the result in the supplied buffer. On success, +// returns the number of bytes used up by the encoded data. +func (enc *Encoder) Encode(pcm []int16, data []byte) (int, error) { if enc.p == nil { - return nil, errEncUninitialized + return 0, errEncUninitialized } - if pcm == nil || len(pcm) == 0 { - return nil, fmt.Errorf("opus: no data supplied") + if len(pcm) == 0 { + return 0, fmt.Errorf("opus: no data supplied") + } + if len(data) == 0 { + return 0, fmt.Errorf("opus: no target buffer") } - data := make([]byte, maxEncodedFrameSize) n := int(C.opus_encode( enc.p, (*C.opus_int16)(&pcm[0]), @@ -75,19 +79,23 @@ func (enc *Encoder) Encode(pcm []int16) ([]byte, error) { (*C.uchar)(&data[0]), C.opus_int32(cap(data)))) if n < 0 { - return nil, opuserr(n) + return 0, opuserr(n) } - return data[:n], nil + return n, nil } -func (enc *Encoder) EncodeFloat32(pcm []float32) ([]byte, error) { +// Encode raw PCM data and store the result in the supplied buffer. On success, +// returns the number of bytes used up by the encoded data. +func (enc *Encoder) EncodeFloat32(pcm []float32, data []byte) (int, error) { if enc.p == nil { - return nil, errEncUninitialized + return 0, errEncUninitialized + } + if len(pcm) == 0 { + return 0, fmt.Errorf("opus: no data supplied") } - if pcm == nil || len(pcm) == 0 { - return nil, fmt.Errorf("opus: no data supplied") + if len(data) == 0 { + return 0, fmt.Errorf("opus: no target buffer") } - data := make([]byte, maxEncodedFrameSize) n := int(C.opus_encode_float( enc.p, (*C.float)(&pcm[0]), @@ -95,7 +103,7 @@ func (enc *Encoder) EncodeFloat32(pcm []float32) ([]byte, error) { (*C.uchar)(&data[0]), C.opus_int32(cap(data)))) if n < 0 { - return nil, opuserr(n) + return 0, opuserr(n) } - return data[:n], nil + return n, nil } diff --git a/opus_test.go b/opus_test.go index c0d0ead..76380ec 100644 --- a/opus_test.go +++ b/opus_test.go @@ -40,11 +40,11 @@ func TestDecoderNew(t *testing.T) { func TestEncoderUnitialized(t *testing.T) { var enc Encoder - _, err := enc.Encode(nil) + _, err := enc.Encode(nil, nil) if err != errEncUninitialized { t.Errorf("Expected \"unitialized encoder\" error: %v", err) } - _, err = enc.EncodeFloat32(nil) + _, err = enc.EncodeFloat32(nil, nil) if err != errEncUninitialized { t.Errorf("Expected \"unitialized encoder\" error: %v", err) } @@ -52,11 +52,11 @@ func TestEncoderUnitialized(t *testing.T) { func TestDecoderUnitialized(t *testing.T) { var dec Decoder - _, err := dec.Decode(nil) + _, err := dec.Decode(nil, nil) if err != errDecUninitialized { t.Errorf("Expected \"unitialized decoder\" error: %v", err) } - _, err = dec.DecodeFloat32(nil) + _, err = dec.DecodeFloat32(nil, nil) if err != errDecUninitialized { t.Errorf("Expected \"unitialized decoder\" error: %v", err) } @@ -98,20 +98,22 @@ func TestCodec(t *testing.T) { t.Fatalf("Error creating new encoder: %v", err) } addSine(pcm, SAMPLE_RATE, G4) - data, err := enc.Encode(pcm) + data := make([]byte, 1000) + n, err := enc.Encode(pcm, data) if err != nil { t.Fatalf("Couldn't encode data: %v", err) } + data = data[:n] dec, err := NewDecoder(SAMPLE_RATE, 1) if err != nil || dec == nil { t.Fatalf("Error creating new decoder: %v", err) } - pcm2, err := dec.Decode(data) + n, err = dec.Decode(data, pcm) if err != nil { t.Fatalf("Couldn't decode data: %v", err) } - if len(pcm) != len(pcm2) { - t.Fatalf("Length mismatch: %d samples in, %d out", len(pcm), len(pcm2)) + if len(pcm) != n { + t.Fatalf("Length mismatch: %d samples in, %d out", len(pcm), n) } // Checking the output programmatically is seriously not easy. I checked it // by hand and by ear, it looks fine. I'll just assume the API faithfully @@ -130,7 +132,8 @@ func TestCodecFloat32(t *testing.T) { t.Fatalf("Error creating new encoder: %v", err) } addSineFloat32(pcm, SAMPLE_RATE, G4) - data, err := enc.EncodeFloat32(pcm) + data := make([]byte, 1000) + n, err := enc.EncodeFloat32(pcm, data) if err != nil { t.Fatalf("Couldn't encode data: %v", err) } @@ -138,11 +141,11 @@ func TestCodecFloat32(t *testing.T) { if err != nil || dec == nil { t.Fatalf("Error creating new decoder: %v", err) } - pcm2, err := dec.DecodeFloat32(data) + n, err = dec.DecodeFloat32(data, pcm) if err != nil { t.Fatalf("Couldn't decode data: %v", err) } - if len(pcm) != len(pcm2) { - t.Fatalf("Length mismatch: %d samples in, %d out", len(pcm), len(pcm2)) + if len(pcm) != n { + t.Fatalf("Length mismatch: %d samples in, %d out", len(pcm), n) } }