synthesizer 3.1.0 → 3.4.0

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.
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