ace/drivers/audio/wavfifo.go

94 lines
2.1 KiB
Go
Raw Permalink Normal View History

2022-09-28 06:14:26 +00:00
package audio
import (
"context"
"encoding/binary"
"io"
2022-10-02 10:50:08 +00:00
"time"
2022-09-28 06:14:26 +00:00
"github.com/pion/mediadevices/pkg/io/audio"
"github.com/pion/mediadevices/pkg/prop"
"github.com/pion/mediadevices/pkg/wave"
"github.com/sirupsen/logrus"
)
const (
DataChunkIDSize = 4
DataChunkSizeSize = 4
)
// BufferSize for pcm bytes
const BitsPerByte = 8
type PCMStreamDriver struct {
PCM <-chan []byte
BufferSizeByBytes uint16
WaveHeader *WavHeader
closed <-chan struct{}
cancel func()
}
func (w *PCMStreamDriver) Open() error {
ctx, cancel := context.WithCancel(context.Background())
w.closed = ctx.Done()
w.cancel = cancel
return nil
}
func (w *PCMStreamDriver) Close() error {
w.cancel()
return nil
}
func (w *PCMStreamDriver) Properties() []prop.Media {
logrus.Debugf("wave header: %v", w.WaveHeader)
return []prop.Media{
{
Audio: prop.Audio{
SampleRate: int(w.WaveHeader.SampleRate),
ChannelCount: int(w.WaveHeader.NumChannels),
SampleSize: int(w.WaveHeader.BitsPerSample),
Latency: w.WaveHeader.GetLatnecy(w.BufferSizeByBytes),
IsFloat: false, // just 8bit or 16bit with qemu
IsBigEndian: false, // qemu should be little endian
IsInterleaved: true,
},
},
}
}
func (w *PCMStreamDriver) AudioRecord(p prop.Media) (audio.Reader, error) {
logrus.Debug(p)
chunkInfo := wave.ChunkInfo{
Len: int(w.BufferSizeByBytes) / int(p.SampleSize/BitsPerByte),
Channels: p.ChannelCount,
SamplingRate: p.SampleRate,
}
reader := func() (wave.Audio, func(), error) {
a := wave.NewInt16Interleaved(chunkInfo)
2022-10-10 11:12:26 +00:00
ticker := time.NewTicker(p.Latency)
defer ticker.Stop()
2022-09-28 06:14:26 +00:00
select {
case <-w.closed:
return nil, func() {}, io.EOF
2022-10-02 10:50:08 +00:00
case pcmData := <-w.PCM:
2022-09-28 06:14:26 +00:00
copy(a.Data, bytesTo16BitSamples(pcmData[:]))
2022-10-10 11:12:26 +00:00
case <-ticker.C:
2022-10-02 10:50:08 +00:00
// no stuck
2022-09-28 06:14:26 +00:00
}
return a, func() {}, nil
}
return audio.ReaderFunc(reader), nil
}
func bytesTo16BitSamples(b []byte) []int16 {
samples := make([]int16, 0)
for i := 0; i < len(b); i += 2 {
2022-09-30 04:24:32 +00:00
sample := binary.LittleEndian.Uint16(b[i : i+2])
2022-09-28 06:14:26 +00:00
samples = append(samples, int16(sample))
}
return samples
}