]> Sergey Matveev's repositories - go-opus.git/commitdiff
Added decodeFECFloat32 + test
authorelinor <elinor.alp@gmail.com>
Mon, 26 Mar 2018 07:39:25 +0000 (10:39 +0300)
committerelinor <elinor.alp@gmail.com>
Mon, 26 Mar 2018 07:39:25 +0000 (10:39 +0300)
decoder.go
opus_test.go

index 9b5b11756909765ac9d0ce8b74c4940a547fe5ff..50453bb039f603fbea68521d1dba7334aadfeda0 100644 (file)
@@ -138,6 +138,31 @@ func (dec *Decoder) DecodeFEC(data []byte, pcm []int16) error {
        return nil
 }
 
+// Decode encoded Opus data into the supplied buffer with forward error
+// correction. The supplied buffer will be entirely filled.
+func (dec *Decoder) DecodeFECFloat32(data []byte, pcm []float32) error {
+       if dec.p == nil {
+               return errDecUninitialized
+       }
+       if len(data) == 0 {
+               return fmt.Errorf("opus: no data supplied")
+       }
+       if len(pcm) == 0 {
+               return fmt.Errorf("opus: target buffer empty")
+       }
+       n := int(C.opus_decode_float(
+               dec.p,
+               (*C.uchar)(&data[0]),
+               C.opus_int32(len(data)),
+               (*C.float)(&pcm[0]),
+               C.int(cap(pcm)),
+               1))
+       if n < 0 {
+               return Error(n)
+       }
+       return nil
+}
+
 // Gets the duration (in samples) of the last packet successfully decoded or concealed.
 func (dec *Decoder) LastPacketDuration() (int, error) {
        var samples C.opus_int32
index f894d5bf5b46468bc4d3d5f8c8ebf46aea5f91d2..68ac45d5aba55517637296d07bf22b5321f73c6e 100644 (file)
@@ -59,6 +59,38 @@ func TestCodec(t *testing.T) {
        // passes error codes through, and that's that.
 }
 
+func TestCodecFloat32(t *testing.T) {
+       // Create bogus input sound
+       const G4 = 391.995
+       const SAMPLE_RATE = 48000
+       const FRAME_SIZE_MS = 60
+       const FRAME_SIZE = SAMPLE_RATE * FRAME_SIZE_MS / 1000
+       pcm := make([]float32, FRAME_SIZE)
+       enc, err := NewEncoder(SAMPLE_RATE, 1, AppVoIP)
+       if err != nil || enc == nil {
+               t.Fatalf("Error creating new encoder: %v", err)
+       }
+       addSineFloat32(pcm, SAMPLE_RATE, G4)
+       data := make([]byte, 1000)
+       n, err := enc.EncodeFloat32(pcm, data)
+       if err != nil {
+               t.Fatalf("Couldn't encode data: %v", err)
+       }
+       dec, err := NewDecoder(SAMPLE_RATE, 1)
+       if err != nil || dec == nil {
+               t.Fatalf("Error creating new decoder: %v", err)
+       }
+       // TODO: Uh-oh.. it looks like I forgot to put a data = data[:n] here, yet
+       // the test is not failing. Why?
+       n, err = dec.DecodeFloat32(data, pcm)
+       if err != nil {
+               t.Fatalf("Couldn't decode data: %v", err)
+       }
+       if len(pcm) != n {
+               t.Fatalf("Length mismatch: %d samples in, %d out", len(pcm), n)
+       }
+}
+
 func TestCodecFEC(t *testing.T) {
        // Create bogus input sound
        const G4 = 391.995
@@ -137,42 +169,98 @@ func TestCodecFEC(t *testing.T) {
        // string of zero samples before they pick up, and the G4 is phase shifted
        // by half a period, but that's all fine for lossy audio encoding.
 
-       //fmt.Printf("in,out\n")
-       //for i := range mono {
-       //      fmt.Printf("%d,%d\n", mono[i], pcm[i])
-       //}
+       /*
+               fmt.Printf("in,out\n")
+               for i := range mono {
+                       fmt.Printf("%d,%d\n", mono[i], pcm[i])
+               }
+       */
 }
 
-func TestCodecFloat32(t *testing.T) {
+func TestCodecFECFloat32(t *testing.T) {
        // Create bogus input sound
        const G4 = 391.995
        const SAMPLE_RATE = 48000
        const FRAME_SIZE_MS = 60
        const FRAME_SIZE = SAMPLE_RATE * FRAME_SIZE_MS / 1000
-       pcm := make([]float32, FRAME_SIZE)
+       const PACKET_SIZE = 480 // 10ms packet
+       pcm := make([]float32, 0)
+
        enc, err := NewEncoder(SAMPLE_RATE, 1, AppVoIP)
        if err != nil || enc == nil {
                t.Fatalf("Error creating new encoder: %v", err)
        }
-       addSineFloat32(pcm, SAMPLE_RATE, G4)
-       data := make([]byte, 1000)
-       n, err := enc.EncodeFloat32(pcm, data)
-       if err != nil {
-               t.Fatalf("Couldn't encode data: %v", err)
-       }
+       enc.SetPacketLossPerc(30)
+       enc.SetInBandFEC(1)
+
        dec, err := NewDecoder(SAMPLE_RATE, 1)
        if err != nil || dec == nil {
                t.Fatalf("Error creating new decoder: %v", err)
        }
-       // TODO: Uh-oh.. it looks like I forgot to put a data = data[:n] here, yet
-       // the test is not failing. Why?
-       n, err = dec.DecodeFloat32(data, pcm)
-       if err != nil {
-               t.Fatalf("Couldn't decode data: %v", err)
+
+       mono := make([]float32, FRAME_SIZE)
+       addSineFloat32(mono, SAMPLE_RATE, G4)
+
+       encodedData := make([][]byte, FRAME_SIZE/PACKET_SIZE)
+       for i, idx := 0, 0; i < len(mono); i += PACKET_SIZE {
+               data := make([]byte, 1000)
+               n, err := enc.EncodeFloat32(mono[i:i+PACKET_SIZE], data)
+               if err != nil {
+                       t.Fatalf("Couldn't encode data: %v", err)
+               }
+               data = data[:n]
+               encodedData[idx] = data
+               idx++
        }
-       if len(pcm) != n {
-               t.Fatalf("Length mismatch: %d samples in, %d out", len(pcm), n)
+
+       lost := false
+       for i := 0; i < len(encodedData); i++ {
+               // "Dropping" packets 2 and 4
+               if i == 2 || i == 4 {
+                       lost = true
+                       continue
+               }
+               if lost {
+                       samples, err := dec.LastPacketDuration()
+                       if err != nil {
+                               t.Fatalf("Couldn't get last packet duration: %v", err)
+                       }
+
+                       pcmBuffer := make([]float32, samples)
+                       if err = dec.DecodeFECFloat32(encodedData[i], pcmBuffer); err != nil {
+                               t.Fatalf("Couldn't decode data: %v", err)
+                       }
+                       pcm = append(pcm, pcmBuffer...)
+                       lost = false
+               }
+
+               pcmBuffer := make([]float32, FRAME_SIZE)
+               n, err := dec.DecodeFloat32(encodedData[i], pcmBuffer)
+               if err != nil {
+                       t.Fatalf("Couldn't decode data: %v", err)
+               }
+               pcmBuffer = pcmBuffer[:n]
+               if len(pcmBuffer) != n {
+                       t.Fatalf("Length mismatch: %d samples in, %d out", len(pcmBuffer), n)
+               }
+               pcm = append(pcm, pcmBuffer...)
        }
+
+       if len(mono) != len(pcm) {
+               t.Fatalf("Input/Output length mismatch: %d samples in, %d out", len(mono), len(pcm))
+       }
+
+       // This is hard to check programatically, but I plotted the graphs in a
+       // spreadsheet and it looked great. The encoded waves both start out with a
+       // string of zero samples before they pick up, and the G4 is phase shifted
+       // by half a period, but that's all fine for lossy audio encoding.
+
+       /*
+               fmt.Printf("in,out\n")
+               for i := 0; i < len(mono); i++ {
+                       fmt.Printf("%f,%f\n", mono[i], pcm[i])
+               }
+       */
 }
 
 func TestStereo(t *testing.T) {