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

Commit 817c2a1

Browse files
committed
Fix for channel conversion issues
1 parent aaa862f commit 817c2a1

File tree

7 files changed

+87
-180
lines changed

7 files changed

+87
-180
lines changed

mixing/mixbuffer.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func (m *MixBuffer) MixInSample(d SampleMixIn) {
5656
func (m *MixBuffer) Add(pos int, rhs *MixBuffer, volMtx volume.Matrix) {
5757
maxLen := len(*rhs)
5858
for i := 0; i < maxLen; i++ {
59-
out := volMtx.ApplyToMatrix(volume.Matrix((*rhs)[i]))
59+
out := volMtx.ApplyToMatrix((*rhs)[i])
6060
(*m)[pos+i].Accumulate(out)
6161
}
6262
}
@@ -68,10 +68,9 @@ func (m *MixBuffer) ToRenderData(samples int, bitsPerSample int, channels int, m
6868
writer.Grow(samples * ((bitsPerSample + 7) / 8) * channels)
6969
for _, samp := range *m {
7070
buf := samp.Apply(mixerVolume)
71-
var d volume.StaticMatrix
72-
buf.ToChannels(channels, d[:])
71+
d := buf.ToChannels(channels)
7372
for i := 0; i < channels; i++ {
74-
val := d[i].ToSample(bitsPerSample)
73+
val := d.StaticMatrix[i].ToSample(bitsPerSample)
7574
_ = binary.Write(writer, binary.LittleEndian, val) // lint
7675
}
7776
}
@@ -87,10 +86,9 @@ func (m *MixBuffer) ToIntStream(outputChannels int, samples int, bitsPerSample i
8786
}
8887
for i, samp := range *m {
8988
buf := samp.Apply(mixerVolume)
90-
var d volume.StaticMatrix
91-
buf.ToChannels(outputChannels, d[:])
89+
d := buf.ToChannels(outputChannels)
9290
for c := 0; c < outputChannels; c++ {
93-
data[c][i] = d[c].ToIntSample(bitsPerSample)
91+
data[c][i] = d.StaticMatrix[c].ToIntSample(bitsPerSample)
9492
}
9593
}
9694
return data

mixing/panmixer_mono.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
// PanMixerMono is a mixer that's specialized for mixing monaural audio content
99
var PanMixerMono PanMixer = &panMixerMono{}
1010

11-
type panMixerMono volume.Matrix
11+
type panMixerMono struct{}
1212

1313
func (p panMixerMono) GetMixingMatrix(pan panning.Position) volume.Matrix {
1414
// distance and angle are ignored on mono
@@ -19,5 +19,5 @@ func (p panMixerMono) GetMixingMatrix(pan panning.Position) volume.Matrix {
1919
}
2020

2121
func (p panMixerMono) NumChannels() int {
22-
return p.Channels
22+
return 1
2323
}

mixing/panmixer_quad.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
// PanMixerQuad is a mixer that's specialized for mixing quadraphonic audio content
1111
var PanMixerQuad PanMixer = &panMixerQuad{}
1212

13-
type panMixerQuad volume.Matrix
13+
type panMixerQuad struct{}
1414

1515
func (p panMixerQuad) GetMixingMatrix(pan panning.Position) volume.Matrix {
1616
pangle := float64(pan.Angle)
@@ -31,5 +31,5 @@ func (p panMixerQuad) GetMixingMatrix(pan panning.Position) volume.Matrix {
3131
}
3232

3333
func (p panMixerQuad) NumChannels() int {
34-
return p.Channels
34+
return 4
3535
}

mixing/panmixer_stereo.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
// PanMixerStereo is a mixer that's specialized for mixing stereo audio content
1111
var PanMixerStereo PanMixer = &panMixerStereo{}
1212

13-
type panMixerStereo volume.Matrix
13+
type panMixerStereo struct{}
1414

1515
func (p panMixerStereo) GetMixingMatrix(pan panning.Position) volume.Matrix {
1616
pangle := float64(pan.Angle)
@@ -28,5 +28,5 @@ func (p panMixerStereo) GetMixingMatrix(pan panning.Position) volume.Matrix {
2828
}
2929

3030
func (p panMixerStereo) NumChannels() int {
31-
return p.Channels
31+
return 2
3232
}

sampling/samplerimpl.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package sampling
33
import "github.com/gotracker/gomixing/volume"
44

55
type sampler struct {
6-
Sampler
76
ss SampleStream
87
pos Pos
98
period float32

volume/matrix.go

Lines changed: 76 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,70 +8,45 @@ type Matrix struct {
88

99
// Apply takes a volume matrix and multiplies it by incoming volumes
1010
func (m Matrix) ApplyToMatrix(mtx Matrix) Matrix {
11+
if mtx.Channels == 0 {
12+
return m
13+
}
14+
1115
if m.Channels == mtx.Channels {
1216
// simple straight-through
13-
out := Matrix{
14-
Channels: m.Channels,
15-
}
1617
for i := 0; i < m.Channels; i++ {
17-
out.StaticMatrix[i] = mtx.StaticMatrix[i].ApplySingle(m.StaticMatrix[i])
18+
m.StaticMatrix[i] = mtx.StaticMatrix[i].ApplySingle(m.StaticMatrix[i])
1819
}
19-
return out
20+
return m
2021
}
2122

2223
// more complex applications follow...
2324

2425
if mtx.Channels == 1 {
2526
// right (mtx) is mono, so just do direct mono application
26-
return m.Apply(m.StaticMatrix[0])
27-
}
28-
29-
out := Matrix{
30-
Channels: m.Channels,
27+
return m.Apply(mtx.StaticMatrix[0])
3128
}
3229

33-
switch m.Channels {
34-
case 1:
35-
// left (m) is mono, so do indirect mono application
36-
mo := mtx.AsMono()
37-
out.StaticMatrix[0] = m.StaticMatrix[0].ApplySingle(mo[0])
38-
return out
39-
case 2:
40-
// left (m) is stereo, so do indirect stereo application
41-
st := mtx.AsStereo()
42-
out.StaticMatrix[0] = m.StaticMatrix[0].ApplySingle(st[0])
43-
out.StaticMatrix[1] = m.StaticMatrix[1].ApplySingle(st[1])
44-
case 4:
45-
// left (m) is quad, so do indirect quad application
46-
qu := mtx.AsQuad()
47-
out.StaticMatrix[0] = m.StaticMatrix[0].ApplySingle(qu[0])
48-
out.StaticMatrix[1] = m.StaticMatrix[1].ApplySingle(qu[1])
49-
out.StaticMatrix[2] = m.StaticMatrix[2].ApplySingle(qu[2])
50-
out.StaticMatrix[3] = m.StaticMatrix[3].ApplySingle(qu[3])
51-
}
52-
return out
30+
// NOTE: recursive
31+
return m.ApplyToMatrix(mtx.ToChannels(m.Channels))
5332
}
5433

5534
func (m Matrix) Apply(vol Volume) Matrix {
56-
var out Matrix
57-
out.Channels = m.Channels
5835
for i := 0; i < m.Channels; i++ {
59-
out.StaticMatrix[i] = vol.ApplySingle(m.StaticMatrix[i])
36+
m.StaticMatrix[i] = vol.ApplySingle(m.StaticMatrix[i])
6037
}
61-
return out
38+
return m
6239
}
6340

6441
func (m *Matrix) Accumulate(in Matrix) {
6542
if m.Channels == 0 {
66-
m.Channels = in.Channels
67-
copy(m.StaticMatrix[:m.Channels], in.StaticMatrix[:m.Channels])
43+
*m = in
6844
return
6945
}
7046

71-
var dry StaticMatrix
72-
in.ToChannels(m.Channels, dry[:])
47+
dry := in.ToChannels(m.Channels)
7348
for i := 0; i < m.Channels; i++ {
74-
m.StaticMatrix[i] += dry[i]
49+
m.StaticMatrix[i] += dry.StaticMatrix[i]
7550
}
7651
}
7752

@@ -82,24 +57,20 @@ func (m *Matrix) Assign(channels int, data []Volume) {
8257
}
8358
}
8459

85-
func (m Matrix) ToChannels(channels int, out []Volume) {
60+
func (m Matrix) ToChannels(channels int) Matrix {
8661
if m.Channels == channels {
87-
copy(out, m.StaticMatrix[0:channels])
88-
return
62+
return m
8963
}
9064

9165
switch channels {
92-
default:
93-
copy(out, m.StaticMatrix[0:channels])
9466
case 1:
95-
mo := m.AsMono()
96-
copy(out, mo[:])
67+
return m.AsMono()
9768
case 2:
98-
st := m.AsStereo()
99-
copy(out, st[:])
69+
return m.AsStereo()
10070
case 4:
101-
qu := m.AsQuad()
102-
copy(out, qu[:])
71+
return m.AsQuad()
72+
default:
73+
return Matrix{}
10374
}
10475
}
10576

@@ -120,34 +91,74 @@ func (m Matrix) Get(ch int) Volume {
12091
return m.StaticMatrix[ch]
12192
}
12293

123-
func (m Matrix) AsMono() [1]Volume {
124-
var out [1]Volume
125-
if m.Channels == 1 {
126-
out[0] = m.StaticMatrix[0]
127-
} else {
128-
out[0] = m.Sum() / Volume(m.Channels)
94+
func (m Matrix) AsMono() Matrix {
95+
switch m.Channels {
96+
case 0:
97+
return Matrix{}
98+
case 1:
99+
return m
100+
default:
101+
return Matrix{
102+
StaticMatrix: StaticMatrix{m.Sum() / Volume(m.Channels)},
103+
Channels: 1,
104+
}
129105
}
130-
return out
131106
}
132107

133-
func (m Matrix) AsStereo() [2]Volume {
108+
func (m Matrix) AsStereo() Matrix {
134109
switch m.Channels {
110+
case 0:
111+
return Matrix{}
135112
case 1:
136-
return [2]Volume{m.StaticMatrix[0], m.StaticMatrix[0]}
113+
return Matrix{
114+
StaticMatrix: StaticMatrix{m.StaticMatrix[0], m.StaticMatrix[0]},
115+
Channels: 2,
116+
}
137117
case 2:
138-
return [2]Volume{m.StaticMatrix[0], m.StaticMatrix[1]}
118+
return m
119+
case 4:
120+
return Matrix{
121+
StaticMatrix: StaticMatrix{(m.StaticMatrix[0] + m.StaticMatrix[2]) / 2.0, (m.StaticMatrix[1] + m.StaticMatrix[3]) / 2.0},
122+
Channels: 2,
123+
}
139124
default:
140-
return [2]Volume{(m.StaticMatrix[0] + m.StaticMatrix[2]) / 2.0, (m.StaticMatrix[1] + m.StaticMatrix[3]) / 2.0}
125+
return Matrix{}
141126
}
142127
}
143128

144-
func (m Matrix) AsQuad() [4]Volume {
129+
func (m Matrix) AsQuad() Matrix {
145130
switch m.Channels {
131+
case 0:
132+
return Matrix{}
146133
case 1:
147-
return [4]Volume{m.StaticMatrix[0], m.StaticMatrix[0], m.StaticMatrix[0], m.StaticMatrix[0]}
134+
return Matrix{
135+
StaticMatrix: StaticMatrix{m.StaticMatrix[0], m.StaticMatrix[0], m.StaticMatrix[0], m.StaticMatrix[0]},
136+
Channels: 4,
137+
}
148138
case 2:
149-
return [4]Volume{m.StaticMatrix[0], m.StaticMatrix[1], m.StaticMatrix[0], m.StaticMatrix[1]}
139+
return Matrix{
140+
StaticMatrix: StaticMatrix{m.StaticMatrix[0], m.StaticMatrix[1], m.StaticMatrix[0], m.StaticMatrix[1]},
141+
Channels: 4,
142+
}
143+
case 4:
144+
return m
150145
default:
151-
return [4]Volume{m.StaticMatrix[0], m.StaticMatrix[1], m.StaticMatrix[2], m.StaticMatrix[3]}
146+
return Matrix{}
147+
}
148+
}
149+
150+
func (m Matrix) Lerp(other Matrix, t float32) Matrix {
151+
if other.Channels == 0 || t <= 0 {
152+
return m
152153
}
154+
155+
out := other.ToChannels(m.Channels)
156+
157+
// lerp between m and v
158+
for c := 0; c < m.Channels; c++ {
159+
a := m.StaticMatrix[c]
160+
b := out.StaticMatrix[c]
161+
out.StaticMatrix[c] = a + Volume(t)*(b-a)
162+
}
163+
return out
153164
}

0 commit comments

Comments
 (0)