@@ -16,11 +16,21 @@ type (
16
16
}
17
17
18
18
section struct {
19
- a , b []float64
19
+ a , b [2 ][ ]float64
20
20
xPast , yPast [][2 ]float64
21
21
}
22
22
23
- EqualizerSection struct {
23
+ // EqualizerSections is the interfacd that is passed into NewEqualizer
24
+ EqualizerSections interface {
25
+ sections (fs float64 ) []section
26
+ }
27
+
28
+ StereoEqualizerSection struct {
29
+ Left MonoEqualizerSection
30
+ Right MonoEqualizerSection
31
+ }
32
+
33
+ MonoEqualizerSection struct {
24
34
// F0 (center frequency) sets the mid-point of the section’s
25
35
// frequency range and is given in Hertz [Hz].
26
36
F0 float64
@@ -52,10 +62,90 @@ type (
52
62
// cut (volume down) and positive numbers to boost (volume up).
53
63
G float64
54
64
}
65
+
66
+ // StereoEqualizerSections implements EqualizerSections and can be passed into NewEqualizer
67
+ StereoEqualizerSections []StereoEqualizerSection
68
+
69
+ // MonoEqualizerSections implements EqualizerSections and can be passed into NewEqualizer
70
+ MonoEqualizerSections []MonoEqualizerSection
55
71
)
56
72
57
- func (s * section ) apply (x [][2 ]float64 ) [][2 ]float64 {
58
- ord := len (s .a ) - 1
73
+ // NewEqualizer returns a beep.Streamer that modifies the stream based on the EqualizerSection slice that is passed in.
74
+ // The SampleRate (sr) must match that of the Streamer.
75
+ func NewEqualizer (st beep.Streamer , sr beep.SampleRate , s EqualizerSections ) beep.Streamer {
76
+ return & equalizer {
77
+ streamer : st ,
78
+ sections : s .sections (float64 (sr )),
79
+ }
80
+ }
81
+
82
+ func (m MonoEqualizerSections ) sections (fs float64 ) []section {
83
+ out := make ([]section , len (m ))
84
+ for i , s := range m {
85
+ out [i ] = s .section (fs )
86
+ }
87
+ return out
88
+ }
89
+
90
+ func (m StereoEqualizerSections ) sections (fs float64 ) []section {
91
+ out := make ([]section , len (m ))
92
+ for i , s := range m {
93
+ out [i ] = s .section (fs )
94
+ }
95
+ return out
96
+ }
97
+
98
+ // Stream streams the wrapped Streamer modified by Equalizer.
99
+ func (e * equalizer ) Stream (samples [][2 ]float64 ) (n int , ok bool ) {
100
+ n , ok = e .streamer .Stream (samples )
101
+ for _ , s := range e .sections {
102
+ s .apply (samples )
103
+ }
104
+ return n , ok
105
+ }
106
+
107
+ // Err propagates the wrapped Streamer's errors.
108
+ func (e * equalizer ) Err () error {
109
+ return e .streamer .Err ()
110
+ }
111
+
112
+ func (m MonoEqualizerSection ) section (fs float64 ) section {
113
+ beta := math .Tan (m .Bf / 2.0 * math .Pi / (fs / 2.0 )) *
114
+ math .Sqrt (math .Abs (math .Pow (math .Pow (10 , m .GB / 20.0 ), 2.0 )-
115
+ math .Pow (math .Pow (10.0 , m .G0 / 20.0 ), 2.0 ))) /
116
+ math .Sqrt (math .Abs (math .Pow (math .Pow (10.0 , m .G / 20.0 ), 2.0 )-
117
+ math .Pow (math .Pow (10.0 , m .GB / 20.0 ), 2.0 )))
118
+
119
+ b := []float64 {
120
+ (math .Pow (10.0 , m .G0 / 20.0 ) + math .Pow (10.0 , m .G / 20.0 )* beta ) / (1 + beta ),
121
+ (- 2 * math .Pow (10.0 , m .G0 / 20.0 ) * math .Cos (m .F0 * math .Pi / (fs / 2.0 ))) / (1 + beta ),
122
+ (math .Pow (10.0 , m .G0 / 20 ) - math .Pow (10.0 , m .G / 20.0 )* beta ) / (1 + beta ),
123
+ }
124
+
125
+ a := []float64 {
126
+ 1.0 ,
127
+ - 2 * math .Cos (m .F0 * math .Pi / (fs / 2.0 )) / (1 + beta ),
128
+ (1 - beta ) / (1 + beta ),
129
+ }
130
+
131
+ return section {
132
+ a : [2 ][]float64 {a , a },
133
+ b : [2 ][]float64 {b , b },
134
+ }
135
+ }
136
+
137
+ func (s StereoEqualizerSection ) section (fs float64 ) section {
138
+ l := s .Left .section (fs )
139
+ r := s .Right .section (fs )
140
+
141
+ return section {
142
+ a : [2 ][]float64 {l .a [0 ], r .a [0 ]},
143
+ b : [2 ][]float64 {l .b [0 ], r .b [0 ]},
144
+ }
145
+ }
146
+
147
+ func (s * section ) apply (x [][2 ]float64 ) {
148
+ ord := len (s .a [0 ]) - 1
59
149
np := len (x ) - 1
60
150
61
151
if np < ord {
@@ -65,85 +155,40 @@ func (s *section) apply(x [][2]float64) [][2]float64 {
65
155
66
156
y := make ([][2 ]float64 , len (x ))
67
157
68
- if len (s .xPast ) == 0 {
69
- s .xPast = make ([][2 ]float64 , len (x ))
158
+ if len (s .xPast ) < len ( x ) {
159
+ s .xPast = append ( s . xPast , make ([][2 ]float64 , len (x )- len ( s . xPast )) ... )
70
160
}
71
161
72
- if len (s .yPast ) == 0 {
73
- s .yPast = make ([][2 ]float64 , len (x ))
162
+ if len (s .yPast ) < len ( x ) {
163
+ s .yPast = append ( s . yPast , make ([][2 ]float64 , len (x )- len ( s . yPast )) ... )
74
164
}
75
165
76
166
for i := 0 ; i < len (x ); i ++ {
77
167
for j := 0 ; j < ord + 1 ; j ++ {
78
168
if i - j < 0 {
79
- y [i ][0 ] = y [i ][0 ] + s .b [j ]* s .xPast [len (s .xPast )- j ][0 ]
80
- y [i ][1 ] = y [i ][1 ] + s .b [j ]* s .xPast [len (s .xPast )- j ][1 ]
169
+ y [i ][0 ] = y [i ][0 ] + s .b [0 ][ j ]* s .xPast [len (s .xPast )- j ][0 ]
170
+ y [i ][1 ] = y [i ][1 ] + s .b [1 ][ j ]* s .xPast [len (s .xPast )- j ][1 ]
81
171
} else {
82
- y [i ][0 ] = y [i ][0 ] + s .b [j ]* x [i - j ][0 ]
83
- y [i ][1 ] = y [i ][1 ] + s .b [j ]* x [i - j ][1 ]
172
+ y [i ][0 ] = y [i ][0 ] + s .b [0 ][ j ]* x [i - j ][0 ]
173
+ y [i ][1 ] = y [i ][1 ] + s .b [1 ][ j ]* x [i - j ][1 ]
84
174
}
85
175
}
86
176
87
177
for j := 0 ; j < ord ; j ++ {
88
178
if i - j - 1 < 0 {
89
- y [i ][0 ] = y [i ][0 ] - s .a [j + 1 ]* s .yPast [len (s .yPast )- j - 1 ][0 ]
90
- y [i ][1 ] = y [i ][1 ] - s .a [j + 1 ]* s .yPast [len (s .yPast )- j - 1 ][1 ]
179
+ y [i ][0 ] = y [i ][0 ] - s .a [0 ][ j + 1 ]* s .yPast [len (s .yPast )- j - 1 ][0 ]
180
+ y [i ][1 ] = y [i ][1 ] - s .a [1 ][ j + 1 ]* s .yPast [len (s .yPast )- j - 1 ][1 ]
91
181
} else {
92
- y [i ][0 ] = y [i ][0 ] - s .a [j + 1 ]* y [i - j - 1 ][0 ]
93
- y [i ][1 ] = y [i ][1 ] - s .a [j + 1 ]* y [i - j - 1 ][1 ]
182
+ y [i ][0 ] = y [i ][0 ] - s .a [0 ][ j + 1 ]* y [i - j - 1 ][0 ]
183
+ y [i ][1 ] = y [i ][1 ] - s .a [1 ][ j + 1 ]* y [i - j - 1 ][1 ]
94
184
}
95
185
}
96
186
97
- y [i ][0 ] = y [i ][0 ] / s .a [0 ]
98
- y [i ][1 ] = y [i ][1 ] / s .a [0 ]
99
- }
100
-
101
- s .xPast = x
102
- s .yPast = y
103
- return y
104
- }
105
-
106
- // NewEqualizer returns a beep.Streamer that modifies the stream based on the EqualizerSection slice that is passed in.
107
- // The SampleRate (sr) must match that of the Streamer.
108
- func NewEqualizer (s beep.Streamer , sr beep.SampleRate , sections []EqualizerSection ) beep.Streamer {
109
- fs := float64 (sr )
110
- out := & equalizer {
111
- streamer : s ,
112
- }
113
-
114
- for _ , s := range sections {
115
- beta := math .Tan (s .Bf / 2.0 * math .Pi / (fs / 2.0 )) *
116
- math .Sqrt (math .Abs (math .Pow (math .Pow (10 , s .GB / 20.0 ), 2.0 )-
117
- math .Pow (math .Pow (10.0 , s .G0 / 20.0 ), 2.0 ))) /
118
- math .Sqrt (math .Abs (math .Pow (math .Pow (10.0 , s .G / 20.0 ), 2.0 )-
119
- math .Pow (math .Pow (10.0 , s .GB / 20.0 ), 2.0 )))
120
-
121
- b := []float64 {
122
- (math .Pow (10.0 , s .G0 / 20.0 ) + math .Pow (10.0 , s .G / 20.0 )* beta ) / (1 + beta ),
123
- (- 2 * math .Pow (10.0 , s .G0 / 20.0 ) * math .Cos (s .F0 * math .Pi / (fs / 2.0 ))) / (1 + beta ),
124
- (math .Pow (10.0 , s .G0 / 20 ) - math .Pow (10.0 , s .G / 20.0 )* beta ) / (1 + beta ),
125
- }
126
-
127
- a := []float64 {
128
- 1.0 ,
129
- - 2 * math .Cos (s .F0 * math .Pi / (fs / 2.0 )) / (1 + beta ),
130
- (1 - beta ) / (1 + beta ),
131
- }
132
- out .sections = append (out .sections , section {a : a , b : b })
133
- }
134
- return out
135
- }
136
-
137
- // Stream streams the wrapped Streamer modified by Equalizer.
138
- func (e * equalizer ) Stream (samples [][2 ]float64 ) (n int , ok bool ) {
139
- n , ok = e .streamer .Stream (samples )
140
- for _ , s := range e .sections {
141
- copy (samples , s .apply (samples ))
187
+ y [i ][0 ] = y [i ][0 ] / s .a [0 ][0 ]
188
+ y [i ][1 ] = y [i ][1 ] / s .a [1 ][0 ]
142
189
}
143
- return n , ok
144
- }
145
190
146
- // Err propagates the wrapped Streamer's errors.
147
- func ( e * equalizer ) Err () error {
148
- return e . streamer . Err ( )
191
+ s . xPast = x [:]
192
+ s . yPast = y [:]
193
+ copy ( x , y )
149
194
}
0 commit comments