av/revid/audio-input_test.go

145 lines
2.9 KiB
Go

package revid
import (
"bytes"
"errors"
"fmt"
"os"
"runtime"
"testing"
"time"
"bitbucket.org/ausocean/av/codec/codecutil"
"github.com/yobert/alsa"
)
// Check that a device exists with the given config parameters.
func checkDevice(ac *AudioConfig) error {
cards, err := alsa.OpenCards()
if err != nil {
return errors.New("no audio cards found")
}
defer alsa.CloseCards(cards)
var testDev *alsa.Device
for _, card := range cards {
devices, err := card.Devices()
if err != nil {
continue
}
for _, dev := range devices {
if dev.Type != alsa.PCM || !dev.Record {
continue
}
testDev = dev
break
}
}
if testDev == nil {
return errors.New("no suitable device found")
}
err = testDev.Open()
if err != nil {
return err
}
_, err = testDev.NegotiateChannels(2)
if err != nil {
return err
}
foundRate := false
for i := 0; i < len(Rates) && !foundRate; i++ {
if Rates[i] < ac.SampleRate {
continue
}
if Rates[i]%ac.SampleRate == 0 {
_, err = testDev.NegotiateRate(Rates[i])
if err == nil {
foundRate = true
}
}
}
if !foundRate {
_, err = testDev.NegotiateRate(defaultSampleRate)
if err != nil {
return err
}
}
var aFmt alsa.FormatType
switch ac.BitDepth {
case 16:
aFmt = alsa.S16_LE
case 32:
aFmt = alsa.S32_LE
default:
return errors.New("unsupported bitdepth")
}
_, err = testDev.NegotiateFormat(aFmt)
if err != nil {
return err
}
_, err = testDev.NegotiateBufferSize(8192, 16384)
if err != nil {
return err
}
if err = testDev.Prepare(); err != nil {
return err
}
if testDev != nil {
testDev.Close()
}
return nil
}
// rTestLogger implements a revid.Logger.
type rTestLogger struct{}
func (tl rTestLogger) SetLevel(level int8) {}
func (tl rTestLogger) Log(level int8, msg string, params ...interface{}) {
logLevels := [...]string{"Debug", "Info", "Warn", "Error", "", "", "Fatal"}
if level < -1 || level > 5 {
panic("Invalid log level")
}
if !silent {
fmt.Printf("%s: %s\n", logLevels[level+1], msg)
}
if level == 5 {
buf := make([]byte, 1<<16)
size := runtime.Stack(buf, true)
fmt.Printf("%s\n", string(buf[:size]))
os.Exit(1)
}
}
func TestAudioDevice(t *testing.T) {
// We want to open a device with a standard configuration.
ac := &AudioConfig{
SampleRate: 8000,
Channels: 1,
RecPeriod: 0.5,
BitDepth: 16,
Codec: ADPCM,
}
n := 2 // Number of periods to wait while recording.
// Skip if there are no suitable devices to test with.
err := checkDevice(ac)
if err != nil {
t.Skip(err)
}
// Create a new audioDevice, start, read/lex, and then stop it.
var l rTestLogger
ai, err := NewAudioDevice(ac, l)
if err != nil {
t.Error(err)
}
dst := bytes.NewBuffer(make([]byte, 0))
err = ai.Start()
if err != nil {
t.Error(err)
}
go codecutil.LexBytes(dst, ai, time.Duration(ac.RecPeriod*float64(time.Second)), ai.ChunkSize())
time.Sleep(time.Second * time.Duration(ac.RecPeriod) * time.Duration(n))
ai.Stop()
}