synthesizer 3.1.0 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/examples/{metronome.rb → audio_input_metronome.rb} +8 -2
- data/examples/{step_editor.rb → audio_input_step_editor.rb} +10 -2
- data/examples/filter_band_pass.rb +73 -0
- data/examples/{lpf.rb → filter_serial.rb} +9 -2
- data/examples/oscillator_pan.rb +70 -0
- data/examples/{formant_vocoder.rb → oscillator_source_formant_vocoder.rb} +10 -3
- data/examples/{formant_vocoder_sweep.rb → oscillator_source_formant_vocoder_sweep.rb} +13 -6
- data/examples/oscillator_sync.rb +71 -0
- data/examples/oscillator_unison.rb +64 -0
- data/examples/oscillator_volume.rb +70 -0
- data/examples/{mono.rb → synth_mono.rb} +10 -2
- data/examples/{poly.rb → synth_poly.rb} +10 -2
- data/{examples → jupyter}/adsr.ipynb +20 -17
- data/jupyter/curves.ipynb +103 -0
- data/jupyter/shapes.ipynb +111 -0
- data/lib/audio_stream/audio_input_metronome.rb +1 -1
- data/lib/synthesizer/amplifier.rb +4 -1
- data/lib/synthesizer/filter/band_pass_filter.rb +3 -3
- data/lib/synthesizer/filter/high_pass_filter.rb +3 -3
- data/lib/synthesizer/filter/high_shelf_filter.rb +4 -4
- data/lib/synthesizer/filter/low_pass_filter.rb +3 -3
- data/lib/synthesizer/filter/low_shelf_filter.rb +4 -4
- data/lib/synthesizer/filter/parallel.rb +2 -2
- data/lib/synthesizer/filter/peaking_filter.rb +5 -5
- data/lib/synthesizer/filter/serial.rb +2 -2
- data/lib/synthesizer/modulation/adsr.rb +37 -35
- data/lib/synthesizer/modulation/curve.rb +3 -0
- data/lib/synthesizer/modulation/glide.rb +9 -8
- data/lib/synthesizer/modulation/lfo.rb +23 -23
- data/lib/synthesizer/modulation_value.rb +5 -5
- data/lib/synthesizer/mono_synth.rb +7 -2
- data/lib/synthesizer/oscillator.rb +11 -9
- data/lib/synthesizer/oscillator_source/base.rb +35 -5
- data/lib/synthesizer/oscillator_source/formant_vocoder.rb +27 -19
- data/lib/synthesizer/oscillator_source/pulse.rb +11 -3
- data/lib/synthesizer/poly_synth.rb +5 -2
- data/lib/synthesizer/processor/high.rb +63 -0
- data/lib/synthesizer/processor/low.rb +59 -0
- data/lib/synthesizer/processor.rb +6 -44
- data/lib/synthesizer/quality.rb +6 -0
- data/lib/synthesizer/shape.rb +4 -4
- data/lib/synthesizer/shape_pos.rb +22 -19
- data/lib/synthesizer/unison.rb +28 -16
- data/lib/synthesizer/version.rb +1 -1
- data/lib/synthesizer.rb +1 -0
- data/samples/cinema.rb +730 -0
- data/samples/cinema_drum.wav +0 -0
- data/samples/daijoubu.rb +811 -0
- data/samples/daijoubu_drum.wav +0 -0
- data/samples/kira_power.rb +987 -0
- data/samples/kira_power_drum.wav +0 -0
- data/synthesizer.gemspec +1 -1
- metadata +32 -18
- data/examples/curves.ipynb +0 -105
- data/examples/shapes.ipynb +0 -116
@@ -0,0 +1,63 @@
|
|
1
|
+
module Synthesizer
|
2
|
+
module Processor
|
3
|
+
class High
|
4
|
+
def generator(osc, note_perform)
|
5
|
+
synth = note_perform.synth
|
6
|
+
filter = synth.filter
|
7
|
+
amp = synth.amplifier
|
8
|
+
|
9
|
+
samplecount = synth.soundinfo.window_size.to_f
|
10
|
+
|
11
|
+
# Oscillator, Amplifier
|
12
|
+
volume_mod = ModulationValue.amp_generator(note_perform, 1, osc.volume, amp.volume)
|
13
|
+
pan_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.pan, amp.pan)
|
14
|
+
tune_semis_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.tune_semis, amp.tune_semis, synth.glide&.to_modval)
|
15
|
+
tune_cents_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.tune_cents, amp.tune_cents)
|
16
|
+
|
17
|
+
sym_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.sym)
|
18
|
+
sync_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.sync)
|
19
|
+
|
20
|
+
uni_num_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.uni_num, amp.uni_num, center: 1.0)
|
21
|
+
uni_detune_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.uni_detune, amp.uni_detune)
|
22
|
+
uni_stereo_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.uni_stereo, amp.uni_stereo)
|
23
|
+
|
24
|
+
unison = Unison.new(note_perform, osc.source, osc.phase)
|
25
|
+
|
26
|
+
# Filter
|
27
|
+
filter_mod = nil
|
28
|
+
if filter
|
29
|
+
filter_mod = filter.generator(note_perform, samplecount)
|
30
|
+
end
|
31
|
+
|
32
|
+
-> {
|
33
|
+
# Oscillator, Amplifier
|
34
|
+
volume = Vdsp::DoubleArray.create(
|
35
|
+
samplecount.to_i.times.map {|i|
|
36
|
+
volume_mod[] * note_perform.velocity
|
37
|
+
}
|
38
|
+
)
|
39
|
+
pan = pan_mod[]
|
40
|
+
tune_semis = tune_semis_mod[] + synth.pitch_bend
|
41
|
+
tune_cents = tune_cents_mod[]
|
42
|
+
|
43
|
+
sym = sym_mod[]
|
44
|
+
sync = sync_mod[]
|
45
|
+
|
46
|
+
uni_num = uni_num_mod[]
|
47
|
+
uni_detune = uni_detune_mod[]
|
48
|
+
uni_stereo = uni_stereo_mod[]
|
49
|
+
|
50
|
+
buf = unison.next(uni_num, uni_detune, uni_stereo, volume, pan, tune_semis, tune_cents, sym, sync)
|
51
|
+
|
52
|
+
# Filter
|
53
|
+
if filter_mod
|
54
|
+
filter_fx = filter_mod[]
|
55
|
+
buf = filter_fx.process(buf)
|
56
|
+
end
|
57
|
+
|
58
|
+
buf
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Synthesizer
|
2
|
+
module Processor
|
3
|
+
class Low
|
4
|
+
def generator(osc, note_perform)
|
5
|
+
synth = note_perform.synth
|
6
|
+
filter = synth.filter
|
7
|
+
amp = synth.amplifier
|
8
|
+
|
9
|
+
samplecount = synth.soundinfo.window_size.to_f
|
10
|
+
|
11
|
+
# Oscillator, Amplifier
|
12
|
+
volume_mod = ModulationValue.amp_generator(note_perform, samplecount, osc.volume, amp.volume)
|
13
|
+
pan_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.pan, amp.pan)
|
14
|
+
tune_semis_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.tune_semis, amp.tune_semis, synth.glide&.to_modval)
|
15
|
+
tune_cents_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.tune_cents, amp.tune_cents)
|
16
|
+
|
17
|
+
sym_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.sym)
|
18
|
+
sync_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.sync)
|
19
|
+
|
20
|
+
uni_num_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.uni_num, amp.uni_num, center: 1.0)
|
21
|
+
uni_detune_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.uni_detune, amp.uni_detune)
|
22
|
+
uni_stereo_mod = ModulationValue.balance_generator(note_perform, samplecount, osc.uni_stereo, amp.uni_stereo)
|
23
|
+
|
24
|
+
unison = Unison.new(note_perform, osc.source, osc.phase)
|
25
|
+
|
26
|
+
# Filter
|
27
|
+
filter_mod = nil
|
28
|
+
if filter
|
29
|
+
filter_mod = filter.generator(note_perform, samplecount)
|
30
|
+
end
|
31
|
+
|
32
|
+
-> {
|
33
|
+
# Oscillator, Amplifier
|
34
|
+
volume = volume_mod[] * note_perform.velocity
|
35
|
+
pan = pan_mod[]
|
36
|
+
tune_semis = tune_semis_mod[] + synth.pitch_bend
|
37
|
+
tune_cents = tune_cents_mod[]
|
38
|
+
|
39
|
+
sym = sym_mod[]
|
40
|
+
sync = sync_mod[]
|
41
|
+
|
42
|
+
uni_num = uni_num_mod[]
|
43
|
+
uni_detune = uni_detune_mod[]
|
44
|
+
uni_stereo = uni_stereo_mod[]
|
45
|
+
|
46
|
+
buf = unison.next(uni_num, uni_detune, uni_stereo, volume, pan, tune_semis, tune_cents, sym, sync)
|
47
|
+
|
48
|
+
# Filter
|
49
|
+
if filter_mod
|
50
|
+
filter_fx = filter_mod[]
|
51
|
+
buf = filter_fx.process(buf)
|
52
|
+
end
|
53
|
+
|
54
|
+
buf
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,48 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
def generator(osc, note_perform)
|
4
|
-
synth = note_perform.synth
|
5
|
-
filter = synth.filter
|
6
|
-
amp = synth.amplifier
|
7
|
-
window_size = synth.soundinfo.window_size
|
8
|
-
framerate = synth.soundinfo.samplerate.to_f / window_size
|
9
|
-
|
10
|
-
# Oscillator, Amplifier
|
11
|
-
volume_mod = ModulationValue.amp_generator(note_perform, framerate, osc.volume, amp.volume)
|
12
|
-
pan_mod = ModulationValue.balance_generator(note_perform, framerate, osc.pan, amp.pan)
|
13
|
-
tune_semis_mod = ModulationValue.balance_generator(note_perform, framerate, osc.tune_semis, amp.tune_semis, synth.glide&.to_modval)
|
14
|
-
tune_cents_mod = ModulationValue.balance_generator(note_perform, framerate, osc.tune_cents, amp.tune_cents)
|
15
|
-
|
16
|
-
uni_num_mod = ModulationValue.balance_generator(note_perform, framerate, osc.uni_num, amp.uni_num, center: 1.0)
|
17
|
-
uni_detune_mod = ModulationValue.balance_generator(note_perform, framerate, osc.uni_detune, amp.uni_detune)
|
18
|
-
unison = Unison.new(note_perform, osc.source, osc.phase)
|
19
|
-
|
20
|
-
# Filter
|
21
|
-
filter_mod = nil
|
22
|
-
if filter
|
23
|
-
filter_mod = filter.generator(note_perform, framerate)
|
24
|
-
end
|
25
|
-
|
26
|
-
-> {
|
27
|
-
# Oscillator, Amplifier
|
28
|
-
volume = volume_mod[] * note_perform.velocity
|
29
|
-
pan = pan_mod[]
|
30
|
-
tune_semis = tune_semis_mod[] + synth.pitch_bend
|
31
|
-
tune_cents = tune_cents_mod[]
|
1
|
+
require 'synthesizer/processor/low'
|
2
|
+
require 'synthesizer/processor/high'
|
32
3
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# Filter
|
39
|
-
if filter_mod
|
40
|
-
filter_fx = filter_mod[]
|
41
|
-
buf = filter_fx.process(buf)
|
42
|
-
end
|
43
|
-
|
44
|
-
buf
|
45
|
-
}
|
4
|
+
module Synthesizer
|
5
|
+
module Processor
|
6
|
+
def self.create(quality)
|
7
|
+
const_get(quality, false).new
|
46
8
|
end
|
47
9
|
end
|
48
10
|
end
|
data/lib/synthesizer/shape.rb
CHANGED
@@ -18,11 +18,11 @@ module Synthesizer
|
|
18
18
|
RampUp = ->(phase) { (phase % 1.0) * 2 - 1 }
|
19
19
|
RampDown = ->(phase) { (phase % 1.0) * -2 + 1 }
|
20
20
|
|
21
|
-
PositiveRampUp = ->(phase) { phase % 1.0}
|
22
|
-
PositiveRampDown = ->(phase) { (phase % 1.0) * -1 + 1}
|
21
|
+
PositiveRampUp = ->(phase) { phase % 1.0 }
|
22
|
+
PositiveRampDown = ->(phase) { (phase % 1.0) * -1 + 1 }
|
23
23
|
|
24
|
-
ForeverRampUp = ->(phase) { phase}
|
25
|
-
ForeverRampDown = ->(phase) { -phase}
|
24
|
+
ForeverRampUp = ->(phase) { phase }
|
25
|
+
ForeverRampDown = ->(phase) { -phase }
|
26
26
|
|
27
27
|
# Complex
|
28
28
|
self.constants.tap {|consts|
|
@@ -1,29 +1,32 @@
|
|
1
1
|
module Synthesizer
|
2
2
|
class ShapePos
|
3
|
-
|
4
|
-
@init_phase = phase
|
5
|
-
@sync = sync
|
3
|
+
SEMITONE_RATIO = 2.0 ** (1.0 / 12.0)
|
6
4
|
|
7
|
-
|
8
|
-
@
|
5
|
+
def initialize(samplerate, init_phase)
|
6
|
+
@samplerate = samplerate.to_f
|
7
|
+
|
8
|
+
init_phase = init_phase ? init_phase.to_f : Random.rand(1.0)
|
9
|
+
@sync_phase = init_phase
|
10
|
+
@shape_phase = init_phase
|
9
11
|
end
|
10
12
|
|
11
|
-
def next(
|
12
|
-
|
13
|
+
def next(hz, sym, sync)
|
14
|
+
if sync<0.0
|
15
|
+
sync = 0.0
|
16
|
+
end
|
13
17
|
|
14
|
-
if
|
15
|
-
|
16
|
-
|
17
|
-
else
|
18
|
-
@phase = Random.rand + delta
|
19
|
-
end
|
20
|
-
# TODO: sync
|
21
|
-
#elsif @sync && @sync<@offset
|
22
|
-
# @offset = 0
|
23
|
-
# @phase = @init_phase
|
24
|
-
else
|
25
|
-
@phase += delta
|
18
|
+
if 1.0<=@sync_phase
|
19
|
+
@sync_phase %= 1.0
|
20
|
+
@shape_phase = @sync_phase
|
26
21
|
end
|
22
|
+
|
23
|
+
sync_hz = hz
|
24
|
+
sync_delta = sync_hz / @samplerate
|
25
|
+
@sync_phase += sync_delta
|
26
|
+
|
27
|
+
shape_hz = hz * (SEMITONE_RATIO ** sync)
|
28
|
+
shape_delta = shape_hz / @samplerate
|
29
|
+
@shape_phase += shape_delta
|
27
30
|
end
|
28
31
|
end
|
29
32
|
end
|
data/lib/synthesizer/unison.rb
CHANGED
@@ -4,7 +4,6 @@ module Synthesizer
|
|
4
4
|
|
5
5
|
def initialize(note_perform, source, phase)
|
6
6
|
synth = note_perform.synth
|
7
|
-
@samplerate = synth.soundinfo.samplerate
|
8
7
|
|
9
8
|
@note_perform = note_perform
|
10
9
|
@source = source
|
@@ -13,32 +12,45 @@ module Synthesizer
|
|
13
12
|
}
|
14
13
|
end
|
15
14
|
|
16
|
-
def next(uni_num, uni_detune, volume, pan, tune_semis, tune_cents)
|
15
|
+
def next(uni_num, uni_detune, uni_stereo, volume, pan, tune_semis, tune_cents, sym, sync)
|
17
16
|
if uni_num<1.0
|
18
17
|
uni_num = 1.0
|
19
18
|
elsif UNI_NUM_MAX<uni_num
|
20
19
|
uni_num = UNI_NUM_MAX
|
21
20
|
end
|
22
21
|
|
23
|
-
uni_num.
|
24
|
-
context = @source_contexts[
|
22
|
+
if uni_num==1.0
|
23
|
+
context = @source_contexts[0]
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
uni_volume = uni_num % 1.0
|
29
|
-
end
|
25
|
+
l_gain, r_gain = Utils.panning(pan)
|
26
|
+
hz = @note_perform.note.hz(semis: tune_semis, cents: tune_cents)
|
30
27
|
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
buffer = @source.next(context, AudioStream::Rate.freq(hz), sym, sync, l_gain, r_gain)
|
29
|
+
else
|
30
|
+
buffer = uni_num.ceil.times.map {|i|
|
31
|
+
context = @source_contexts[i]
|
34
32
|
|
35
|
-
|
33
|
+
uni_volume = 1.0
|
34
|
+
if uni_num<i
|
35
|
+
uni_volume = uni_num % 1.0
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
38
|
+
sign = i.even? ? 1 : -1
|
39
|
+
diff = sign * (i + 1.0) / (uni_num + 1.0)
|
39
40
|
|
40
|
-
|
41
|
-
|
41
|
+
detune_cents = uni_detune * diff * 100
|
42
|
+
diff_pan = uni_stereo * diff
|
43
|
+
|
44
|
+
l_gain, r_gain = Utils.panning(pan + diff_pan)
|
45
|
+
hz = @note_perform.note.hz(semis: tune_semis, cents: tune_cents + detune_cents)
|
46
|
+
|
47
|
+
@source.next(context, AudioStream::Rate.freq(hz), sym, sync, l_gain * uni_volume / uni_num, r_gain * uni_volume / uni_num)
|
48
|
+
}.inject(:+)
|
49
|
+
end
|
50
|
+
|
51
|
+
AudioStream::Buffer.new(*buffer.streams.map {|stream|
|
52
|
+
stream * volume
|
53
|
+
})
|
42
54
|
end
|
43
55
|
end
|
44
56
|
end
|
data/lib/synthesizer/version.rb
CHANGED