]> Sergey Matveev's repositories - go-opus.git/commitdiff
Let user pass the target buffers (noalloc)
authorHraban Luyat <hraban@0brg.net>
Wed, 22 Jul 2015 05:52:38 +0000 (06:52 +0100)
committerHraban Luyat <hraban@0brg.net>
Wed, 22 Jul 2015 05:53:34 +0000 (06:53 +0100)
decoder.go
encoder.go
opus_test.go

index 16b26288fe1e4895a1b47724d9846e6433883241..94e98386d224d27935c07cff6687f864d6706f55 100644 (file)
@@ -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
 }
index 58a541b573517dd46cd1847ef28839059e438332..e6e3ae44097a80d86bd5be36ef3c0ffb4778477a 100644 (file)
@@ -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
 }
index c0d0eada007a0f81595a4cacaac5dd5e7817676f..76380eca751587e7a24caf7c5a09e70afc8ef5cd 100644 (file)
@@ -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)
        }
 }