Skip to content
This repository was archived by the owner on Mar 18, 2024. It is now read-only.

Commit aaa862f

Browse files
authored
Merge pull request #1 from gotracker/alloc-reductions-and-go1.18
Upgrade to go 1.18 and reduce memory allocs
2 parents e1ce73a + 0e1a5d4 commit aaa862f

File tree

11 files changed

+400
-154
lines changed

11 files changed

+400
-154
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module github.com/gotracker/gomixing
22

3-
go 1.15
3+
go 1.18

mixing/mixbuffer.go

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ import (
99
"github.com/gotracker/gomixing/volume"
1010
)
1111

12-
// ChannelMixBuffer is a single channel's premixed volume data
13-
type ChannelMixBuffer volume.Matrix
14-
1512
// SampleMixIn is the parameters for mixing in a sample into a MixBuffer
1613
type SampleMixIn struct {
1714
Sample sampling.Sampler
@@ -24,7 +21,7 @@ type SampleMixIn struct {
2421
// MixBuffer is a buffer of premixed volume data intended to
2522
// be eventually sent out to the sound output device after
2623
// conversion to the output format
27-
type MixBuffer []ChannelMixBuffer
24+
type MixBuffer []volume.Matrix
2825

2926
// C returns a channel and a function that flushes any outstanding mix-ins and closes the channel
3027
func (m *MixBuffer) C() (chan<- SampleMixIn, func()) {
@@ -46,39 +43,35 @@ func (m *MixBuffer) C() (chan<- SampleMixIn, func()) {
4643
func (m *MixBuffer) MixInSample(d SampleMixIn) {
4744
pos := d.MixPos
4845
for i := 0; i < d.MixLen; i++ {
49-
sdata := d.Sample.GetSample()
50-
samp := sdata.ApplyInSitu(d.StaticVol)
51-
mixed := d.VolMatrix.Apply(samp...)
52-
for c, s := range mixed {
53-
(*m)[c][pos] += s
54-
}
46+
dry := d.Sample.GetSample()
47+
samp := dry.Apply(d.StaticVol)
48+
mixed := d.VolMatrix.ApplyToMatrix(samp)
49+
(*m)[pos].Accumulate(mixed)
5550
pos++
5651
d.Sample.Advance()
5752
}
5853
}
5954

6055
// Add will mix in another MixBuffer's data
61-
func (m *MixBuffer) Add(pos int, rhs MixBuffer, volMtx volume.Matrix) {
62-
sdata := make(volume.Matrix, len(*m))
63-
for i := 0; i < len(rhs[0]); i++ {
64-
for c := 0; c < len(rhs); c++ {
65-
sdata[c] = rhs[c][i]
66-
}
67-
sd := volMtx.Apply(sdata...)
68-
for c, s := range sd {
69-
(*m)[c][pos+i] += s
70-
}
56+
func (m *MixBuffer) Add(pos int, rhs *MixBuffer, volMtx volume.Matrix) {
57+
maxLen := len(*rhs)
58+
for i := 0; i < maxLen; i++ {
59+
out := volMtx.ApplyToMatrix(volume.Matrix((*rhs)[i]))
60+
(*m)[pos+i].Accumulate(out)
7161
}
7262
}
7363

7464
// ToRenderData converts a mixbuffer into a byte stream intended to be
7565
// output to the output sound device
76-
func (m *MixBuffer) ToRenderData(samples int, bitsPerSample int, mixerVolume volume.Volume) []byte {
66+
func (m *MixBuffer) ToRenderData(samples int, bitsPerSample int, channels int, mixerVolume volume.Volume) []byte {
7767
writer := &bytes.Buffer{}
78-
for i := 0; i < samples; i++ {
79-
for _, buf := range *m {
80-
v := buf[i] * mixerVolume
81-
val := v.ToSample(bitsPerSample)
68+
writer.Grow(samples * ((bitsPerSample + 7) / 8) * channels)
69+
for _, samp := range *m {
70+
buf := samp.Apply(mixerVolume)
71+
var d volume.StaticMatrix
72+
buf.ToChannels(channels, d[:])
73+
for i := 0; i < channels; i++ {
74+
val := d[i].ToSample(bitsPerSample)
8275
_ = binary.Write(writer, binary.LittleEndian, val) // lint
8376
}
8477
}
@@ -92,10 +85,12 @@ func (m *MixBuffer) ToIntStream(outputChannels int, samples int, bitsPerSample i
9285
for c := range data {
9386
data[c] = make([]int32, samples)
9487
}
95-
for i := 0; i < samples; i++ {
96-
for c, buf := range *m {
97-
v := buf[i] * mixerVolume
98-
data[c][i] = v.ToIntSample(bitsPerSample)
88+
for i, samp := range *m {
89+
buf := samp.Apply(mixerVolume)
90+
var d volume.StaticMatrix
91+
buf.ToChannels(outputChannels, d[:])
92+
for c := 0; c < outputChannels; c++ {
93+
data[c][i] = d[c].ToIntSample(bitsPerSample)
9994
}
10095
}
10196
return data
@@ -107,8 +102,9 @@ func (m *MixBuffer) ToRenderDataWithBufs(outBuffers [][]byte, samples int, bitsP
107102
pos := 0
108103
onum := 0
109104
out := outBuffers[onum]
110-
for i := 0; i < samples; i++ {
111-
for _, buf := range *m {
105+
for _, samp := range *m {
106+
buf := samp.Apply(mixerVolume)
107+
for c := 0; c < buf.Channels; c++ {
112108
for pos >= len(out) {
113109
onum++
114110
if onum > len(outBuffers) {
@@ -117,8 +113,7 @@ func (m *MixBuffer) ToRenderDataWithBufs(outBuffers [][]byte, samples int, bitsP
117113
out = outBuffers[onum]
118114
pos = 0
119115
}
120-
v := buf[i] * mixerVolume
121-
val := v.ToSample(bitsPerSample)
116+
val := buf.StaticMatrix[c].ToSample(bitsPerSample)
122117
switch d := val.(type) {
123118
case int8:
124119
out[pos] = uint8(d)

mixing/mixer.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@ type Mixer struct {
1111
// NewMixBuffer returns a mixer buffer with a number of channels
1212
// of preallocated sample data
1313
func (m *Mixer) NewMixBuffer(samples int) MixBuffer {
14-
mb := make(MixBuffer, m.Channels)
15-
for i := range mb {
16-
mb[i] = make(ChannelMixBuffer, samples)
17-
}
18-
return mb
14+
return make(MixBuffer, samples)
1915
}
2016

2117
// GetDefaultMixerVolume returns the default mixer volume value based on the number of mixed channels
@@ -34,13 +30,13 @@ func (m *Mixer) Flatten(panmixer PanMixer, samplesLen int, row []ChannelData, mi
3430
cdata.Flush()
3531
}
3632
if len(cdata.Data) > 0 {
37-
volMtx := cdata.Volume.Apply(panmixer.GetMixingMatrix(cdata.Pan)...)
38-
data.Add(pos, cdata.Data, volMtx)
33+
volMtx := panmixer.GetMixingMatrix(cdata.Pan).Apply(cdata.Volume)
34+
data.Add(pos, &cdata.Data, volMtx)
3935
}
4036
pos += cdata.SamplesLen
4137
}
4238
}
43-
return data.ToRenderData(samplesLen, m.BitsPerSample, mixerVolume)
39+
return data.ToRenderData(samplesLen, m.BitsPerSample, m.Channels, mixerVolume)
4440
}
4541

4642
// FlattenToInts runs a flatten on the channel data into separate channel data of int32 variety
@@ -54,13 +50,13 @@ func (m *Mixer) FlattenToInts(panmixer PanMixer, samplesLen int, row []ChannelDa
5450
cdata.Flush()
5551
}
5652
if len(cdata.Data) > 0 {
57-
volMtx := cdata.Volume.Apply(panmixer.GetMixingMatrix(cdata.Pan)...)
58-
data.Add(pos, cdata.Data, volMtx)
53+
volMtx := panmixer.GetMixingMatrix(cdata.Pan).Apply(cdata.Volume)
54+
data.Add(pos, &cdata.Data, volMtx)
5955
}
6056
pos += cdata.SamplesLen
6157
}
6258
}
63-
return data.ToIntStream(panmixer.Channels(), samplesLen, m.BitsPerSample, mixerVolume)
59+
return data.ToIntStream(panmixer.NumChannels(), samplesLen, m.BitsPerSample, mixerVolume)
6460
}
6561

6662
// FlattenTo will to a final saturation mix of all the row's channel data into a single output buffer
@@ -77,8 +73,8 @@ func (m *Mixer) FlattenTo(resultBuffers [][]byte, panmixer PanMixer, samplesLen
7773
maxLen = cdata.SamplesLen
7874
}
7975
if len(cdata.Data) > 0 {
80-
volMtx := cdata.Volume.Apply(panmixer.GetMixingMatrix(cdata.Pan)...)
81-
data.Add(pos, cdata.Data, volMtx)
76+
volMtx := panmixer.GetMixingMatrix(cdata.Pan).Apply(cdata.Volume)
77+
data.Add(pos, &cdata.Data, volMtx)
8278
}
8379
}
8480
pos += maxLen

mixing/panmixer.go

Lines changed: 1 addition & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,14 @@
11
package mixing
22

33
import (
4-
"math"
5-
64
"github.com/gotracker/gomixing/panning"
75
"github.com/gotracker/gomixing/volume"
86
)
97

108
// PanMixer is a mixer that's specialized for mixing multichannel audio content
119
type PanMixer interface {
1210
GetMixingMatrix(panning.Position) volume.Matrix
13-
Channels() int
14-
}
15-
16-
var (
17-
// PanMixerMono is a mixer that's specialized for mixing monaural audio content
18-
PanMixerMono PanMixer = &panMixerMono{}
19-
20-
// PanMixerStereo is a mixer that's specialized for mixing stereo audio content
21-
PanMixerStereo PanMixer = &panMixerStereo{}
22-
23-
// PanMixerQuad is a mixer that's specialized for mixing quadraphonic audio content
24-
PanMixerQuad PanMixer = &panMixerQuad{}
25-
)
26-
27-
type panMixerMono struct {
28-
PanMixer
29-
}
30-
31-
func (p panMixerMono) GetMixingMatrix(pan panning.Position) volume.Matrix {
32-
// distance and angle are ignored on mono
33-
return volume.Matrix{1.0}
34-
}
35-
36-
func (p panMixerMono) Channels() int {
37-
return 1
38-
}
39-
40-
type panMixerStereo struct {
41-
PanMixer
42-
}
43-
44-
func (p panMixerStereo) GetMixingMatrix(pan panning.Position) volume.Matrix {
45-
pangle := float64(pan.Angle)
46-
s, c := math.Sincos(pangle)
47-
var d volume.Volume
48-
if pan.Distance > 0 {
49-
d = 1 / volume.Volume(pan.Distance*pan.Distance)
50-
}
51-
l := d * volume.Volume(s)
52-
r := d * volume.Volume(c)
53-
return volume.Matrix{l, r}
54-
}
55-
56-
func (p panMixerStereo) Channels() int {
57-
return 2
58-
}
59-
60-
type panMixerQuad struct {
61-
PanMixer
62-
}
63-
64-
func (p panMixerQuad) GetMixingMatrix(pan panning.Position) volume.Matrix {
65-
pangle := float64(pan.Angle)
66-
sf, cf := math.Sincos(pangle)
67-
sr, cr := math.Sin(pangle+math.Pi/2.0), math.Cos(pangle-math.Pi/2.0)
68-
var d volume.Volume
69-
if pan.Distance > 0 {
70-
d = 1 / volume.Volume(pan.Distance*pan.Distance)
71-
}
72-
lf := d * volume.Volume(sf)
73-
rf := d * volume.Volume(cf)
74-
lr := d * volume.Volume(cr)
75-
rr := d * volume.Volume(sr)
76-
return volume.Matrix{lf, rf, lr, rr}
77-
}
78-
79-
func (p panMixerQuad) Channels() int {
80-
return 4
11+
NumChannels() int
8112
}
8213

8314
// GetPanMixer returns the panning mixer that can generate a matrix

mixing/panmixer_mono.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package mixing
2+
3+
import (
4+
"github.com/gotracker/gomixing/panning"
5+
"github.com/gotracker/gomixing/volume"
6+
)
7+
8+
// PanMixerMono is a mixer that's specialized for mixing monaural audio content
9+
var PanMixerMono PanMixer = &panMixerMono{}
10+
11+
type panMixerMono volume.Matrix
12+
13+
func (p panMixerMono) GetMixingMatrix(pan panning.Position) volume.Matrix {
14+
// distance and angle are ignored on mono
15+
return volume.Matrix{
16+
StaticMatrix: volume.StaticMatrix{1.0},
17+
Channels: 1,
18+
}
19+
}
20+
21+
func (p panMixerMono) NumChannels() int {
22+
return p.Channels
23+
}

mixing/panmixer_quad.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package mixing
2+
3+
import (
4+
"math"
5+
6+
"github.com/gotracker/gomixing/panning"
7+
"github.com/gotracker/gomixing/volume"
8+
)
9+
10+
// PanMixerQuad is a mixer that's specialized for mixing quadraphonic audio content
11+
var PanMixerQuad PanMixer = &panMixerQuad{}
12+
13+
type panMixerQuad volume.Matrix
14+
15+
func (p panMixerQuad) GetMixingMatrix(pan panning.Position) volume.Matrix {
16+
pangle := float64(pan.Angle)
17+
sf, cf := math.Sincos(pangle)
18+
sr, cr := math.Sin(pangle+math.Pi/2.0), math.Cos(pangle-math.Pi/2.0)
19+
var d volume.Volume
20+
if pan.Distance > 0 {
21+
d = 1 / volume.Volume(pan.Distance*pan.Distance)
22+
}
23+
lf := d * volume.Volume(sf)
24+
rf := d * volume.Volume(cf)
25+
lr := d * volume.Volume(cr)
26+
rr := d * volume.Volume(sr)
27+
return volume.Matrix{
28+
StaticMatrix: volume.StaticMatrix{lf, rf, lr, rr},
29+
Channels: 4,
30+
}
31+
}
32+
33+
func (p panMixerQuad) NumChannels() int {
34+
return p.Channels
35+
}

mixing/panmixer_stereo.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package mixing
2+
3+
import (
4+
"math"
5+
6+
"github.com/gotracker/gomixing/panning"
7+
"github.com/gotracker/gomixing/volume"
8+
)
9+
10+
// PanMixerStereo is a mixer that's specialized for mixing stereo audio content
11+
var PanMixerStereo PanMixer = &panMixerStereo{}
12+
13+
type panMixerStereo volume.Matrix
14+
15+
func (p panMixerStereo) GetMixingMatrix(pan panning.Position) volume.Matrix {
16+
pangle := float64(pan.Angle)
17+
s, c := math.Sincos(pangle)
18+
var d volume.Volume
19+
if pan.Distance > 0 {
20+
d = 1 / volume.Volume(pan.Distance*pan.Distance)
21+
}
22+
l := d * volume.Volume(s)
23+
r := d * volume.Volume(c)
24+
return volume.Matrix{
25+
StaticMatrix: volume.StaticMatrix{l, r},
26+
Channels: 2,
27+
}
28+
}
29+
30+
func (p panMixerStereo) NumChannels() int {
31+
return p.Channels
32+
}

sampling/samplerimpl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func (s *sampler) Advance() {
1919

2020
func (s *sampler) GetSample() volume.Matrix {
2121
if s.ss == nil {
22-
return nil
22+
return volume.Matrix{}
2323
}
2424
return s.ss.GetSample(s.pos)
2525
}

0 commit comments

Comments
 (0)