Kirika/audio/sink.go
DataHoarder 09f3cf3b56
All checks were successful
continuous-integration/drone/push Build is passing
Use generics to implement TypedSource[float32|int16|int32]
2022-07-22 12:07:01 +02:00

86 lines
1.9 KiB
Go

package audio
import (
"sync/atomic"
"time"
)
type Sink interface {
Process(source Source)
}
type NullSink struct {
Sink
}
func NewNullSink() *NullSink {
return &NullSink{}
}
func (n *NullSink) Process(source Source) {
if f32Source, ok := source.(TypedSource[float32]); ok {
for range f32Source.GetBlocks() {
}
} else if i16Source, ok := source.(TypedSource[int16]); ok {
for range i16Source.GetBlocks() {
}
} else if i32Source, ok := source.(TypedSource[int32]); ok {
for range i32Source.GetBlocks() {
}
} else {
for range source.ToFloat32().GetBlocks() {
}
}
}
type ForwardSink struct {
Sink
Target Sink
SamplesRead int64
Duration time.Duration
}
func NewForwardSink(target Sink) *ForwardSink {
return &ForwardSink{
Target: target,
}
}
func (n *ForwardSink) GetDuration() time.Duration {
return time.Duration(atomic.LoadInt64((*int64)(&n.Duration)))
}
func (n *ForwardSink) GetSamplesRead() int64 {
return atomic.LoadInt64(&n.SamplesRead)
}
func forwardSinkProcess[T AllowedSourceTypes](n *ForwardSink, source TypedSource[T]) {
processor := NewSource[T](source.GetBitDepth(), source.GetSampleRate(), source.GetChannels())
go func() {
defer processor.Close()
for block := range source.GetBlocks() {
atomic.AddInt64((*int64)(&n.Duration), int64((time.Second*time.Duration(len(block)/source.GetChannels()))/time.Duration(source.GetSampleRate())))
atomic.AddInt64(&n.SamplesRead, int64(len(block)/source.GetChannels()))
processor.IngestNative(block, source.GetBitDepth())
}
}()
n.Target.Process(processor)
}
func (n *ForwardSink) Process(source Source) {
if f32Source, ok := source.(TypedSource[float32]); ok {
forwardSinkProcess(n, f32Source)
} else if i16Source, ok := source.(TypedSource[int16]); ok {
forwardSinkProcess(n, i16Source)
} else if i32Source, ok := source.(TypedSource[int32]); ok {
forwardSinkProcess(n, i32Source)
} else {
forwardSinkProcess(n, source.ToFloat32())
}
}