synthesizer 3.1.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/examples/{metronome.rb → audio_input_metronome.rb} +8 -2
  4. data/examples/{step_editor.rb → audio_input_step_editor.rb} +10 -2
  5. data/examples/filter_band_pass.rb +73 -0
  6. data/examples/{lpf.rb → filter_serial.rb} +9 -2
  7. data/examples/oscillator_pan.rb +70 -0
  8. data/examples/{formant_vocoder.rb → oscillator_source_formant_vocoder.rb} +10 -3
  9. data/examples/{formant_vocoder_sweep.rb → oscillator_source_formant_vocoder_sweep.rb} +13 -6
  10. data/examples/oscillator_sync.rb +71 -0
  11. data/examples/oscillator_unison.rb +64 -0
  12. data/examples/oscillator_volume.rb +70 -0
  13. data/examples/{mono.rb → synth_mono.rb} +10 -2
  14. data/examples/{poly.rb → synth_poly.rb} +10 -2
  15. data/{examples → jupyter}/adsr.ipynb +20 -17
  16. data/jupyter/curves.ipynb +103 -0
  17. data/jupyter/shapes.ipynb +111 -0
  18. data/lib/audio_stream/audio_input_metronome.rb +1 -1
  19. data/lib/synthesizer/amplifier.rb +4 -1
  20. data/lib/synthesizer/filter/band_pass_filter.rb +3 -3
  21. data/lib/synthesizer/filter/high_pass_filter.rb +3 -3
  22. data/lib/synthesizer/filter/high_shelf_filter.rb +4 -4
  23. data/lib/synthesizer/filter/low_pass_filter.rb +3 -3
  24. data/lib/synthesizer/filter/low_shelf_filter.rb +4 -4
  25. data/lib/synthesizer/filter/parallel.rb +2 -2
  26. data/lib/synthesizer/filter/peaking_filter.rb +5 -5
  27. data/lib/synthesizer/filter/serial.rb +2 -2
  28. data/lib/synthesizer/modulation/adsr.rb +37 -35
  29. data/lib/synthesizer/modulation/curve.rb +3 -0
  30. data/lib/synthesizer/modulation/glide.rb +9 -8
  31. data/lib/synthesizer/modulation/lfo.rb +23 -23
  32. data/lib/synthesizer/modulation_value.rb +5 -5
  33. data/lib/synthesizer/mono_synth.rb +7 -2
  34. data/lib/synthesizer/oscillator.rb +11 -9
  35. data/lib/synthesizer/oscillator_source/base.rb +35 -5
  36. data/lib/synthesizer/oscillator_source/formant_vocoder.rb +27 -19
  37. data/lib/synthesizer/oscillator_source/pulse.rb +11 -3
  38. data/lib/synthesizer/poly_synth.rb +5 -2
  39. data/lib/synthesizer/processor/high.rb +63 -0
  40. data/lib/synthesizer/processor/low.rb +59 -0
  41. data/lib/synthesizer/processor.rb +6 -44
  42. data/lib/synthesizer/quality.rb +6 -0
  43. data/lib/synthesizer/shape.rb +4 -4
  44. data/lib/synthesizer/shape_pos.rb +22 -19
  45. data/lib/synthesizer/unison.rb +28 -16
  46. data/lib/synthesizer/version.rb +1 -1
  47. data/lib/synthesizer.rb +1 -0
  48. data/samples/cinema.rb +730 -0
  49. data/samples/cinema_drum.wav +0 -0
  50. data/samples/daijoubu.rb +811 -0
  51. data/samples/daijoubu_drum.wav +0 -0
  52. data/samples/kira_power.rb +987 -0
  53. data/samples/kira_power_drum.wav +0 -0
  54. data/synthesizer.gemspec +1 -1
  55. metadata +32 -18
  56. data/examples/curves.ipynb +0 -105
  57. 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
- module Synthesizer
2
- class Processor
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
- uni_num = uni_num_mod[]
34
- uni_detune = uni_detune_mod[]
35
-
36
- buf = unison.next(uni_num, uni_detune, volume, pan, tune_semis, tune_cents)
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
@@ -0,0 +1,6 @@
1
+ module Synthesizer
2
+ module Quality
3
+ HIGH = :High
4
+ LOW = :Low
5
+ end
6
+ end
@@ -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
- def initialize(phase: 0.0, sync: nil)
4
- @init_phase = phase
5
- @sync = sync
3
+ SEMITONE_RATIO = 2.0 ** (1.0 / 12.0)
6
4
 
7
- @offset = 0
8
- @phase = 0.0
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(delta)
12
- @offset += 1
13
+ def next(hz, sym, sync)
14
+ if sync<0.0
15
+ sync = 0.0
16
+ end
13
17
 
14
- if @offset==1
15
- if @init_phase
16
- @phase = @init_phase + delta
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
@@ -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.ceil.times.map {|i|
24
- context = @source_contexts[i]
22
+ if uni_num==1.0
23
+ context = @source_contexts[0]
25
24
 
26
- uni_volume = 1.0
27
- if uni_num<i
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
- sign = i.even? ? 1 : -1
32
- detune_cents = sign * (i/2) * uni_detune * 100
33
- diff_pan = sign * (i/2) * uni_detune
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
- l_gain, r_gain = Utils.panning(pan + diff_pan)
33
+ uni_volume = 1.0
34
+ if uni_num<i
35
+ uni_volume = uni_num % 1.0
36
+ end
36
37
 
37
- hz = @note_perform.note.hz(semis: tune_semis, cents: tune_cents + detune_cents)
38
- delta = hz / @samplerate
38
+ sign = i.even? ? 1 : -1
39
+ diff = sign * (i + 1.0) / (uni_num + 1.0)
39
40
 
40
- @source.next(context, delta, l_gain * volume * uni_volume / uni_num, r_gain * volume * uni_volume / uni_num)
41
- }.inject(:+)
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
@@ -1,3 +1,3 @@
1
1
  module Synthesizer
2
- VERSION = "3.1.0"
2
+ VERSION = "3.4.0"
3
3
  end
data/lib/synthesizer.rb CHANGED
@@ -20,6 +20,7 @@ require 'synthesizer/note'
20
20
  require 'synthesizer/note_perform'
21
21
  require 'synthesizer/unison'
22
22
  require 'synthesizer/processor'
23
+ require 'synthesizer/quality'
23
24
  require 'synthesizer/utils'
24
25
 
25
26
  module Synthesizer