-
Notifications
You must be signed in to change notification settings - Fork 59
/
stream_test.go
134 lines (120 loc) · 3.17 KB
/
stream_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// 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")
}
}