2022-07-22 09:39:58 +00:00
|
|
|
package audio
|
|
|
|
|
|
|
|
import (
|
|
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/vector"
|
2022-09-05 14:57:17 +00:00
|
|
|
"sync/atomic"
|
2022-07-22 09:39:58 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type int32Source struct {
|
|
|
|
BitDepth int
|
|
|
|
SampleRate int
|
|
|
|
Channels int
|
|
|
|
Blocks chan []int32
|
2022-09-05 14:57:17 +00:00
|
|
|
locked atomic.Bool
|
2022-07-22 09:39:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func newInt32Source(bitDepth, sampleRate, channels int) TypedSource[int32] {
|
|
|
|
if bitDepth <= 0 || bitDepth > 32 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return &int32Source{
|
|
|
|
BitDepth: bitDepth,
|
|
|
|
SampleRate: sampleRate,
|
|
|
|
Channels: channels,
|
|
|
|
Blocks: make(chan []int32),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) Split(n int) []Source {
|
|
|
|
return Split[int32](s, n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) New() TypedSource[int32] {
|
|
|
|
return newInt32Source(s.BitDepth, s.SampleRate, s.Channels)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) GetBlocks() chan []int32 {
|
|
|
|
if s.Locked() {
|
|
|
|
return nil
|
|
|
|
}
|
2022-09-05 14:57:17 +00:00
|
|
|
if !s.locked.Swap(true) {
|
|
|
|
return s.Blocks
|
|
|
|
}
|
|
|
|
return nil
|
2022-07-22 09:39:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) Close() {
|
|
|
|
close(s.Blocks)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) GetSampleRate() int {
|
|
|
|
return s.SampleRate
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) GetChannels() int {
|
|
|
|
return s.Channels
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) GetBitDepth() int {
|
|
|
|
return s.BitDepth
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) Locked() bool {
|
2022-09-05 14:57:17 +00:00
|
|
|
return s.locked.Load()
|
2022-07-22 09:39:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) Unlock() {
|
2022-09-05 14:57:17 +00:00
|
|
|
s.locked.Store(false)
|
2022-07-22 09:39:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) SwapBlocks(blocks chan []int32) chan []int32 {
|
|
|
|
oldBlocks := s.Blocks
|
|
|
|
s.Blocks = blocks
|
|
|
|
return oldBlocks
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) GetFormat() SourceFormat {
|
|
|
|
return SourceInt32
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) ToInt16() TypedSource[int16] {
|
|
|
|
if s.Locked() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
source := newInt16Source(16, s.SampleRate, s.Channels)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
defer source.Close()
|
|
|
|
|
|
|
|
for block := range s.GetBlocks() {
|
|
|
|
source.IngestInt16(vector.Int32ToInt16(block, s.BitDepth), 16)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return source
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) ToInt32(bitDepth int) TypedSource[int32] {
|
|
|
|
if s.BitDepth == bitDepth {
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
source := newInt32Source(bitDepth, s.SampleRate, s.Channels)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
diff := s.BitDepth - bitDepth
|
|
|
|
defer source.Close()
|
|
|
|
|
|
|
|
if diff >= 0 {
|
|
|
|
for block := range s.GetBlocks() {
|
|
|
|
buf := make([]int32, len(block))
|
|
|
|
for i := range block {
|
|
|
|
buf[i] = block[i] >> diff
|
|
|
|
}
|
|
|
|
source.IngestInt32(buf, bitDepth)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
diff = -diff
|
|
|
|
for block := range s.GetBlocks() {
|
|
|
|
buf := make([]int32, len(block))
|
|
|
|
for i := range block {
|
|
|
|
buf[i] = block[i] << diff
|
|
|
|
}
|
|
|
|
source.IngestInt32(buf, bitDepth)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return source
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) ToFloat32() TypedSource[float32] {
|
|
|
|
if s.Locked() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
source := newFloat32Source(s.BitDepth, s.SampleRate, s.Channels)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
defer source.Close()
|
|
|
|
for block := range s.GetBlocks() {
|
|
|
|
source.IngestFloat32(vector.Int32ToFloat32(block, s.BitDepth))
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return source
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) IngestFloat32(buf []float32) {
|
|
|
|
s.Blocks <- vector.Float32ToInt32(buf, s.BitDepth)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) IngestInt8(buf []int8, bitDepth int) {
|
|
|
|
block := make([]int32, len(buf))
|
|
|
|
for i := range buf {
|
|
|
|
block[i] = int32(buf[i]) << (s.BitDepth - bitDepth)
|
|
|
|
}
|
|
|
|
s.Blocks <- block
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) IngestInt16(buf []int16, bitDepth int) {
|
|
|
|
block := make([]int32, len(buf))
|
|
|
|
for i := range buf {
|
|
|
|
block[i] = int32(buf[i]) << (s.BitDepth - bitDepth)
|
|
|
|
}
|
|
|
|
s.Blocks <- block
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) IngestInt24(buf []byte, bitDepth int) {
|
|
|
|
s.Blocks <- vector.BytesToInt32(buf, bitDepth)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) IngestInt32(buf []int32, bitDepth int) {
|
|
|
|
if bitDepth == s.BitDepth {
|
|
|
|
s.Blocks <- buf
|
|
|
|
} else {
|
|
|
|
block := make([]int32, len(buf))
|
|
|
|
for i := range buf {
|
|
|
|
block[i] = buf[i] << (s.BitDepth - bitDepth)
|
|
|
|
}
|
|
|
|
s.Blocks <- block
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *int32Source) IngestNative(buf []int32, bitDepth int) {
|
|
|
|
s.IngestInt32(buf, bitDepth)
|
|
|
|
}
|