synth_blocks 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -0
- data/lib/synth_blocks.rb +35 -24
- data/lib/synth_blocks/core/wave_writer.rb +22 -15
- data/lib/synth_blocks/fx/g_verb.rb +227 -216
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9e4c687fc841d59a5e910589e7cd8d584ad84bc6079ef508a02969afb547690
|
4
|
+
data.tar.gz: 7f3e2170fb0559f07b151784b16e835f032d10ab397b49ebc7477d5026aef3c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0a01ec77eb1d4b51ad402f82f3566e2ca9f79d37eb13eb27d5c9702f077c8c1da06b079afe248d1c710025285ac2db24a0d33e4dd6d43674b58f6a68c1682d5
|
7
|
+
data.tar.gz: fe8407848935beac13adb2f90a01a38762ebd0692d2f1265f1e24ff7813d0534c030ed58756ae81e092d8a3165cbbf7c82784608defda93bcaef3bfc16b3ed50
|
data/README.md
CHANGED
@@ -19,6 +19,17 @@ The code is super unoptimised, as it is written for learning purposes. This mean
|
|
19
19
|
takes a couple of hours to render. I'm relatively sure that there are some low hanging fruits for optimisation, especially in the sequencer code that does a lot of
|
20
20
|
useless lookups on quite large data structures that hold the automation data, but I haven't yet gotten around to take a look at it.
|
21
21
|
|
22
|
+
## Opal
|
23
|
+
|
24
|
+
Since my presentation runs in a browser I thought it could be fun to try to make this library run in Opal and thus in the browser.
|
25
|
+
|
26
|
+
It works but obviously long running code that will block the main thread is not something that makes browsers (and users) happy, but for small demonstrations, it's probably good enough.
|
27
|
+
|
28
|
+
There are two modules that do not work:
|
29
|
+
|
30
|
+
- GVerb uses prime numbers but Opal does not implement Stdlib::Prime.
|
31
|
+
- To prevent adding WaveFile as an additional dependency (and because it doesn't make a ton of sense for my usecase), WaveWriter is not functional in Opal.
|
32
|
+
|
22
33
|
## Examples
|
23
34
|
|
24
35
|
The easiest way to test the example code is to check out the repo and then execute the code directly.
|
data/lib/synth_blocks.rb
CHANGED
@@ -1,24 +1,35 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
1
|
+
require_relative 'synth_blocks/core/sound'
|
2
|
+
require_relative 'synth_blocks/mod/adsr'
|
3
|
+
require_relative 'synth_blocks/fx/chorus'
|
4
|
+
require_relative 'synth_blocks/fx/compressor'
|
5
|
+
require_relative 'synth_blocks/fx/delay'
|
6
|
+
require_relative 'synth_blocks/mod/envelope'
|
7
|
+
require_relative 'synth_blocks/fx/eq'
|
8
|
+
require_relative 'synth_blocks/fx/g_verb'
|
9
|
+
require_relative 'synth_blocks/drum/hihat'
|
10
|
+
require_relative 'synth_blocks/drum/kick_drum'
|
11
|
+
require_relative 'synth_blocks/drum/tuned_drum'
|
12
|
+
require_relative 'synth_blocks/mixer/mixer_channel'
|
13
|
+
require_relative 'synth_blocks/synth/monosynth'
|
14
|
+
require_relative 'synth_blocks/core/moog_filter'
|
15
|
+
require_relative 'synth_blocks/core/oscillator'
|
16
|
+
require_relative 'synth_blocks/synth/polysynth'
|
17
|
+
require_relative 'synth_blocks/mixer/send_channel'
|
18
|
+
require_relative 'synth_blocks/sequencer/sequencer_dsl'
|
19
|
+
require_relative 'synth_blocks/drum/snare_drum'
|
20
|
+
require_relative 'synth_blocks/core/state_variable_filter'
|
21
|
+
require_relative 'synth_blocks/utils'
|
22
|
+
require_relative 'synth_blocks/fx/waveshaper'
|
23
|
+
require_relative 'synth_blocks/fx/limiter'
|
24
|
+
require_relative 'synth_blocks/core/wave_writer'
|
25
|
+
|
26
|
+
unless RUBY_ENGINE == 'opal'
|
27
|
+
# Now if we are NOT running inside of opal, set things up so opal can find
|
28
|
+
# the files. The whole thing is rescued in case the opal gem is not available.
|
29
|
+
# This would happen if the gem is being used server side ONLY.
|
30
|
+
begin
|
31
|
+
require 'opal'
|
32
|
+
Opal.append_path File.expand_path('..', __FILE__).untaint
|
33
|
+
rescue LoadError
|
34
|
+
end
|
35
|
+
end
|
@@ -1,26 +1,33 @@
|
|
1
|
-
require 'wavefile'
|
2
|
-
|
3
1
|
module SynthBlocks
|
4
2
|
module Core
|
5
3
|
##
|
6
4
|
# Writes Floating point data to a wavefile using the wave file gem
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
if (ARGV[0])
|
12
|
-
WaveWriter.new(ARGV[0]).write(samples)
|
5
|
+
if RUBY_ENGINE == 'opal'
|
6
|
+
class WaveWriter
|
7
|
+
def self.write_if_name_given(samples)
|
8
|
+
raise "Not Implemented in OPAL"
|
13
9
|
end
|
14
10
|
end
|
11
|
+
else
|
12
|
+
require 'wavefile'
|
13
|
+
class WaveWriter
|
14
|
+
##
|
15
|
+
# Static method to write to file given as first argument IF given
|
16
|
+
def self.write_if_name_given(samples)
|
17
|
+
if (ARGV[0])
|
18
|
+
WaveWriter.new(ARGV[0]).write(samples)
|
19
|
+
end
|
20
|
+
end
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
|
22
|
+
def initialize(filename)
|
23
|
+
@filename = filename
|
24
|
+
end
|
19
25
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
26
|
+
def write(float_data)
|
27
|
+
buffer = WaveFile::Buffer.new(float_data, WaveFile::Format.new(:mono, :float, 44100))
|
28
|
+
WaveFile::Writer.new(@filename, WaveFile::Format.new(:mono, :pcm_16, 44100)) do |writer|
|
29
|
+
writer.write(buffer)
|
30
|
+
end
|
24
31
|
end
|
25
32
|
end
|
26
33
|
end
|
@@ -21,254 +21,265 @@ module SynthBlocks
|
|
21
21
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
22
22
|
#
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
class FixedDelay # :nodoc:
|
27
|
-
def initialize(size)
|
28
|
-
@size = size
|
29
|
-
@buf = Array.new(size)
|
30
|
-
@idx = 0
|
31
|
-
@buf = @buf.map { |e| 0.0 }
|
32
|
-
end
|
33
|
-
|
34
|
-
def read(n)
|
35
|
-
i = (@idx - n + @size) % @size;
|
36
|
-
@buf[i]
|
37
|
-
end
|
38
|
-
|
39
|
-
def write(x)
|
40
|
-
@buf[@idx] = x
|
41
|
-
@idx = (@idx + 1) % @size
|
42
|
-
end
|
43
|
-
end
|
24
|
+
if RUBY_ENGINE != 'opal'
|
44
25
|
|
45
|
-
|
46
|
-
def initialize(damping)
|
47
|
-
@damping = damping
|
48
|
-
@delay = 0.0
|
49
|
-
end
|
26
|
+
require 'prime'
|
50
27
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
28
|
+
class FixedDelay # :nodoc:
|
29
|
+
def initialize(size)
|
30
|
+
@size = size
|
31
|
+
@buf = Array.new(size)
|
32
|
+
@idx = 0
|
33
|
+
@buf = @buf.map { |e| 0.0 }
|
34
|
+
end
|
57
35
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
@idx = 0
|
63
|
-
@buf = Array.new(@size)
|
64
|
-
@buf = @buf.map { |e| 0.0 }
|
65
|
-
end
|
36
|
+
def read(n)
|
37
|
+
i = (@idx - n + @size) % @size;
|
38
|
+
@buf[i]
|
39
|
+
end
|
66
40
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
@idx = (@idx + 1) % @size;
|
72
|
-
y
|
41
|
+
def write(x)
|
42
|
+
@buf[@idx] = x
|
43
|
+
@idx = (@idx + 1) % @size
|
44
|
+
end
|
73
45
|
end
|
74
|
-
end
|
75
|
-
##
|
76
|
-
# GVerb is a relatively simple reverb implementation
|
77
|
-
class GVerb
|
78
|
-
FDNORDER = 4 # :nodoc:
|
79
46
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
# max_room_size is the maximum room size you'll use
|
85
|
-
#
|
86
|
-
# room_size is the current room size
|
87
|
-
#
|
88
|
-
def initialize(srate, max_room_size: 120.0, room_size: 50.0, rev_time: 2.0, damping: 0.3, spread: 15.0, input_bandwidth: 1.5, early_level: 0.8, tail_level: 0.5, mix: 0.2)
|
89
|
-
@rate = srate
|
90
|
-
@damping = damping
|
91
|
-
@max_room_size = max_room_size
|
92
|
-
@room_size = room_size
|
93
|
-
@rev_time = rev_time
|
94
|
-
@early_level = early_level
|
95
|
-
@tail_level = tail_level
|
96
|
-
@mix = mix
|
97
|
-
@max_delay = @rate * @max_room_size / 340.0
|
98
|
-
@largest_delay = @rate * @room_size / 340.0
|
99
|
-
@input_bandwidth = input_bandwidth;
|
100
|
-
@input_damper = Damper.new(1.0 - @input_bandwidth)
|
101
|
-
|
102
|
-
|
103
|
-
@fdndels = FDNORDER.times.map do |i|
|
104
|
-
FixedDelay.new(@max_delay + 1000)
|
47
|
+
class Damper # :nodoc:
|
48
|
+
def initialize(damping)
|
49
|
+
@damping = damping
|
50
|
+
@delay = 0.0
|
105
51
|
end
|
106
|
-
@fdngains = Array.new(FDNORDER)
|
107
|
-
@fdnlens = Array.new(FDNORDER)
|
108
52
|
|
109
|
-
|
110
|
-
|
53
|
+
def run(x)
|
54
|
+
y = x * (1.0-@damping) + @delay * @damping;
|
55
|
+
@delay = y
|
56
|
+
y
|
111
57
|
end
|
58
|
+
end
|
112
59
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
gb = 1.000000*@largest_delay if (i == 0)
|
121
|
-
gb = 0.816490*@largest_delay if (i == 1)
|
122
|
-
gb = 0.707100*@largest_delay if (i == 2)
|
123
|
-
gb = 0.632450*@largest_delay if (i == 3)
|
124
|
-
|
125
|
-
@fdnlens[i] = nearest_prime(gb, 0.5);
|
126
|
-
@fdnlens[i] = gb.round;
|
127
|
-
@fdngains[i] = -(@alpha ** @fdnlens[i])
|
60
|
+
class Diffuser # :nodoc:
|
61
|
+
def initialize(size, coeff)
|
62
|
+
@size = size.floor
|
63
|
+
@coeff = coeff
|
64
|
+
@idx = 0
|
65
|
+
@buf = Array.new(@size)
|
66
|
+
@buf = @buf.map { |e| 0.0 }
|
128
67
|
end
|
129
68
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
diffscale = @fdnlens[3].to_f/(210+159+562+410);
|
137
|
-
spread1 = spread.to_f
|
138
|
-
spread2 = 3.0*spread
|
139
|
-
|
140
|
-
b = 210
|
141
|
-
r = 0.125541
|
142
|
-
a = spread1*r
|
143
|
-
c = 210+159+a
|
144
|
-
cc = c-b
|
145
|
-
r = 0.854046
|
146
|
-
a = spread2*r
|
147
|
-
d = 210+159+562+a
|
148
|
-
dd = d-c
|
149
|
-
e = 1341-d
|
150
|
-
|
151
|
-
@ldifs = [
|
152
|
-
Diffuser.new((diffscale*b),0.75),
|
153
|
-
Diffuser.new((diffscale*cc),0.75),
|
154
|
-
Diffuser.new((diffscale*dd),0.625),
|
155
|
-
Diffuser.new((diffscale*e),0.625)
|
156
|
-
]
|
157
|
-
|
158
|
-
b = 210
|
159
|
-
r = -0.568366
|
160
|
-
a = spread1*r
|
161
|
-
c = 210+159+a
|
162
|
-
cc = c-b
|
163
|
-
r = -0.126815;
|
164
|
-
a = spread2*r
|
165
|
-
d = 210+159+562+a
|
166
|
-
dd = d-c
|
167
|
-
e = 1341-d
|
168
|
-
|
169
|
-
@rdifs = [
|
170
|
-
Diffuser.new((diffscale*b),0.75),
|
171
|
-
Diffuser.new((diffscale*cc),0.75),
|
172
|
-
Diffuser.new((diffscale*dd),0.625),
|
173
|
-
Diffuser.new((diffscale*e),0.625)
|
174
|
-
]
|
175
|
-
|
176
|
-
|
177
|
-
# Tapped delay section */
|
178
|
-
|
179
|
-
@tapdelay = FixedDelay.new(44000)
|
180
|
-
@taps = Array.new(FDNORDER)
|
181
|
-
@tapgains = Array.new(FDNORDER)
|
182
|
-
|
183
|
-
@taps[0] = 5+0.410*@largest_delay
|
184
|
-
@taps[1] = 5+0.300*@largest_delay
|
185
|
-
@taps[2] = 5+0.155*@largest_delay
|
186
|
-
@taps[3] = 5+0.000*@largest_delay
|
187
|
-
|
188
|
-
FDNORDER.times do |i|
|
189
|
-
@tapgains[i] = @alpha ** @taps[i]
|
69
|
+
def run(x)
|
70
|
+
w = x - @buf[@idx] * @coeff;
|
71
|
+
y = @buf[@idx] + w * @coeff;
|
72
|
+
@buf[@idx] = w
|
73
|
+
@idx = (@idx + 1) % @size;
|
74
|
+
y
|
190
75
|
end
|
191
76
|
end
|
192
|
-
|
193
|
-
|
194
77
|
##
|
195
|
-
#
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
78
|
+
# GVerb is a relatively simple reverb implementation
|
79
|
+
class GVerb
|
80
|
+
FDNORDER = 4 # :nodoc:
|
81
|
+
|
82
|
+
|
83
|
+
##
|
84
|
+
# Create new GVerb instance
|
85
|
+
#
|
86
|
+
# max_room_size is the maximum room size you'll use
|
87
|
+
#
|
88
|
+
# room_size is the current room size
|
89
|
+
#
|
90
|
+
def initialize(srate, max_room_size: 120.0, room_size: 50.0, rev_time: 2.0, damping: 0.3, spread: 15.0, input_bandwidth: 1.5, early_level: 0.8, tail_level: 0.5, mix: 0.2)
|
91
|
+
@rate = srate
|
92
|
+
@damping = damping
|
93
|
+
@max_room_size = max_room_size
|
94
|
+
@room_size = room_size
|
95
|
+
@rev_time = rev_time
|
96
|
+
@early_level = early_level
|
97
|
+
@tail_level = tail_level
|
98
|
+
@mix = mix
|
99
|
+
@max_delay = @rate * @max_room_size / 340.0
|
100
|
+
@largest_delay = @rate * @room_size / 340.0
|
101
|
+
@input_bandwidth = input_bandwidth;
|
102
|
+
@input_damper = Damper.new(1.0 - @input_bandwidth)
|
103
|
+
|
104
|
+
|
105
|
+
@fdndels = FDNORDER.times.map do |i|
|
106
|
+
FixedDelay.new(@max_delay + 1000)
|
107
|
+
end
|
108
|
+
@fdngains = Array.new(FDNORDER)
|
109
|
+
@fdnlens = Array.new(FDNORDER)
|
110
|
+
|
111
|
+
@fdndamps = FDNORDER.times.map do |i|
|
112
|
+
Damper.new(@damping)
|
113
|
+
end
|
114
|
+
|
115
|
+
ga = 60.0;
|
116
|
+
gt = @rev_time;
|
117
|
+
ga = 10.0 ** (-ga / 20.0)
|
118
|
+
n = @rate * gt
|
119
|
+
@alpha = ga ** (1.0 / n)
|
120
|
+
gb = 0.0;
|
121
|
+
FDNORDER.times do |i|
|
122
|
+
gb = 1.000000*@largest_delay if (i == 0)
|
123
|
+
gb = 0.816490*@largest_delay if (i == 1)
|
124
|
+
gb = 0.707100*@largest_delay if (i == 2)
|
125
|
+
gb = 0.632450*@largest_delay if (i == 3)
|
126
|
+
|
127
|
+
@fdnlens[i] = nearest_prime(gb, 0.5);
|
128
|
+
@fdnlens[i] = gb.round;
|
129
|
+
@fdngains[i] = -(@alpha ** @fdnlens[i])
|
130
|
+
end
|
131
|
+
|
132
|
+
@d = Array.new(FDNORDER)
|
133
|
+
@u = Array.new(FDNORDER)
|
134
|
+
@f = Array.new(FDNORDER)
|
135
|
+
|
136
|
+
# DIFFUSER SECTION
|
137
|
+
|
138
|
+
diffscale = @fdnlens[3].to_f/(210+159+562+410);
|
139
|
+
spread1 = spread.to_f
|
140
|
+
spread2 = 3.0*spread
|
141
|
+
|
142
|
+
b = 210
|
143
|
+
r = 0.125541
|
144
|
+
a = spread1*r
|
145
|
+
c = 210+159+a
|
146
|
+
cc = c-b
|
147
|
+
r = 0.854046
|
148
|
+
a = spread2*r
|
149
|
+
d = 210+159+562+a
|
150
|
+
dd = d-c
|
151
|
+
e = 1341-d
|
152
|
+
|
153
|
+
@ldifs = [
|
154
|
+
Diffuser.new((diffscale*b),0.75),
|
155
|
+
Diffuser.new((diffscale*cc),0.75),
|
156
|
+
Diffuser.new((diffscale*dd),0.625),
|
157
|
+
Diffuser.new((diffscale*e),0.625)
|
158
|
+
]
|
159
|
+
|
160
|
+
b = 210
|
161
|
+
r = -0.568366
|
162
|
+
a = spread1*r
|
163
|
+
c = 210+159+a
|
164
|
+
cc = c-b
|
165
|
+
r = -0.126815;
|
166
|
+
a = spread2*r
|
167
|
+
d = 210+159+562+a
|
168
|
+
dd = d-c
|
169
|
+
e = 1341-d
|
170
|
+
|
171
|
+
@rdifs = [
|
172
|
+
Diffuser.new((diffscale*b),0.75),
|
173
|
+
Diffuser.new((diffscale*cc),0.75),
|
174
|
+
Diffuser.new((diffscale*dd),0.625),
|
175
|
+
Diffuser.new((diffscale*e),0.625)
|
176
|
+
]
|
177
|
+
|
178
|
+
|
179
|
+
# Tapped delay section */
|
180
|
+
|
181
|
+
@tapdelay = FixedDelay.new(44000)
|
182
|
+
@taps = Array.new(FDNORDER)
|
183
|
+
@tapgains = Array.new(FDNORDER)
|
184
|
+
|
185
|
+
@taps[0] = 5+0.410*@largest_delay
|
186
|
+
@taps[1] = 5+0.300*@largest_delay
|
187
|
+
@taps[2] = 5+0.155*@largest_delay
|
188
|
+
@taps[3] = 5+0.000*@largest_delay
|
189
|
+
|
190
|
+
FDNORDER.times do |i|
|
191
|
+
@tapgains[i] = @alpha ** @taps[i]
|
192
|
+
end
|
200
193
|
end
|
201
194
|
|
202
|
-
z = @input_damper.run(x)
|
203
|
-
z = @ldifs[0].run(z)
|
204
|
-
FDNORDER.times do |i|
|
205
|
-
@u[i] = @tapgains[i] * @tapdelay.read(@taps[i])
|
206
|
-
end
|
207
195
|
|
208
|
-
|
196
|
+
##
|
197
|
+
# runs a value through the reverb, returns the reverberated signal
|
198
|
+
# mixed with the original.
|
199
|
+
def run(x)
|
200
|
+
if x.nan? || x.abs > 100000.0
|
201
|
+
x = 0.0
|
202
|
+
end
|
209
203
|
|
210
|
-
|
211
|
-
|
212
|
-
|
204
|
+
z = @input_damper.run(x)
|
205
|
+
z = @ldifs[0].run(z)
|
206
|
+
FDNORDER.times do |i|
|
207
|
+
@u[i] = @tapgains[i] * @tapdelay.read(@taps[i])
|
208
|
+
end
|
213
209
|
|
214
|
-
|
215
|
-
sign = 1.0
|
216
|
-
FDNORDER.times do |i|
|
217
|
-
sum += sign * (@tail_level * @d[i] + @early_level * @u[i])
|
218
|
-
sign = -sign
|
219
|
-
end
|
210
|
+
@tapdelay.write(z)
|
220
211
|
|
221
|
-
|
212
|
+
FDNORDER.times do |i|
|
213
|
+
@d[i] = @fdndamps[i].run(@fdngains[i] * @fdndels[i].read(@fdnlens[i]))
|
214
|
+
end
|
222
215
|
|
223
|
-
|
224
|
-
|
216
|
+
sum = 0.0
|
217
|
+
sign = 1.0
|
218
|
+
FDNORDER.times do |i|
|
219
|
+
sum += sign * (@tail_level * @d[i] + @early_level * @u[i])
|
220
|
+
sign = -sign
|
221
|
+
end
|
225
222
|
|
226
|
-
|
223
|
+
sum += x* @early_level
|
227
224
|
|
228
|
-
|
229
|
-
|
230
|
-
end
|
225
|
+
lsum = sum
|
226
|
+
# rsum = sum
|
231
227
|
|
232
|
-
|
233
|
-
lsum = @ldifs[2].run(lsum)
|
234
|
-
lsum = @ldifs[3].run(lsum)
|
228
|
+
@f = fdn_matrix(@d)
|
235
229
|
|
236
|
-
|
237
|
-
|
238
|
-
|
230
|
+
FDNORDER.times do |i|
|
231
|
+
@fdndels[i].write(@u[i] + @f[i])
|
232
|
+
end
|
239
233
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
end
|
234
|
+
lsum = @ldifs[1].run(lsum)
|
235
|
+
lsum = @ldifs[2].run(lsum)
|
236
|
+
lsum = @ldifs[3].run(lsum)
|
244
237
|
|
238
|
+
# rsum = @rdifs[1].run(rsum)
|
239
|
+
# rsum = @rdifs[2].run(rsum)
|
240
|
+
# rsum = @rdifs[3].run(rsum)
|
241
|
+
|
242
|
+
lsum = x * (1.0 - @mix) + lsum * @mix
|
243
|
+
# rsum = x * (1.0 - mix) + rsum * mix
|
244
|
+
return lsum
|
245
|
+
end
|
245
246
|
|
246
|
-
private
|
247
247
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
248
|
+
private
|
249
|
+
|
250
|
+
def nearest_prime(n_f, rerror)
|
251
|
+
n = n_f.to_i
|
252
|
+
return n if Prime.prime?(n)
|
253
|
+
# assume n is large enough and n*rerror enough smaller than n */
|
254
|
+
bound = n*rerror;
|
255
|
+
1.upto(bound) do |k|
|
256
|
+
return n+k if Prime.prime?(n+k)
|
257
|
+
return n-k if Prime.prime?(n-k)
|
258
|
+
end
|
259
|
+
return -1
|
256
260
|
end
|
257
|
-
return -1
|
258
|
-
end
|
259
261
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
262
|
+
def fdn_matrix(a)
|
263
|
+
b = Array.new(FDNORDER)
|
264
|
+
dl0 = a[0]
|
265
|
+
dl1 = a[1]
|
266
|
+
dl2 = a[2]
|
267
|
+
dl3 = a[3]
|
268
|
+
|
269
|
+
b[0] = 0.5*(dl0 + dl1 - dl2 - dl3);
|
270
|
+
b[1] = 0.5*(dl0 - dl1 - dl2 + dl3);
|
271
|
+
b[2] = 0.5*(-dl0 + dl1 - dl2 + dl3);
|
272
|
+
b[3] = 0.5*(dl0 + dl1 + dl2 + dl3);
|
273
|
+
b
|
274
|
+
end
|
275
|
+
end
|
276
|
+
else
|
277
|
+
class GVerb
|
278
|
+
def initialize(srate, max_room_size: 120.0, room_size: 50.0, rev_time: 2.0, damping: 0.3, spread: 15.0, input_bandwidth: 1.5, early_level: 0.8, tail_level: 0.5, mix: 0.2)
|
279
|
+
end
|
280
|
+
def run(x)
|
281
|
+
x
|
282
|
+
end
|
272
283
|
end
|
273
284
|
end
|
274
285
|
end
|