Added decodeFECFloat32 + test
This commit is contained in:
parent
5ba421ac73
commit
68fb7a26d9
25
decoder.go
25
decoder.go
|
@ -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
|
||||
|
|
126
opus_test.go
126
opus_test.go
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue