Kirika/vector/audio_nocgo.go
DataHoarder 514a88aec1
Some checks failed
continuous-integration/drone/push Build is failing
Update to Go 1.20
2023-04-09 13:10:30 +02:00

369 lines
8.1 KiB
Go

//go:build !cgo
package vector
import (
"encoding/binary"
"golang.org/x/exp/slices"
"math"
"runtime"
"unsafe"
)
func bitsToDiv(b int) float32 {
return float32((int(1) << (b - 1)) - 1)
}
// MultipleChannelsToMonoFloat32 bring any number of channels to mono, equally weighted
func MultipleChannelsToMonoFloat32(buffer []float32, channels int) (buf []float32) {
buf = make([]float32, len(buffer)/channels)
for i := 0; i < len(buffer); i += channels {
f := buffer[i]
for j := 1; j < channels; j++ {
f += buffer[i+j]
}
buf[i/channels] = f / float32(channels)
}
return
}
// MultipleChannelsToStereoFloat32 bring any number of channels to stereo, using downmix formulas when necessary
func MultipleChannelsToStereoFloat32(buffer []float32, channels int) (buf []float32) {
if channels != 2 {
buf = make([]float32, (len(buffer)/channels)*2)
}
var samples int
surroundMix := 1 / float32(math.Sqrt(2))
switch channels {
case 1: //mono, duplicate channels
for i := 0; i < len(buffer); i++ {
buf[i*2] = buffer[i]
buf[i*2+1] = buffer[i]
}
break
case 2: //copy
buf = slices.Clone(buffer)
break
case 3: //2.1, FL, FR, LFE
for i := 0; i < len(buffer); i += 3 {
FL := i
FR := i + 1
//LFE := i + 2
buf[samples*2] = buffer[FL]
buf[samples*2+1] = buffer[FR]
samples++
}
case 5: //5.0, FL, FR, FC, RL, RR
for i := 0; i < len(buffer); i += 5 {
FL := i
FR := i + 1
C := i + 2
RL := i + 3
RR := i + 4
//TODO: this is wrong
buf[samples*2] = buffer[FL] + surroundMix*buffer[C] + surroundMix*buffer[RL]
buf[samples*2+1] = buffer[FR] + surroundMix*buffer[C] + surroundMix*buffer[RR]
samples++
}
case 6: //5.1, FL, FR, FC, LFE, RL, RR
for i := 0; i < len(buffer); i += 6 {
FL := i
FR := i + 1
C := i + 2
//LFE := i + 3
RL := i + 4
RR := i + 5
//TODO: this is wrong
buf[samples*2] = buffer[FL] + surroundMix*buffer[C] + surroundMix*buffer[RL]
buf[samples*2+1] = buffer[FR] + surroundMix*buffer[C] + surroundMix*buffer[RR]
samples++
}
break
default: //no known formula, just take stereo out of it
for i := 0; i < len(buffer); i += channels {
buf[samples*2] = buffer[i]
buf[samples*2+1] = buffer[i+1]
samples++
}
}
return
}
// MultipleChannelsToMonoInt32 bring any number of channels to mono, equally weighted
func MultipleChannelsToMonoInt32(buffer []int32, channels int) (buf []int32) {
buf = make([]int32, len(buffer)/channels)
for i := 0; i < len(buffer); i += channels {
f := int64(buffer[i])
for j := 1; j < channels; j++ {
f += int64(buffer[i+j])
}
buf[i/channels] = int32(f / int64(channels))
}
return
}
// MultipleChannelsToStereoInt32 bring any number of channels to stereo, using downmix formulas when necessary
func MultipleChannelsToStereoInt32(buffer []int32, channels int) (buf []int32) {
if channels != 2 {
buf = make([]int32, (len(buffer)/channels)*2)
}
var samples int
surroundMix := 1 / float32(math.Sqrt(2))
switch channels {
case 1: //mono, duplicate channels
for i := 0; i < len(buffer); i++ {
buf[i*2] = buffer[i]
buf[i*2+1] = buffer[i]
}
break
case 2: //copy
buf = slices.Clone(buffer)
break
case 3: //2.1, FL, FR, LFE
for i := 0; i < len(buffer); i += 3 {
FL := i
FR := i + 1
//LFE := i + 2
buf[samples*2] = buffer[FL]
buf[samples*2+1] = buffer[FR]
samples++
}
case 5: //5.0, FL, FR, FC, RL, RR
for i := 0; i < len(buffer); i += 5 {
FL := i
FR := i + 1
C := i + 2
RL := i + 3
RR := i + 4
//TODO: this is wrong
buf[samples*2] = int32(int64(buffer[FL]) + int64(surroundMix*float32(buffer[C])+surroundMix*float32(buffer[RL])))
buf[samples*2+1] = int32(int64(buffer[FR]) + int64(surroundMix*float32(buffer[C])+surroundMix*float32(buffer[RR])))
samples++
}
case 6: //5.1, FL, FR, FC, LFE, RL, RR
for i := 0; i < len(buffer); i += 6 {
FL := i
FR := i + 1
C := i + 2
//LFE := i + 3
RL := i + 4
RR := i + 5
//TODO: this is wrong
buf[samples*2] = int32(int64(buffer[FL]) + int64(surroundMix*float32(buffer[C])+surroundMix*float32(buffer[RL])))
buf[samples*2+1] = int32(int64(buffer[FR]) + int64(surroundMix*float32(buffer[C])+surroundMix*float32(buffer[RR])))
samples++
}
break
default: //no known formula, just take stereo out of it
for i := 0; i < len(buffer); i += channels {
buf[samples*2] = buffer[i]
buf[samples*2+1] = buffer[i+1]
samples++
}
}
return
}
func Int32ToInt16(data []int32, bitDepth int) (buf []int16) {
buf = make([]int16, len(data))
diff := bitDepth - 16
if diff >= 0 {
for i := range data {
buf[i] = int16(data[i] >> diff)
}
} else {
diff = -diff
for i := range data {
buf[i] = int16(data[i] << diff)
}
}
return buf
}
func Int32ToBytes(data []int32, bitDepth int) (buf []byte) {
buf = make([]byte, len(data)*(bitDepth/8))
//element size in bytes, rounded up
switch bitDepth {
case 8:
for i := range data {
buf[i] = byte(data[i])
}
break
case 16:
for i := range data {
binary.LittleEndian.PutUint16(buf[i*2:], uint16(int16(data[i])))
}
break
case 24:
var tmp [4]byte
for i := range data {
binary.LittleEndian.PutUint32(tmp[:], uint32(data[i]))
copy(buf[i*3:], tmp[:3])
}
break
case 32:
buf = slices.Clone(unsafe.Slice((*byte)(unsafe.Pointer(unsafe.SliceData(data))), len(data)*4))
runtime.KeepAlive(data)
break
}
return buf
}
func BytesToInt32(data []byte, bitDepth int) (buf []int32) {
buf = make([]int32, len(data)/(bitDepth/8))
switch bitDepth {
case 8:
for i := 0; i < len(data); i++ {
buf[i] = int32(data[i])
}
break
case 16:
for i := 0; i < len(data); i += 2 {
buf[i/2] = int32(int16(binary.LittleEndian.Uint16(data[i : i+2])))
}
break
case 24:
{
var sample uint32
for i := 0; i < len(data); i += 3 {
sample = uint32(data[i])
sample += uint32(data[i+1]) << 8
sample += uint32(data[i+2]) << 16
/*if sample > (1 << 23) {
sample = -((1 << 24) - sample)
}*/
//sign extend
buf[i/3] = int32(sample<<8) >> 8
}
}
break
case 32:
buf = slices.Clone(unsafe.Slice((*int32)(unsafe.Pointer(unsafe.SliceData(data))), len(data)/4))
runtime.KeepAlive(data)
break
}
return
}
func Int32ToFloat32(data []int32, bitDepth int) (buf []float32) {
buf = make([]float32, len(data))
for i := 0; i < len(data); i++ {
buf[i] = float32(data[i]) / bitsToDiv(bitDepth)
}
return
}
// Int24ToFloat32 special case
func Int24ToFloat32(data []byte, bitDepth int) (buf []float32) {
buf = make([]float32, len(data)/3)
var sample uint32
for i := 0; i < len(data); i += 3 {
sample = uint32(data[i])
sample += uint32(data[i+1]) << 8
sample += uint32(data[i+2]) << 16
//sign extend
buf[i/3] = (float32(int32(sample<<8) >> 8)) / bitsToDiv(bitDepth)
}
return
}
func Int16ToFloat32(data []int16, bitDepth int) (buf []float32) {
buf = make([]float32, len(data))
for i := 0; i < len(data); i++ {
buf[i] = float32(data[i]) / bitsToDiv(bitDepth)
}
return
}
func Int8ToFloat32(data []int8, bitDepth int) (buf []float32) {
buf = make([]float32, len(data))
for i := 0; i < len(data); i++ {
buf[i] = float32(data[i]) / bitsToDiv(bitDepth)
}
return
}
func Float32ToInt32(data []float32, bitDepth int) (buf []int32) {
buf = make([]int32, len(data))
for i := 0; i < len(data); i++ {
f := data[i]
if f < -1.0 {
f = -1.0
}
if f > 1.0 {
f = 1.0
}
buf[i] = int32(f * bitsToDiv(bitDepth))
}
return
}
func Float32ToInt24(data []float32) (buf []byte) {
buf = make([]byte, len(data)*3)
for i := 0; i < len(data); i++ {
f := data[i]
if f < -1.0 {
f = -1.0
}
if f > 1.0 {
f = 1.0
}
value := int32(f * bitsToDiv(24))
buf[i*3] = byte(value & 0xFF)
buf[i*3+1] = byte((value >> 8) & 0xFF)
buf[i*3+2] = byte((value >> 16) & 0xFF)
}
return
}
func Float32ToInt16(data []float32) (buf []int16) {
buf = make([]int16, len(data))
for i := 0; i < len(data); i++ {
f := data[i]
if f < -1.0 {
f = -1.0
}
if f > 1.0 {
f = 1.0
}
buf[i] = int16(f * bitsToDiv(16))
}
return
}
func Float32ToInt8(data []float32) (buf []int8) {
buf = make([]int8, len(data))
for i := 0; i < len(data); i++ {
f := data[i]
if f < -1.0 {
f = -1.0
}
if f > 1.0 {
f = 1.0
}
buf[i] = int8(f * bitsToDiv(8))
}
return
}