synth_blocks 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|