Files
mediadevices/pkg/io/audio/buffer.go
2020-10-29 00:04:12 -07:00

90 lines
2.2 KiB
Go

package audio
import (
"errors"
"github.com/pion/mediadevices/pkg/wave"
)
var errUnsupported = errors.New("unsupported audio format")
// NewBuffer creates audio transform to buffer signal to have exact nSample samples.
func NewBuffer(nSamples int) TransformFunc {
var inBuff wave.Audio
return func(r Reader) Reader {
return ReaderFunc(func() (wave.Audio, func(), error) {
for {
if inBuff != nil && inBuff.ChunkInfo().Len >= nSamples {
break
}
buff, _, err := r.Read()
if err != nil {
return nil, func() {}, err
}
switch b := buff.(type) {
case *wave.Float32Interleaved:
ib, ok := inBuff.(*wave.Float32Interleaved)
if !ok || ib.Size.Channels != b.Size.Channels {
ib = wave.NewFloat32Interleaved(
wave.ChunkInfo{
SamplingRate: b.Size.SamplingRate,
Channels: b.Size.Channels,
Len: nSamples,
},
)
ib.Data = ib.Data[:0]
ib.Size.Len = 0
inBuff = ib
}
ib.Data = append(ib.Data, b.Data...)
ib.Size.Len += b.Size.Len
case *wave.Int16Interleaved:
ib, ok := inBuff.(*wave.Int16Interleaved)
if !ok || ib.Size.Channels != b.Size.Channels {
ib = wave.NewInt16Interleaved(
wave.ChunkInfo{
SamplingRate: b.Size.SamplingRate,
Channels: b.Size.Channels,
Len: nSamples,
},
)
ib.Data = ib.Data[:0]
ib.Size.Len = 0
inBuff = ib
}
ib.Data = append(ib.Data, b.Data...)
ib.Size.Len += b.Size.Len
default:
return nil, func() {}, errUnsupported
}
}
switch ib := inBuff.(type) {
case *wave.Int16Interleaved:
ibCopy := *ib
ibCopy.Size.Len = nSamples
n := nSamples * ib.Size.Channels
ibCopy.Data = make([]int16, n)
copy(ibCopy.Data, ib.Data)
ib.Data = ib.Data[n:]
ib.Size.Len -= nSamples
return &ibCopy, func() {}, nil
case *wave.Float32Interleaved:
ibCopy := *ib
ibCopy.Size.Len = nSamples
n := nSamples * ib.Size.Channels
ibCopy.Data = make([]float32, n)
copy(ibCopy.Data, ib.Data)
ib.Data = ib.Data[n:]
ib.Size.Len -= nSamples
return &ibCopy, func() {}, nil
}
return nil, func() {}, errUnsupported
})
}
}