135 lines
3.2 KiB
Go
135 lines
3.2 KiB
Go
// Copyright © Go Opus Authors (see AUTHORS file)
|
|
//
|
|
// License for use of this code is detailed in the LICENSE file
|
|
|
|
// +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")
|
|
}
|
|
}
|