mirror of
https://github.com/pion/mediadevices.git
synced 2025-10-05 08:36:55 +08:00
Add raw audio decoder
* Add Int16Interleaved and Int16NonInterleaved formats * Add Float32Interleaved and Float32NonInterleaved formats * Add unit tests
This commit is contained in:
314
pkg/wave/decoder_test.go
Normal file
314
pkg/wave/decoder_test.go
Normal file
@@ -0,0 +1,314 @@
|
||||
package wave
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCalculateChunkInfo(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
chunk []byte
|
||||
channels int
|
||||
sampleSize int
|
||||
expected ChunkInfo
|
||||
expectErr bool
|
||||
}{
|
||||
"InvalidChunkSize1": {
|
||||
chunk: make([]byte, 3),
|
||||
channels: 2,
|
||||
sampleSize: 2,
|
||||
expected: ChunkInfo{},
|
||||
expectErr: true,
|
||||
},
|
||||
"InvalidChunkSize2": {
|
||||
chunk: make([]byte, 4),
|
||||
channels: 2,
|
||||
sampleSize: 4,
|
||||
expected: ChunkInfo{},
|
||||
expectErr: true,
|
||||
},
|
||||
"InvalidChannels": {
|
||||
chunk: nil,
|
||||
channels: 0,
|
||||
sampleSize: 2,
|
||||
expected: ChunkInfo{},
|
||||
expectErr: true,
|
||||
},
|
||||
"InvalidSampleSize": {
|
||||
chunk: nil,
|
||||
channels: 2,
|
||||
sampleSize: 0,
|
||||
expected: ChunkInfo{},
|
||||
expectErr: true,
|
||||
},
|
||||
"Valid1": {
|
||||
chunk: nil,
|
||||
channels: 2,
|
||||
sampleSize: 2,
|
||||
expected: ChunkInfo{
|
||||
Len: 0,
|
||||
Channels: 2,
|
||||
SamplingRate: 0,
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
"Valid2": {
|
||||
chunk: make([]byte, 8),
|
||||
channels: 2,
|
||||
sampleSize: 4,
|
||||
expected: ChunkInfo{
|
||||
Len: 1,
|
||||
Channels: 2,
|
||||
SamplingRate: 0,
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
"Valid3": {
|
||||
chunk: make([]byte, 4),
|
||||
channels: 1,
|
||||
sampleSize: 2,
|
||||
expected: ChunkInfo{
|
||||
Len: 2,
|
||||
Channels: 1,
|
||||
SamplingRate: 0,
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for testCaseName, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(testCaseName, func(t *testing.T) {
|
||||
actual, err := calculateChunkInfo(testCase.chunk, testCase.channels, testCase.sampleSize)
|
||||
if testCase.expectErr && err == nil {
|
||||
t.Fatal("expected an error, but got nil")
|
||||
} else if !testCase.expectErr && err != nil {
|
||||
t.Fatalf("expected no error, but got %s", err)
|
||||
} else if !testCase.expectErr && !reflect.DeepEqual(actual, testCase.expected) {
|
||||
t.Errorf("Wrong chunk info calculation result,\nexpected:\n%+v\ngot:\n%+v", testCase.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeInt16Interleaved(t *testing.T) {
|
||||
raw := []byte{
|
||||
// 16 bits per channel
|
||||
0x01, 0x02, 0x03, 0x04,
|
||||
0x05, 0x06, 0x07, 0x08,
|
||||
}
|
||||
|
||||
t.Run("BigEndian", func(t *testing.T) {
|
||||
expected := &Int16Interleaved{
|
||||
Data: []int16{
|
||||
int16(binary.BigEndian.Uint16([]byte{0x01, 0x02})),
|
||||
int16(binary.BigEndian.Uint16([]byte{0x03, 0x04})),
|
||||
int16(binary.BigEndian.Uint16([]byte{0x05, 0x06})),
|
||||
int16(binary.BigEndian.Uint16([]byte{0x07, 0x08})),
|
||||
},
|
||||
Size: ChunkInfo{
|
||||
Len: 2,
|
||||
Channels: 2,
|
||||
},
|
||||
}
|
||||
actual, err := decodeInt16Interleaved(binary.BigEndian, raw, 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("Wrong decode result,\nexpected:\n%+v\ngot:\n%+v", expected, actual)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("LittleEndian", func(t *testing.T) {
|
||||
expected := &Int16Interleaved{
|
||||
Data: []int16{
|
||||
int16(binary.LittleEndian.Uint16([]byte{0x01, 0x02})),
|
||||
int16(binary.LittleEndian.Uint16([]byte{0x03, 0x04})),
|
||||
int16(binary.LittleEndian.Uint16([]byte{0x05, 0x06})),
|
||||
int16(binary.LittleEndian.Uint16([]byte{0x07, 0x08})),
|
||||
},
|
||||
Size: ChunkInfo{
|
||||
Len: 2,
|
||||
Channels: 2,
|
||||
},
|
||||
}
|
||||
actual, err := decodeInt16Interleaved(binary.LittleEndian, raw, 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("Wrong decode result,\nexpected:\n%+v\ngot:\n%+v", expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestDecodeInt16NonInterleaved(t *testing.T) {
|
||||
raw := []byte{
|
||||
// 16 bits per channel
|
||||
0x01, 0x02, 0x03, 0x04,
|
||||
0x05, 0x06, 0x07, 0x08,
|
||||
}
|
||||
|
||||
t.Run("BigEndian", func(t *testing.T) {
|
||||
expected := &Int16NonInterleaved{
|
||||
Data: [][]int16{
|
||||
{int16(binary.BigEndian.Uint16([]byte{0x01, 0x02})), int16(binary.BigEndian.Uint16([]byte{0x03, 0x04}))},
|
||||
{int16(binary.BigEndian.Uint16([]byte{0x05, 0x06})), int16(binary.BigEndian.Uint16([]byte{0x07, 0x08}))},
|
||||
},
|
||||
Size: ChunkInfo{
|
||||
Len: 2,
|
||||
Channels: 2,
|
||||
},
|
||||
}
|
||||
actual, err := decodeInt16NonInterleaved(binary.BigEndian, raw, 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("Wrong decode result,\nexpected:\n%+v\ngot:\n%+v", expected, actual)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("LittleEndian", func(t *testing.T) {
|
||||
expected := &Int16NonInterleaved{
|
||||
Data: [][]int16{
|
||||
{int16(binary.LittleEndian.Uint16([]byte{0x01, 0x02})), int16(binary.LittleEndian.Uint16([]byte{0x03, 0x04}))},
|
||||
{int16(binary.LittleEndian.Uint16([]byte{0x05, 0x06})), int16(binary.LittleEndian.Uint16([]byte{0x07, 0x08}))},
|
||||
},
|
||||
Size: ChunkInfo{
|
||||
Len: 2,
|
||||
Channels: 2,
|
||||
},
|
||||
}
|
||||
actual, err := decodeInt16NonInterleaved(binary.LittleEndian, raw, 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("Wrong decode result,\nexpected:\n%+v\ngot:\n%+v", expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestDecodeFloat32Interleaved(t *testing.T) {
|
||||
raw := []byte{
|
||||
// 32 bits per channel
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
|
||||
}
|
||||
|
||||
t.Run("BigEndian", func(t *testing.T) {
|
||||
expected := &Float32Interleaved{
|
||||
Data: []float32{
|
||||
math.Float32frombits(binary.BigEndian.Uint32([]byte{0x01, 0x02, 0x03, 0x04})),
|
||||
math.Float32frombits(binary.BigEndian.Uint32([]byte{0x05, 0x06, 0x07, 0x08})),
|
||||
math.Float32frombits(binary.BigEndian.Uint32([]byte{0x09, 0x0a, 0x0b, 0x0c})),
|
||||
math.Float32frombits(binary.BigEndian.Uint32([]byte{0x0d, 0x0e, 0x0f, 0x10})),
|
||||
},
|
||||
Size: ChunkInfo{
|
||||
Len: 2,
|
||||
Channels: 2,
|
||||
},
|
||||
}
|
||||
actual, err := decodeFloat32Interleaved(binary.BigEndian, raw, 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("Wrong decode result,\nexpected:\n%+v\ngot:\n%+v", expected, actual)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("LittleEndian", func(t *testing.T) {
|
||||
expected := &Float32Interleaved{
|
||||
Data: []float32{
|
||||
math.Float32frombits(binary.LittleEndian.Uint32([]byte{0x01, 0x02, 0x03, 0x04})),
|
||||
math.Float32frombits(binary.LittleEndian.Uint32([]byte{0x05, 0x06, 0x07, 0x08})),
|
||||
math.Float32frombits(binary.LittleEndian.Uint32([]byte{0x09, 0x0a, 0x0b, 0x0c})),
|
||||
math.Float32frombits(binary.LittleEndian.Uint32([]byte{0x0d, 0x0e, 0x0f, 0x10})),
|
||||
},
|
||||
Size: ChunkInfo{
|
||||
Len: 2,
|
||||
Channels: 2,
|
||||
},
|
||||
}
|
||||
actual, err := decodeFloat32Interleaved(binary.LittleEndian, raw, 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("Wrong decode result,\nexpected:\n%+v\ngot:\n%+v", expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestDecodeFloat32NonInterleaved(t *testing.T) {
|
||||
raw := []byte{
|
||||
// 32 bits per channel
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
|
||||
}
|
||||
|
||||
t.Run("BigEndian", func(t *testing.T) {
|
||||
expected := &Float32NonInterleaved{
|
||||
Data: [][]float32{
|
||||
{
|
||||
math.Float32frombits(binary.BigEndian.Uint32([]byte{0x01, 0x02, 0x03, 0x04})),
|
||||
math.Float32frombits(binary.BigEndian.Uint32([]byte{0x05, 0x06, 0x07, 0x08})),
|
||||
},
|
||||
{
|
||||
math.Float32frombits(binary.BigEndian.Uint32([]byte{0x09, 0x0a, 0x0b, 0x0c})),
|
||||
math.Float32frombits(binary.BigEndian.Uint32([]byte{0x0d, 0x0e, 0x0f, 0x10})),
|
||||
},
|
||||
},
|
||||
Size: ChunkInfo{
|
||||
Len: 2,
|
||||
Channels: 2,
|
||||
},
|
||||
}
|
||||
actual, err := decodeFloat32NonInterleaved(binary.BigEndian, raw, 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("Wrong decode result,\nexpected:\n%+v\ngot:\n%+v", expected, actual)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("LittleEndian", func(t *testing.T) {
|
||||
expected := &Float32NonInterleaved{
|
||||
Data: [][]float32{
|
||||
{
|
||||
math.Float32frombits(binary.LittleEndian.Uint32([]byte{0x01, 0x02, 0x03, 0x04})),
|
||||
math.Float32frombits(binary.LittleEndian.Uint32([]byte{0x05, 0x06, 0x07, 0x08})),
|
||||
},
|
||||
{
|
||||
math.Float32frombits(binary.LittleEndian.Uint32([]byte{0x09, 0x0a, 0x0b, 0x0c})),
|
||||
math.Float32frombits(binary.LittleEndian.Uint32([]byte{0x0d, 0x0e, 0x0f, 0x10})),
|
||||
},
|
||||
},
|
||||
Size: ChunkInfo{
|
||||
Len: 2,
|
||||
Channels: 2,
|
||||
},
|
||||
}
|
||||
actual, err := decodeFloat32NonInterleaved(binary.LittleEndian, raw, 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
t.Errorf("Wrong decode result,\nexpected:\n%+v\ngot:\n%+v", expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user