go-pus/stream_test.go
DataHoarder c9b07c6bec
All checks were successful
continuous-integration/drone/push Build is passing
Added +build comment
2022-01-30 01:33:20 +01:00

136 lines
3.2 KiB
Go

// Copyright © Go Opus Authors (see AUTHORS file)
//
// License for use of this code is detailed in the LICENSE file
//go:build !nolibopusfile
// +build !nolibopusfile
package opus
import (
"fmt"
"io"
"io/ioutil"
"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 := mustOpenStream(t, reader)
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 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 = 18
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")
}
}