Add int32 stereo/mono converters

This commit is contained in:
DataHoarder 2022-07-22 20:58:26 +02:00
parent 09f3cf3b56
commit 1d2effea75
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
7 changed files with 245 additions and 19 deletions

View file

@ -214,14 +214,24 @@ func (f StereoFilter) Process(source audio.Source) audio.Source {
return source
}
//TODO: make this for int16 and int32
outSource := audio.NewSource[float32](source.GetBitDepth(), source.GetSampleRate(), 2)
outSource := audio.NewTypedInterface(source, source.GetBitDepth(), source.GetSampleRate(), 2)
go func() {
defer outSource.Close()
for block := range source.ToFloat32().GetBlocks() {
outSource.IngestFloat32(vector.MultipleChannelsToStereo(block, source.GetChannels()))
if _, ok := source.(audio.TypedSource[int32]); ok {
for block := range source.ToInt32(source.GetBitDepth()).GetBlocks() {
outSource.IngestInt32(vector.MultipleChannelsToStereoInt32(block, source.GetChannels()), source.GetBitDepth())
}
} else if _, ok = source.(audio.TypedSource[int16]); ok {
for block := range source.ToInt32(source.GetBitDepth()).GetBlocks() {
outSource.IngestInt32(vector.MultipleChannelsToStereoInt32(block, source.GetChannels()), source.GetBitDepth())
}
} else {
for block := range source.ToFloat32().GetBlocks() {
outSource.IngestFloat32(vector.MultipleChannelsToStereoFloat32(block, source.GetChannels()))
}
}
}()
return outSource
@ -235,14 +245,24 @@ func (f MonoFilter) Process(source audio.Source) audio.Source {
return source
}
//TODO: make this for int16 and int32
outSource := audio.NewSource[float32](source.GetBitDepth(), source.GetSampleRate(), 1)
outSource := audio.NewTypedInterface(source, source.GetBitDepth(), source.GetSampleRate(), 1)
go func() {
defer outSource.Close()
for block := range source.ToFloat32().GetBlocks() {
outSource.IngestFloat32(vector.MultipleChannelsToMono(block, source.GetChannels()))
if _, ok := source.(audio.TypedSource[int32]); ok {
for block := range source.ToInt32(source.GetBitDepth()).GetBlocks() {
outSource.IngestInt32(vector.MultipleChannelsToMonoInt32(block, source.GetChannels()), source.GetBitDepth())
}
} else if _, ok = source.(audio.TypedSource[int16]); ok {
for block := range source.ToInt32(source.GetBitDepth()).GetBlocks() {
outSource.IngestInt32(vector.MultipleChannelsToMonoInt32(block, source.GetChannels()), source.GetBitDepth())
}
} else {
for block := range source.ToFloat32().GetBlocks() {
outSource.IngestFloat32(vector.MultipleChannelsToMonoFloat32(block, source.GetChannels()))
}
}
}()
return outSource

View file

@ -38,12 +38,12 @@ func NewAnalyzerChannel(source audio.Source, err error) (audio.Source, AnalyzerC
defer close(channel)
if _, ok := sources[1].(audio.TypedSource[float32]); ok {
for block := range sources[1].ToInt32(32).GetBlocks() {
for block := range sources[1].ToInt32(source.GetBitDepth()).GetBlocks() {
channel <- &AnalyzerPacket{
Samples: block,
Channels: source.GetChannels(),
SampleRate: source.GetSampleRate(),
BitDepth: 32,
BitDepth: source.GetBitDepth(),
}
}
} else {

View file

@ -53,6 +53,30 @@ func Split[T AllowedSourceTypes](s TypedSource[T], n int) (sources []Source) {
return
}
func NewTypedInterface(s Source, bitDepth, sampleRate, channels int) Source {
if _, ok := s.(TypedSource[float32]); ok {
return newFloat32Source(bitDepth, sampleRate, channels)
} else if _, ok = s.(TypedSource[int16]); ok {
return newInt16Source(bitDepth, sampleRate, channels)
} else if _, ok = s.(TypedSource[int32]); ok {
return newInt32Source(bitDepth, sampleRate, channels)
} else {
return newFloat32Source(bitDepth, sampleRate, channels)
}
}
func NewInterface(s Source) Source {
if f32Source, ok := s.(TypedSource[float32]); ok {
return f32Source.New()
} else if i16Source, ok := s.(TypedSource[int16]); ok {
return i16Source.New()
} else if i32Source, ok := s.(TypedSource[int32]); ok {
return i32Source.New()
} else {
return s.ToFloat32().New()
}
}
func GetBlocksInterface(s Source) interface{} {
if f32Source, ok := s.(TypedSource[float32]); ok {
return f32Source.GetBlocks()

View file

@ -23,8 +23,29 @@ void audio_multiple_channels_to_mono(float* restrict buffer, size_t buffer_len,
}
}
void audio_multiple_channels_to_mono_int32(int32_t* restrict buffer, size_t buffer_len, int32_t* restrict out, int channels) {
int64_t s;
switch(channels) {
case 1:
memcpy(out, buffer, sizeof(int32_t) * buffer_len);
break;
case 2:
for (int i = 0; i < buffer_len; i += 2){
out[i/2] = (int32_t)((((int64_t)buffer[i]) + ((int64_t)buffer[i+1])) / 2);
}
break;
default:
for (int i = 0; i < buffer_len; i += channels){
s = buffer[i];
for (int j = 1; j < channels; ++j) {
s += buffer[i + j];
}
out[i/channels] = (int32_t)(s / channels);
}
}
}
void audio_multiple_channels_to_stereo(float* restrict buffer, size_t buffer_len, float* restrict out, int channels) {
float f;
int samples = 0;
float surroundMix = 1 / sqrt(2);
switch(channels) {
@ -53,6 +74,7 @@ void audio_multiple_channels_to_stereo(float* restrict buffer, size_t buffer_len
int C = i+2;
int RL = i+3;
int RR = i+4;
//TODO: this is wrong
out[samples*2] = buffer[FL] + surroundMix * buffer[C] + surroundMix * buffer[RL];
out[samples*2+1] = buffer[FR] + surroundMix * buffer[C] + surroundMix * buffer[RR];
++samples;
@ -65,6 +87,7 @@ void audio_multiple_channels_to_stereo(float* restrict buffer, size_t buffer_len
int LFE = i+3;
int RL = i+4;
int RR = i+5;
//TODO: this is wrong
out[samples*2] = buffer[FL] + surroundMix * buffer[C] + surroundMix * buffer[RL];
out[samples*2+1] = buffer[FR] + surroundMix * buffer[C] + surroundMix * buffer[RR];
++samples;
@ -79,6 +102,62 @@ void audio_multiple_channels_to_stereo(float* restrict buffer, size_t buffer_len
}
}
void audio_multiple_channels_to_stereo_int32(int32_t* restrict buffer, size_t buffer_len, int32_t* restrict out, int channels) {
int samples = 0;
float surroundMix = 1 / sqrt(2);
switch(channels) {
case 1: //mono, duplicate channels
for (int i = 0; i < buffer_len; i++){
out[i*2] = buffer[i];
out[i*2+1] = buffer[i];
}
break;
case 2: //copy
memcpy(out, buffer, sizeof(int32_t) * buffer_len);
break;
case 3: //2.1, FL, FR, LFE
for (int i = 0; i < buffer_len; i += 3){
int FL = i;
int FR = i+1;
int LFE = i+2;
out[samples*2] = buffer[FL];
out[samples*2+1] = buffer[FR];
++samples;
}
case 5: //5.0, FL, FR, FC, RL, RR
for (int i = 0; i < buffer_len; i += 5){
int FL = i;
int FR = i+1;
int C = i+2;
int RL = i+3;
int RR = i+4;
//TODO: this is wrong
out[samples*2] = ((int64_t)buffer[FL]) + (int64_t)(surroundMix * buffer[C] + surroundMix * buffer[RL]);
out[samples*2+1] = ((int64_t)buffer[FR]) + (int64_t)(surroundMix * buffer[C] + surroundMix * buffer[RR]);
++samples;
}
case 6: //5.1, FL, FR, FC, LFE, RL, RR
for (int i = 0; i < buffer_len; i += 6){
int FL = i;
int FR = i+1;
int C = i+2;
int LFE = i+3;
int RL = i+4;
int RR = i+5;
//TODO: this is wrong
out[samples*2] = ((int64_t)buffer[FL]) + (int64_t)(surroundMix * buffer[C] + surroundMix * buffer[RL]);
out[samples*2+1] = ((int64_t)buffer[FR]) + (int64_t)(surroundMix * buffer[C] + surroundMix * buffer[RR]);
++samples;
}
break;
default: //no known formula, just take stereo out of it
for (int i = 0; i < buffer_len; i += channels){
out[samples*2] = buffer[i];
out[samples*2+1] = buffer[i+1];
++samples;
}
}
}
void audio_int32_to_int16(int32_t* restrict data, size_t data_len, int16_t* restrict buffer, int bitDepth){
switch(bitDepth) {

View file

@ -11,26 +11,46 @@ import (
"unsafe"
)
// MultipleChannelsToMono bring any number of channels to mono, equally weighted, reusing buffer backwards
func MultipleChannelsToMono(buffer []float32, channels int) (buf []float32) {
// MultipleChannelsToMonoFloat32 bring any number of channels to mono, equally weighted
func MultipleChannelsToMonoFloat32(buffer []float32, channels int) (buf []float32) {
buf = make([]float32, len(buffer)/channels)
C.audio_multiple_channels_to_mono((*C.float)(&buffer[0]), C.size_t(len(buffer)), (*C.float)(&buf[0]), C.int(channels))
return
}
// MultipleChannelsToStereo bring any number of channels to stereo, using downmix formulas when necessary
func MultipleChannelsToStereo(buffer []float32, channels int) (buf []float32) {
// MultipleChannelsToStereoFloat32 bring any number of channels to stereo, using downmix formulas when necessary
func MultipleChannelsToStereoFloat32(buffer []float32, channels int) (buf []float32) {
buf = make([]float32, (len(buffer)/channels)*2)
C.audio_multiple_channels_to_stereo((*C.float)(&buffer[0]), C.size_t(len(buffer)), (*C.float)(&buf[0]), C.int(channels))
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)
C.audio_multiple_channels_to_mono_int32((*C.int32_t)(&buffer[0]), C.size_t(len(buffer)), (*C.int32_t)(&buf[0]), C.int(channels))
return
}
// MultipleChannelsToStereoInt32 bring any number of channels to stereo, using downmix formulas when necessary
func MultipleChannelsToStereoInt32(buffer []int32, channels int) (buf []int32) {
buf = make([]int32, (len(buffer)/channels)*2)
C.audio_multiple_channels_to_stereo_int32((*C.int32_t)(&buffer[0]), C.size_t(len(buffer)), (*C.int32_t)(&buf[0]), C.int(channels))
return
}
func Int32ToInt16(data []int32, bitDepth int) (buf []int16) {
buf = make([]int16, len(data))
C.audio_int32_to_int16((*C.int32_t)(&data[0]), C.size_t(len(data)), (*C.int16_t)(unsafe.Pointer(&buf[0])), C.int(bitDepth))
return
}
func Int16ToInt32(data []int32, bitDepth int) (buf []int16) {
buf = make([]int16, len(data))
C.audio_int32_to_int16((*C.int32_t)(&data[0]), C.size_t(len(data)), (*C.int16_t)(unsafe.Pointer(&buf[0])), C.int(bitDepth))
return
}
func Int32ToBytes(data []int32, bitDepth int) (buf []byte) {
buf = make([]byte, len(data)*(bitDepth/8))
C.audio_int32_to_bytes((*C.int32_t)(&data[0]), C.size_t(len(data)), (*C.int8_t)(unsafe.Pointer(&buf[0])), C.int(bitDepth))

View file

@ -7,6 +7,10 @@ void audio_multiple_channels_to_mono(float* buffer, size_t buffer_len, float* ou
void audio_multiple_channels_to_stereo(float* buffer, size_t buffer_len, float* out, int channels);
void audio_multiple_channels_to_mono_int32(int32_t* buffer, size_t buffer_len, int32_t* out, int channels);
void audio_multiple_channels_to_stereo_int32(int32_t* buffer, size_t buffer_len, int32_t* out, int channels);
void audio_int32_to_int16(int32_t* restrict data, size_t data_len, int16_t* restrict buffer, int bitDepth);
void audio_int32_to_bytes(int32_t* restrict data, size_t data_len, int8_t* restrict buffer, int bitDepth);

View file

@ -12,8 +12,8 @@ func bitsToDiv(b int) float32 {
return float32((int(1) << (b - 1)) - 1)
}
// MultipleChannelsToMono bring any number of channels to mono, equally weighted, reusing buffer backwards
func MultipleChannelsToMono(buffer []float32, channels int) (buf []float32) {
// 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]
@ -26,8 +26,8 @@ func MultipleChannelsToMono(buffer []float32, channels int) (buf []float32) {
return
}
// MultipleChannelsToStereo bring any number of channels to stereo, using downmix formulas when necessary
func MultipleChannelsToStereo(buffer []float32, channels int) (buf []float32) {
// MultipleChannelsToStereoFloat32 bring any number of channels to stereo, using downmix formulas when necessary
func MultipleChannelsToStereoFloat32(buffer []float32, channels int) (buf []float32) {
buf = make([]float32, (len(buffer)/channels)*2)
var samples int
@ -59,6 +59,7 @@ func MultipleChannelsToStereo(buffer []float32, channels int) (buf []float32) {
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++
@ -71,6 +72,7 @@ func MultipleChannelsToStereo(buffer []float32, channels int) (buf []float32) {
//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++
@ -87,6 +89,83 @@ func MultipleChannelsToStereo(buffer []float32, channels int) (buf []float32) {
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) {
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
copy(buf, 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