2019-11-11 09:25:47 +03:00
|
|
|
/*
|
|
|
|
NAME
|
2019-11-12 05:58:53 +03:00
|
|
|
alsa_test.go
|
2019-11-11 09:25:47 +03:00
|
|
|
|
|
|
|
AUTHOR
|
|
|
|
Trek Hopton <trek@ausocean.org>
|
2020-01-30 03:51:06 +03:00
|
|
|
Scott Barnard <scott@ausocean.org>
|
2019-11-11 09:25:47 +03:00
|
|
|
|
|
|
|
LICENSE
|
2020-01-30 03:51:06 +03:00
|
|
|
This file is Copyright (C) 2019-2020 the Australian Ocean Lab (AusOcean)
|
2019-11-11 09:25:47 +03:00
|
|
|
|
|
|
|
It is free software: you can redistribute it and/or modify them
|
|
|
|
under the terms of the GNU General Public License as published by the
|
|
|
|
Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
option) any later version.
|
|
|
|
|
|
|
|
It is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License in gpl.txt.
|
2019-11-12 08:35:01 +03:00
|
|
|
If not, see http://www.gnu.org/licenses.
|
2019-11-11 09:25:47 +03:00
|
|
|
*/
|
|
|
|
|
2020-03-12 08:26:29 +03:00
|
|
|
// Package alsa provides access to input from ALSA audio devices.
|
2019-11-12 05:58:53 +03:00
|
|
|
package alsa
|
2019-11-11 09:25:47 +03:00
|
|
|
|
|
|
|
import (
|
2020-01-30 03:51:06 +03:00
|
|
|
"bytes"
|
2019-11-11 09:25:47 +03:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"bitbucket.org/ausocean/av/codec/codecutil"
|
2019-11-13 12:26:13 +03:00
|
|
|
"bitbucket.org/ausocean/av/codec/pcm"
|
2019-11-11 09:25:47 +03:00
|
|
|
"bitbucket.org/ausocean/av/revid/config"
|
|
|
|
"bitbucket.org/ausocean/utils/logger"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestDevice(t *testing.T) {
|
|
|
|
// We want to open a device with a standard configuration.
|
|
|
|
c := config.Config{
|
|
|
|
SampleRate: 8000,
|
|
|
|
Channels: 1,
|
|
|
|
RecPeriod: 0.3,
|
|
|
|
BitDepth: 16,
|
|
|
|
InputCodec: codecutil.ADPCM,
|
|
|
|
}
|
|
|
|
n := 2 // Number of periods to wait while recording.
|
|
|
|
|
2019-11-11 15:10:13 +03:00
|
|
|
// Create a new ALSA device, start, read/lex, and then stop it.
|
2019-11-11 09:25:47 +03:00
|
|
|
l := logger.New(logger.Debug, os.Stderr, true)
|
2019-11-12 08:34:07 +03:00
|
|
|
ai := New(l)
|
2019-11-11 09:25:47 +03:00
|
|
|
err := ai.Set(c)
|
|
|
|
// If there was an error opening the device, skip this test.
|
|
|
|
if _, ok := err.(OpenError); ok {
|
|
|
|
t.Skip(err)
|
|
|
|
}
|
|
|
|
// For any other error, report it.
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
err = ai.Start()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
2019-11-13 12:26:13 +03:00
|
|
|
cs := pcm.DataSize(c.SampleRate, c.Channels, c.BitDepth, c.RecPeriod, c.InputCodec)
|
|
|
|
lexer, err := codecutil.NewByteLexer(cs)
|
2019-11-11 09:25:47 +03:00
|
|
|
go lexer.Lex(ioutil.Discard, ai, time.Duration(c.RecPeriod*float64(time.Second)))
|
|
|
|
time.Sleep(time.Duration(c.RecPeriod*float64(time.Second)) * time.Duration(n))
|
|
|
|
ai.Stop()
|
|
|
|
}
|
|
|
|
|
|
|
|
var powerTests = []struct {
|
|
|
|
in int
|
|
|
|
out int
|
|
|
|
}{
|
|
|
|
{36, 32},
|
|
|
|
{47, 32},
|
|
|
|
{3, 4},
|
|
|
|
{46, 32},
|
|
|
|
{7, 8},
|
|
|
|
{2, 2},
|
|
|
|
{36, 32},
|
|
|
|
{757, 512},
|
|
|
|
{2464, 2048},
|
|
|
|
{18980, 16384},
|
|
|
|
{70000, 65536},
|
|
|
|
{8192, 8192},
|
|
|
|
{2048, 2048},
|
|
|
|
{65536, 65536},
|
|
|
|
{-2048, 1},
|
|
|
|
{-127, 1},
|
|
|
|
{-1, 1},
|
|
|
|
{0, 1},
|
|
|
|
{1, 2},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNearestPowerOfTwo(t *testing.T) {
|
|
|
|
for _, tt := range powerTests {
|
|
|
|
t.Run(strconv.Itoa(tt.in), func(t *testing.T) {
|
|
|
|
v := nearestPowerOfTwo(tt.in)
|
|
|
|
if v != tt.out {
|
|
|
|
t.Errorf("got %v, want %v", v, tt.out)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2020-01-30 03:51:06 +03:00
|
|
|
|
|
|
|
func TestIsRunning(t *testing.T) {
|
2020-01-31 04:52:48 +03:00
|
|
|
const dur = 250 * time.Millisecond
|
|
|
|
const sampleRate = 1000
|
|
|
|
const channels = 1
|
|
|
|
const bitDepth = 16
|
|
|
|
const recPeriod = 1
|
|
|
|
|
2020-01-30 03:51:06 +03:00
|
|
|
l := logger.New(logger.Debug, &bytes.Buffer{}, true) // Discard logs.
|
|
|
|
d := New(l)
|
|
|
|
|
2020-01-31 04:52:48 +03:00
|
|
|
err := d.Set(config.Config{
|
|
|
|
SampleRate: sampleRate,
|
|
|
|
Channels: channels,
|
|
|
|
BitDepth: bitDepth,
|
|
|
|
RecPeriod: recPeriod,
|
2020-01-30 03:51:06 +03:00
|
|
|
InputCodec: codecutil.ADPCM,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Skipf("could not set device: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = d.Start()
|
|
|
|
if err != nil {
|
2020-01-31 06:32:45 +03:00
|
|
|
t.Fatalf("could not start device %w", err)
|
2020-01-30 03:51:06 +03:00
|
|
|
}
|
2020-01-31 04:52:48 +03:00
|
|
|
|
|
|
|
time.Sleep(dur)
|
|
|
|
|
2020-01-30 03:51:06 +03:00
|
|
|
if !d.IsRunning() {
|
|
|
|
t.Error("device isn't running, when it should be")
|
|
|
|
}
|
|
|
|
|
|
|
|
err = d.Stop()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err.Error())
|
|
|
|
}
|
2020-01-31 04:52:48 +03:00
|
|
|
|
|
|
|
time.Sleep(dur)
|
|
|
|
|
2020-01-30 03:51:06 +03:00
|
|
|
if d.IsRunning() {
|
|
|
|
t.Error("device is running, when it should not be")
|
|
|
|
}
|
|
|
|
}
|