go-pus/stream_test.go
2015-07-12 11:08:13 +00:00

154 lines
3.5 KiB
Go

// Copyright © 2015 Hraban Luyat <hraban@0brg.net>
//
// License for use of this code is detailed in the LICENSE file
package opus
import (
"fmt"
"io"
"io/ioutil"
"math"
"os"
"reflect"
"strings"
"testing"
)
func TestStreamIllegal(t *testing.T) {
// Simple testing, no actual decoding
reader := strings.NewReader("hello test test this is not a legal Opus stream")
_, err := NewStream(reader)
if err == nil {
t.Fatalf("Expected error while initializing illegal opus stream")
}
}
func readStreamPcm(t *testing.T, stream *Stream, buffersize int) []int16 {
var pcm []int16
pcmbuf := make([]int16, buffersize)
for {
n, err := stream.Read(pcmbuf)
switch err {
case io.EOF:
return pcm
case nil:
break
default:
t.Fatalf("Error while decoding opus file: %v", err)
}
if n == 0 {
t.Fatal("Nil-error Read() must not return 0")
}
pcm = append(pcm, pcmbuf[:n]...)
}
}
func mustOpenFile(t *testing.T, fname string) *os.File {
f, err := os.Open(fname)
if err != nil {
t.Fatalf("Error while opening %s: %v", fname, err)
return nil
}
return f
}
func mustOpenStream(t *testing.T, r io.Reader) *Stream {
stream, err := NewStream(r)
if err != nil {
t.Fatalf("Error while creating opus stream: %v", err)
return nil
}
return stream
}
func opus2pcm(t *testing.T, fname string, buffersize int) []int16 {
reader := mustOpenFile(t, fname)
stream, err := NewStream(reader)
if err != nil {
t.Fatalf("Error while creating opus stream: %v", err)
}
return readStreamPcm(t, stream, buffersize)
}
// Extract raw pcm data from .wav file
func extractWavPcm(t *testing.T, fname string) []int16 {
bytes, err := ioutil.ReadFile(fname)
if err != nil {
t.Fatalf("Error reading file data from %s: %v", fname, err)
}
const wavHeaderSize = 44
if (len(bytes)-wavHeaderSize)%2 == 1 {
t.Fatalf("Illegal wav data: payload must be encoded in byte pairs")
}
numSamples := (len(bytes) - wavHeaderSize) / 2
samples := make([]int16, numSamples)
for i := 0; i < numSamples; i++ {
samples[i] += int16(bytes[wavHeaderSize+i*2])
samples[i] += int16(bytes[wavHeaderSize+i*2+1]) << 8
}
return samples
}
func maxDiff(a []int16, b []int16) int32 {
if len(a) != len(b) {
return math.MaxInt16
}
var max int32 = 0
for i := range a {
d := int32(a[i]) - int32(b[i])
if d < 0 {
d = -d
}
if d > max {
max = d
}
}
return max
}
func TestStream(t *testing.T) {
opuspcm := opus2pcm(t, "testdata/speech_8.opus", 10000)
wavpcm := extractWavPcm(t, "testdata/speech_8.wav")
if len(opuspcm) != len(wavpcm) {
t.Fatalf("Unexpected length of decoded opus file: %d (.wav: %d)", len(opuspcm), len(wavpcm))
}
d := maxDiff(opuspcm, wavpcm)
// No science behind this number
const epsilon = 12
if d > epsilon {
t.Errorf("Maximum difference between decoded streams too high: %d", d)
}
}
func TestStreamSmallBuffer(t *testing.T) {
smallbuf := opus2pcm(t, "testdata/speech_8.opus", 1)
bigbuf := opus2pcm(t, "testdata/speech_8.opus", 10000)
if !reflect.DeepEqual(smallbuf, bigbuf) {
t.Errorf("Reading with 1-sample buffer size yields different audio data")
}
}
type mockCloser struct {
io.Reader
closed bool
}
func (m *mockCloser) Close() error {
if m.closed {
return fmt.Errorf("Already closed")
}
m.closed = true
return nil
}
func TestCloser(t *testing.T) {
f := mustOpenFile(t, "testdata/speech_8.opus")
mc := &mockCloser{Reader: f}
stream := mustOpenStream(t, mc)
stream.Close()
if !mc.closed {
t.Error("Expected opus stream to call .Close on the reader")
}
}