Files
mediadevices/pkg/driver/audiotest/dummy.go
2020-12-16 19:04:12 -05:00

105 lines
2.0 KiB
Go

// Package audiotest provides dummy audio driver for testing.
package audiotest
import (
"context"
"io"
"math"
"time"
"github.com/pion/mediadevices/pkg/driver"
"github.com/pion/mediadevices/pkg/io/audio"
"github.com/pion/mediadevices/pkg/prop"
"github.com/pion/mediadevices/pkg/wave"
)
func init() {
driver.GetManager().Register(
&dummy{}, driver.Info{Label: "AudioTest", DeviceType: driver.Microphone},
)
}
type dummy struct {
closed <-chan struct{}
cancel func()
}
func (d *dummy) Open() error {
ctx, cancel := context.WithCancel(context.Background())
d.closed = ctx.Done()
d.cancel = cancel
return nil
}
func (d *dummy) Close() error {
d.cancel()
return nil
}
func (d *dummy) AudioRecord(p prop.Media) (audio.Reader, error) {
var sin [100]float32
for i := range sin {
sin[i] = float32(math.Sin(2*math.Pi*float64(i)/100) * 0.25) // 480 Hz
}
if p.Latency == 0 {
p.Latency = 20 * time.Millisecond
}
nSample := int(uint64(p.SampleRate) * uint64(p.Latency) / uint64(time.Second))
nextReadTime := time.Now()
var phase int
closed := d.closed
reader := audio.ReaderFunc(func() (wave.Audio, func(), error) {
select {
case <-closed:
return nil, func() {}, io.EOF
default:
}
time.Sleep(nextReadTime.Sub(time.Now()))
nextReadTime = nextReadTime.Add(p.Latency)
a := wave.NewFloat32Interleaved(
wave.ChunkInfo{
Channels: p.ChannelCount,
Len: nSample,
SamplingRate: p.SampleRate,
},
)
for i := 0; i < nSample; i++ {
phase++
if phase >= 100 {
phase = 0
}
for ch := 0; ch < p.ChannelCount; ch++ {
a.SetFloat32(i, ch, wave.Float32Sample(sin[phase]))
}
}
return a, func() {}, nil
})
return reader, nil
}
func (d *dummy) Properties() []prop.Media {
return []prop.Media{
{
Audio: prop.Audio{
SampleRate: 48000,
Latency: time.Millisecond * 20,
ChannelCount: 1,
},
},
{
Audio: prop.Audio{
SampleRate: 48000,
Latency: time.Millisecond * 20,
ChannelCount: 2,
},
},
}
}