package opus
import (
- "errors"
"fmt"
)
*/
import "C"
-var opusfileErrcodes = map[C.int]error{
- -1: errors.New("OP_FALSE"),
- -2: errors.New("OP_EOF"),
- -3: errors.New("OP_HOLE"),
- -128: errors.New("OP_EREAD"),
- -129: errors.New("OP_EFAULT"),
- -130: errors.New("OP_EIMPL"),
- -131: errors.New("OP_EINVAL"),
- -132: errors.New("OP_ENOTFORMAT"),
- -133: errors.New("OP_EBADHEADER"),
- -134: errors.New("OP_EVERSION"),
- -135: errors.New("OP_ENOTAUDIO"),
- -136: errors.New("OP_EBADPACKET"),
- -137: errors.New("OP_EBADLINK"),
- -138: errors.New("OP_ENOSEEK"),
- -139: errors.New("OP_EBADTIMESTAMP"),
-}
+type opusFileError int
+
+var opusfileErrcodes = map[C.int]error{}
+
+const (
+ ERR_OP_FALSE opusFileError = -1
+ ERR_OP_EOF = -2
+ ERR_OP_HOLE = -3
+ ERR_OP_EREAD = -128
+ ERR_OP_EFAULT = -129
+ ERR_OP_EIMPL = -130
+ ERR_OP_EINVAL = -131
+ ERR_OP_ENOTFORMAT = -132
+ ERR_OP_EBADHEADER = -133
+ ERR_OP_EVERSION = -134
+ ERR_OP_ENOTAUDIO = -135
+ ERR_OP_EBADPACKET = -136
+ ERR_OP_EBADLINK = -137
+ ERR_OP_ENOSEEK = -138
+ ERR_OP_EBADTIMESTAMP = -139
+)
-// opusfileerr maps libopusfile error codes to human readable strings
-func opusfileerr(code C.int) error {
- err, ok := opusfileErrcodes[code]
- if ok {
- return err
+func (i opusFileError) Error() string {
+ switch i {
+ case ERR_OP_FALSE:
+ return "OP_FALSE"
+ case ERR_OP_EOF:
+ return "OP_EOF"
+ case ERR_OP_HOLE:
+ return "OP_HOLE"
+ case ERR_OP_EREAD:
+ return "OP_EREAD"
+ case ERR_OP_EFAULT:
+ return "OP_EFAULT"
+ case ERR_OP_EIMPL:
+ return "OP_EIMPL"
+ case ERR_OP_EINVAL:
+ return "OP_EINVAL"
+ case ERR_OP_ENOTFORMAT:
+ return "OP_ENOTFORMAT"
+ case ERR_OP_EBADHEADER:
+ return "OP_EBADHEADER"
+ case ERR_OP_EVERSION:
+ return "OP_EVERSION"
+ case ERR_OP_ENOTAUDIO:
+ return "OP_ENOTAUDIO"
+ case ERR_OP_EBADPACKET:
+ return "OP_EBADPACKET"
+ case ERR_OP_EBADLINK:
+ return "OP_EBADLINK"
+ case ERR_OP_ENOSEEK:
+ return "OP_ENOSEEK"
+ case ERR_OP_EBADTIMESTAMP:
+ return "OP_EBADTIMESTAMP"
+ default:
+ return "libopus error: %d (unknown code)"
}
- return fmt.Errorf("libopus error: %d (unknown code)", int(code))
}
// opuserr translates libopus (not libopusfile) error codes to human readable
package opus
import (
- "bytes"
"fmt"
"io"
+ "io/ioutil"
"os"
+ "reflect"
"strings"
"testing"
)
}
}
-func readStreamWav(t *testing.T, stream *Stream, buffersize int) []byte {
- var buf bytes.Buffer
- pcm := make([]int16, buffersize)
+func readStreamPcm(t *testing.T, stream *Stream, buffersize int) []int16 {
+ var pcm []int16
+ pcmbuf := make([]int16, buffersize)
for {
- n, err := stream.Read(pcm)
+ n, err := stream.Read(pcmbuf)
switch err {
case io.EOF:
- return buf.Bytes()
+ return pcm
case nil:
break
default:
if n == 0 {
t.Fatal("Nil-error Read() must not return 0")
}
- for i := 0; i < n; i++ {
- buf.WriteByte(byte(pcm[i] & 0xff))
- buf.WriteByte(byte(pcm[i] >> 8))
- }
+ pcm = append(pcm, pcmbuf[:n]...)
}
}
return stream
}
-func readFileWav(t *testing.T, fname string, buffersize int) []byte {
+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 readStreamWav(t, stream, buffersize)
+ return readStreamPcm(t, stream, buffersize)
+}
+
+// Extract raw pcm data from .wav file
+func exctractWavPcm(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) {
- wav := readFileWav(t, "testdata/speech_8.opus", 10000)
- if len(wav) != 1036800 {
- t.Fatalf("Unexpected length of WAV file: %d", len(wav))
+ pcm := opus2pcm(t, "testdata/speech_8.opus", 10000)
+ if len(pcm) != 518400 {
+ t.Fatalf("Unexpected length of decoded opus file: %d", len(pcm))
}
+
}
func TestStreamSmallBuffer(t *testing.T) {
- smallbuf := readFileWav(t, "testdata/speech_8.opus", 1)
- bigbuf := readFileWav(t, "testdata/speech_8.opus", 10000)
- if !bytes.Equal(smallbuf, bigbuf) {
+ 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")
}
}