synthesizer 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04ecefcdbf996dac3b8b38315ba0fa1c88ee9ce9a353ae13189c6f59d7ca764c
4
- data.tar.gz: 5804b29acadece1016f420b85ee2c7fc43521e0cf14dc633240b09f2d80fa1f5
3
+ metadata.gz: ab192c339eebdc39d867ac206c82454c8b3509f92967e54f4aa4f4660b2e3cdf
4
+ data.tar.gz: 86fadad577d12289b652be8bfa4ac55f6a6bad136fa5dc9ce21eac4df3f536e6
5
5
  SHA512:
6
- metadata.gz: bd465c0efba7fdf5608297fbd85214370328a801a97074d37670a19681a96045b68f7cbb18cb9af5d809a2a63f33d2219ef3c27319c517bba3c2a9c11c1102bd
7
- data.tar.gz: ee9e14bde33fbf7eff84b2b9c88afa4ff45ae8e73b6c170ef1e03fd95d0dda4562abecd58811da9a6f0e7dcf2cacfecab344624a4b0d2d4a5ba231697c460caa
6
+ metadata.gz: ce723ad9a5fd4817ce33f362fb15cdce50132b066c0aff60b203d13e04ab4bef99f947f6e4d871d2a24ad0a66b98aa1b899e72b579d23dbad64245b848ffc94d
7
+ data.tar.gz: c42def904f7c6531d2f68d1000c5cd0a4cc2b54088f7af0c3414d3ffa59d1da8750eca6efd961b987953cde385266f187066ca71ba4f41c3bf2798fb0f1fcec3
@@ -0,0 +1,78 @@
1
+ require 'synthesizer'
2
+ require 'audio_stream/core_ext'
3
+
4
+ include AudioStream
5
+ include Synthesizer
6
+
7
+ soundinfo = SoundInfo.new(
8
+ channels: 2,
9
+ samplerate: 44100,
10
+ window_size: 1024,
11
+ format: RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
12
+ )
13
+
14
+ synth = PolySynth.new(
15
+ oscillators: [
16
+ Oscillator.new(
17
+ shape: Shape::WhiteNoise
18
+ ),
19
+ ],
20
+ filter: Filter::Serial.new(
21
+ Filter::LowPassFilter.new(
22
+ freq: ModulationValue.new(440.0)
23
+ .add(Modulation::Adsr.new(
24
+ attack: 3.0,
25
+ hold: 0.0,
26
+ decay: 0.0,
27
+ sustain: 0.0,
28
+ release: 1.0
29
+ ), depth: 3000.0),
30
+ ),
31
+ Filter::HighPassFilter.new(
32
+ freq: ModulationValue.new(400.0)
33
+ .add(Modulation::Adsr.new(
34
+ attack: 3.0,
35
+ hold: 0.0,
36
+ decay: 0.0,
37
+ sustain: 0.0,
38
+ release: 1.0
39
+ ), depth: 3000.0),
40
+ ),
41
+ ),
42
+ amplifier: Amplifier.new(
43
+ volume: ModulationValue.new(1.0)
44
+ .add(Modulation::Adsr.new(
45
+ attack: 0.05,
46
+ hold: 0.1,
47
+ decay: 0.4,
48
+ sustain: 0.8,
49
+ release: 0.2
50
+ ), depth: 1.0),
51
+ ),
52
+ quality: Quality::LOW,
53
+ soundinfo: soundinfo,
54
+ )
55
+ bufs = []
56
+
57
+ synth.note_on(Note.new(60))
58
+ bufs += 100.times.map {|_| synth.next}
59
+
60
+ synth.note_off(Note.new(60))
61
+ bufs += 50.times.map {|_| synth.next}
62
+
63
+
64
+ track1 = AudioInput.buffer(bufs)
65
+
66
+ stereo_out = AudioOutput.device(soundinfo: soundinfo)
67
+
68
+ track1
69
+ .stream
70
+ .send_to(stereo_out, gain: 0.25)
71
+
72
+
73
+ conductor = Conductor.new(
74
+ input: [track1],
75
+ output: [stereo_out]
76
+ )
77
+ conductor.connect
78
+ conductor.join
@@ -2,6 +2,7 @@ require 'synthesizer'
2
2
  require 'audio_stream/core_ext'
3
3
 
4
4
  include AudioStream
5
+ include Synthesizer
5
6
 
6
7
  soundinfo = SoundInfo.new(
7
8
  channels: 2,
@@ -10,31 +11,31 @@ soundinfo = SoundInfo.new(
10
11
  format: RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
11
12
  )
12
13
 
13
- synth = Synthesizer::Mono.new(
14
+ synth = MonoSynth.new(
14
15
  oscillators: [
15
- Synthesizer::Oscillator.new(
16
- shape: Synthesizer::Shape::SquareSawtooth,
17
- uni_num: Synthesizer::ModulationValue.new(4),
18
- #.add(Synthesizer::Modulation::Lfo.new(
16
+ Oscillator.new(
17
+ shape: Shape::SquareSawtooth,
18
+ uni_num: ModulationValue.new(4),
19
+ #.add(Modulation::Lfo.new(
19
20
  #)),
20
21
  uni_detune: 0.1,
21
22
  ),
22
- #Synthesizer::Oscillator.new(
23
- # shape: Synthesizer::Shape::SquareSawtooth,
23
+ #Oscillator.new(
24
+ # shape: Shape::SquareSawtooth,
24
25
  # tune_cents: 0.1,
25
26
  # uni_num: 4,
26
27
  # uni_detune: 0.1,
27
28
  #),
28
- #Synthesizer::Oscillator.new(
29
- # shape: Synthesizer::Shape::SquareSawtooth,
29
+ #Oscillator.new(
30
+ # shape: Shape::SquareSawtooth,
30
31
  # tune_semis: -12,
31
32
  # uni_num: 4,
32
33
  # uni_detune: 0.1,
33
34
  #),
34
35
  ],
35
- amplifier: Synthesizer::Amplifier.new(
36
- volume: Synthesizer::ModulationValue.new(1.0)
37
- .add(Synthesizer::Modulation::Adsr.new(
36
+ amplifier: Amplifier.new(
37
+ volume: ModulationValue.new(1.0)
38
+ .add(Modulation::Adsr.new(
38
39
  attack: 0.05,
39
40
  hold: 0.1,
40
41
  decay: 0.4,
@@ -43,28 +44,28 @@ synth = Synthesizer::Mono.new(
43
44
  ), depth: 1.0),
44
45
  ),
45
46
  glide: 0.2,
46
- quality: Synthesizer::Quality::LOW,
47
+ quality: Quality::LOW,
47
48
  soundinfo: soundinfo,
48
49
  )
49
50
  bufs = []
50
51
 
51
- synth.note_on(Synthesizer::Note.new(60))
52
+ synth.note_on(Note.new(60))
52
53
  bufs += 50.times.map {|_| synth.next}
53
- synth.note_on(Synthesizer::Note.new(62))
54
+ synth.note_on(Note.new(62))
54
55
  bufs += 50.times.map {|_| synth.next}
55
- synth.note_on(Synthesizer::Note.new(64))
56
+ synth.note_on(Note.new(64))
56
57
  bufs += 50.times.map {|_| synth.next}
57
- synth.note_on(Synthesizer::Note.new(62))
58
+ synth.note_on(Note.new(62))
58
59
  bufs += 50.times.map {|_| synth.next}
59
60
 
60
- synth.note_off(Synthesizer::Note.new(62))
61
+ synth.note_off(Note.new(62))
61
62
  bufs += 50.times.map {|_| synth.next}
62
- synth.note_off(Synthesizer::Note.new(64))
63
+ synth.note_off(Note.new(64))
63
64
  bufs += 50.times.map {|_| synth.next}
64
- synth.note_off(Synthesizer::Note.new(60))
65
- synth.note_on(Synthesizer::Note.new(65))
65
+ synth.note_off(Note.new(60))
66
+ synth.note_on(Note.new(65))
66
67
  bufs += 50.times.map {|_| synth.next}
67
- synth.note_off(Synthesizer::Note.new(65))
68
+ synth.note_off(Note.new(65))
68
69
  bufs += 50.times.map {|_| synth.next}
69
70
 
70
71
 
@@ -2,6 +2,7 @@ require 'synthesizer'
2
2
  require 'audio_stream/core_ext'
3
3
 
4
4
  include AudioStream
5
+ include Synthesizer
5
6
 
6
7
  soundinfo = SoundInfo.new(
7
8
  channels: 2,
@@ -10,31 +11,31 @@ soundinfo = SoundInfo.new(
10
11
  format: RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
11
12
  )
12
13
 
13
- synth = Synthesizer::Poly.new(
14
+ synth = PolySynth.new(
14
15
  oscillators: [
15
- Synthesizer::Oscillator.new(
16
- shape: Synthesizer::Shape::SquareSawtooth,
17
- uni_num: Synthesizer::ModulationValue.new(4)
18
- .add(Synthesizer::Modulation::Lfo.new(
16
+ Oscillator.new(
17
+ shape: Shape::SquareSawtooth,
18
+ uni_num: ModulationValue.new(4)
19
+ .add(Modulation::Lfo.new(
19
20
  )),
20
21
  uni_detune: 0.1,
21
22
  ),
22
- #Synthesizer::Oscillator.new(
23
- # shape: Synthesizer::Shape::SquareSawtooth,
23
+ #Oscillator.new(
24
+ # shape: Shape::SquareSawtooth,
24
25
  # tune_cents: 0.1,
25
26
  # uni_num: 4,
26
27
  # uni_detune: 0.1,
27
28
  #),
28
- #Synthesizer::Oscillator.new(
29
- # shape: Synthesizer::Shape::SquareSawtooth,
29
+ #Oscillator.new(
30
+ # shape: Shape::SquareSawtooth,
30
31
  # tune_semis: -12,
31
32
  # uni_num: 4,
32
33
  # uni_detune: 0.1,
33
34
  #),
34
35
  ],
35
- amplifier: Synthesizer::Amplifier.new(
36
- volume: Synthesizer::ModulationValue.new(1.0)
37
- .add(Synthesizer::Modulation::Adsr.new(
36
+ amplifier: Amplifier.new(
37
+ volume: ModulationValue.new(1.0)
38
+ .add(Modulation::Adsr.new(
38
39
  attack: 0.05,
39
40
  hold: 0.1,
40
41
  decay: 0.4,
@@ -42,23 +43,23 @@ synth = Synthesizer::Poly.new(
42
43
  release: 0.2
43
44
  ), depth: 1.0),
44
45
  ),
45
- quality: Synthesizer::Quality::LOW,
46
+ quality: Quality::LOW,
46
47
  soundinfo: soundinfo,
47
48
  )
48
49
  bufs = []
49
50
 
50
- synth.note_on(Synthesizer::Note.new(60))
51
- synth.note_on(Synthesizer::Note.new(62))
52
- synth.note_on(Synthesizer::Note.new(64))
51
+ synth.note_on(Note.new(60))
52
+ synth.note_on(Note.new(62))
53
+ synth.note_on(Note.new(64))
53
54
  bufs += 10.times.map {|_| synth.next}
54
55
  synth.pitch_bend = 1
55
56
  bufs += 10.times.map {|_| synth.next}
56
57
  synth.pitch_bend = 2
57
58
  bufs += 10.times.map {|_| synth.next}
58
59
 
59
- synth.note_off(Synthesizer::Note.new(60))
60
- synth.note_off(Synthesizer::Note.new(62))
61
- synth.note_off(Synthesizer::Note.new(64))
60
+ synth.note_off(Note.new(60))
61
+ synth.note_off(Note.new(62))
62
+ synth.note_off(Note.new(64))
62
63
  bufs += 50.times.map {|_| synth.next}
63
64
 
64
65
 
@@ -4,9 +4,10 @@ require 'audio_stream'
4
4
  require 'audio_stream/audio_input_synth.rb'
5
5
  require 'audio_stream/audio_input_metronome.rb'
6
6
 
7
- require 'synthesizer/poly'
8
- require 'synthesizer/mono'
7
+ require 'synthesizer/poly_synth'
8
+ require 'synthesizer/mono_synth'
9
9
  require 'synthesizer/oscillator'
10
+ require 'synthesizer/filter'
10
11
  require 'synthesizer/amplifier'
11
12
  require 'synthesizer/shape'
12
13
  require 'synthesizer/shape_pos'
@@ -0,0 +1,14 @@
1
+ require 'synthesizer/filter/low_pass_filter'
2
+ require 'synthesizer/filter/high_pass_filter'
3
+ require 'synthesizer/filter/band_pass_filter'
4
+ require 'synthesizer/filter/low_shelf_filter'
5
+ require 'synthesizer/filter/high_shelf_filter'
6
+ require 'synthesizer/filter/peaking_filter'
7
+
8
+ require 'synthesizer/filter/serial'
9
+ require 'synthesizer/filter/parallel'
10
+
11
+ module Synthesizer
12
+ module Filter
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ module Synthesizer
2
+ module Filter
3
+ class BandPassFilter
4
+ def initialize(freq:, bandwidth:)
5
+ @freq = ModulationValue.create(freq)
6
+ @bandwidth = ModulationValue.create(bandwidth)
7
+ end
8
+
9
+ def generator(note_perform, framerate, &block)
10
+ Enumerator.new do |y|
11
+ soundinfo = note_perform.synth.soundinfo
12
+ filter = AudioStream::Fx::BandPassFilter.new(soundinfo)
13
+
14
+ freq_mod = ModulationValue.balance_generator(note_perform, framerate, @freq)
15
+ bandwidth_mod = ModulationValue.balance_generator(note_perform, framerate, @bandwidth)
16
+
17
+ loop {
18
+ filter.update_coef(freq: freq_mod.next, bandwidth: bandwidth_mod.next)
19
+ y << filter
20
+ }
21
+ end.each(&block)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ module Synthesizer
2
+ module Filter
3
+ class HighPassFilter
4
+ def initialize(freq:, q: nil)
5
+ @freq = ModulationValue.create(freq)
6
+ @q = ModulationValue.create(q || 1.0 / Math.sqrt(2))
7
+ end
8
+
9
+ def generator(note_perform, framerate, &block)
10
+ Enumerator.new do |y|
11
+ soundinfo = note_perform.synth.soundinfo
12
+ filter = AudioStream::Fx::HighPassFilter.new(soundinfo)
13
+
14
+ freq_mod = ModulationValue.balance_generator(note_perform, framerate, @freq)
15
+ q_mod = ModulationValue.balance_generator(note_perform, framerate, @q)
16
+
17
+ loop {
18
+ filter.update_coef(freq: freq_mod.next, q: q_mod.next)
19
+ y << filter
20
+ }
21
+ end.each(&block)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ module Synthesizer
2
+ module Filter
3
+ class HighShelfFilter
4
+ def initialize(freq:, q: nil, gain:)
5
+ @freq = ModulationValue.create(freq)
6
+ @q = ModulationValue.create(q || 1.0 / Math.sqrt(2))
7
+ @gain = ModulationValue.create(gain)
8
+ end
9
+
10
+ def generator(note_perform, framerate, &block)
11
+ Enumerator.new do |y|
12
+ soundinfo = note_perform.synth.soundinfo
13
+ filter = AudioStream::Fx::HighShelfFilter.new(soundinfo)
14
+
15
+ freq_mod = ModulationValue.balance_generator(note_perform, framerate, @freq)
16
+ q_mod = ModulationValue.balance_generator(note_perform, framerate, @q)
17
+ gain_mod = ModulationValue.balance_generator(note_perform, framerate, @gain)
18
+
19
+ loop {
20
+ filter.update_coef(freq: freq_mod.next, q: q_mod.next, gain: gain_mod.next)
21
+ y << filter
22
+ }
23
+ end.each(&block)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ module Synthesizer
2
+ module Filter
3
+ class LowPassFilter
4
+ def initialize(freq:, q: nil)
5
+ @freq = ModulationValue.create(freq)
6
+ @q = ModulationValue.create(q || 1.0 / Math.sqrt(2))
7
+ end
8
+
9
+ def generator(note_perform, framerate, &block)
10
+ Enumerator.new do |y|
11
+ soundinfo = note_perform.synth.soundinfo
12
+ filter = AudioStream::Fx::LowPassFilter.new(soundinfo)
13
+
14
+ freq_mod = ModulationValue.balance_generator(note_perform, framerate, @freq)
15
+ q_mod = ModulationValue.balance_generator(note_perform, framerate, @q)
16
+
17
+ loop {
18
+ filter.update_coef(freq: freq_mod.next, q: q_mod.next)
19
+ y << filter
20
+ }
21
+ end.each(&block)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ module Synthesizer
2
+ module Filter
3
+ class LowShelfFilter
4
+ def initialize(freq:, q: nil, gain:)
5
+ @freq = ModulationValue.create(freq)
6
+ @q = ModulationValue.create(q || 1.0 / Math.sqrt(2))
7
+ @gain = ModulationValue.create(gain)
8
+ end
9
+
10
+ def generator(note_perform, framerate, &block)
11
+ Enumerator.new do |y|
12
+ soundinfo = note_perform.synth.soundinfo
13
+ filter = AudioStream::Fx::LowShelfFilter.new(soundinfo)
14
+
15
+ freq_mod = ModulationValue.balance_generator(note_perform, framerate, @freq)
16
+ q_mod = ModulationValue.balance_generator(note_perform, framerate, @q)
17
+ gain_mod = ModulationValue.balance_generator(note_perform, framerate, @gain)
18
+
19
+ loop {
20
+ filter.update_coef(freq: freq_mod.next, q: q_mod.next, gain: gain_mod.next)
21
+ y << filter
22
+ }
23
+ end.each(&block)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,57 @@
1
+ module Synthesizer
2
+ module Filter
3
+ class Parallel
4
+ def initialize(*filters)
5
+ @filters = filters
6
+ end
7
+
8
+ def generator(note_perform, framerate, &block)
9
+ Enumerator.new do |y|
10
+ filter_mods = @filters.map {|filter|
11
+ filter.generator(note_perform, framerate)
12
+ }
13
+
14
+ loop {
15
+ fxs = filter_mods.map(&:next)
16
+ y << Fx.new(fxs)
17
+ }
18
+ end.each(&block)
19
+ end
20
+
21
+ class Fx
22
+ include AudioStream::Fx::BangProcess
23
+
24
+ def initialize(fxs)
25
+ @fxs = fxs
26
+ end
27
+
28
+ def process!(input)
29
+ window_size = input.size
30
+ channels = input.channels
31
+ fx_size = @fxs.size
32
+
33
+ outputs = @fxs.map {|fx|
34
+ fx.process(input)
35
+ }
36
+
37
+ case channels
38
+ when 1
39
+ input.size.times {|i|
40
+ input[i] = outputs.map{|buf| buf[i]}.sum / fx_size
41
+ }
42
+ when 2
43
+ input.size.times {|i|
44
+ samples = outputs.map{|buf| buf[i]}
45
+ input[i] = [
46
+ samples.map{|sval| sval[0]}.sum / fx_size,
47
+ samples.map{|sval| sval[1]}.sum / fx_size
48
+ ]
49
+ }
50
+ end
51
+
52
+ input
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,27 @@
1
+ module Synthesizer
2
+ module Filter
3
+ class PeakingFilter
4
+ def initialize(freq:, bandwidth: 1.0, gain:)
5
+ @freq = ModulationValue.create(freq)
6
+ @bandwidth = ModulationValue.create(bandwidth)
7
+ @gain = ModulationValue.create(gain)
8
+ end
9
+
10
+ def generator(note_perform, framerate, &block)
11
+ Enumerator.new do |y|
12
+ soundinfo = note_perform.synth.soundinfo
13
+ filter = AudioStream::Fx::LowShelfFilter.new(soundinfo)
14
+
15
+ freq_mod = ModulationValue.balance_generator(note_perform, framerate, @freq)
16
+ bandwidth_mod = ModulationValue.balance_generator(note_perform, framerate, @bandwidth)
17
+ gain_mod = ModulationValue.balance_generator(note_perform, framerate, @gain)
18
+
19
+ loop {
20
+ filter.update_coef(freq: freq_mod.next, bandwidth: bandwidth_mod.next, gain: gain_mod.next)
21
+ y << filter
22
+ }
23
+ end.each(&block)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ module Synthesizer
2
+ module Filter
3
+ class Serial
4
+ def initialize(*filters)
5
+ @filters = filters
6
+ end
7
+
8
+ def generator(note_perform, framerate, &block)
9
+ Enumerator.new do |y|
10
+ filter_mods = @filters.map {|filter|
11
+ filter.generator(note_perform, framerate)
12
+ }
13
+
14
+ loop {
15
+ fxs = filter_mods.map(&:next)
16
+ y << Fx.new(fxs)
17
+ }
18
+ end.each(&block)
19
+ end
20
+
21
+ class Fx
22
+ include AudioStream::Fx::BangProcess
23
+
24
+ def initialize(fxs)
25
+ @fxs = fxs
26
+ end
27
+
28
+ def process!(input)
29
+ @fxs.each {|fx|
30
+ fx.process!(input)
31
+ }
32
+ input
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -21,10 +21,10 @@ module Synthesizer
21
21
  @release_curve = release_curve
22
22
  end
23
23
 
24
- def note_on_envelope(samplerate, sustain: false, &block)
24
+ def note_on_envelope(framerate, sustain: false, &block)
25
25
  Enumerator.new do |yld|
26
26
  # attack
27
- rate = @attack * samplerate
27
+ rate = @attack * framerate
28
28
  rate.to_i.times {|i|
29
29
  x = i.to_f / rate
30
30
  y = @attack_curve[x]
@@ -32,13 +32,13 @@ module Synthesizer
32
32
  }
33
33
 
34
34
  # hold
35
- rate = @hold * samplerate
35
+ rate = @hold * framerate
36
36
  rate.to_i.times {|i|
37
37
  yld << 1.0
38
38
  }
39
39
 
40
40
  # decay
41
- rate = @decay * samplerate
41
+ rate = @decay * framerate
42
42
  rate.to_i.times {|i|
43
43
  x = i.to_f / rate
44
44
  y = 1.0 - @sustain_curve[x] * (1.0 - @sustain)
@@ -54,10 +54,10 @@ module Synthesizer
54
54
  end.each(&block)
55
55
  end
56
56
 
57
- def note_off_envelope(samplerate, sustain: false, &block)
57
+ def note_off_envelope(framerate, sustain: false, &block)
58
58
  Enumerator.new do |yld|
59
59
  # release
60
- rate = @release * samplerate
60
+ rate = @release * framerate
61
61
  rate.to_i.times {|i|
62
62
  x = i.to_f / rate
63
63
  y = 1.0 - @release_curve[x]
@@ -73,10 +73,10 @@ module Synthesizer
73
73
  end.each(&block)
74
74
  end
75
75
 
76
- def generator(note_perform, samplerate, release_sustain:, &block)
76
+ def generator(note_perform, framerate, release_sustain:, &block)
77
77
  Enumerator.new do |y|
78
- note_on = note_on_envelope(samplerate, sustain: true)
79
- note_off = note_off_envelope(samplerate, sustain: release_sustain)
78
+ note_on = note_on_envelope(framerate, sustain: true)
79
+ note_off = note_off_envelope(framerate, sustain: release_sustain)
80
80
  last = 0.0
81
81
 
82
82
  loop {
@@ -91,23 +91,23 @@ module Synthesizer
91
91
  end
92
92
 
93
93
 
94
- def amp_generator(note_perform, samplerate, depth, &block)
94
+ def amp_generator(note_perform, framerate, depth, &block)
95
95
  bottom = 1.0 - depth
96
96
 
97
- generator(note_perform, samplerate, release_sustain: 0.0<bottom).lazy.map {|val|
97
+ generator(note_perform, framerate, release_sustain: 0.0<bottom).lazy.map {|val|
98
98
  val * depth + bottom
99
99
  }.each(&block)
100
100
  end
101
101
 
102
- def balance_generator(note_perform, samplerate, depth, &block)
103
- generator(note_perform, samplerate).lazy.map {|val|
102
+ def balance_generator(note_perform, framerate, depth, &block)
103
+ generator(note_perform, framerate, release_sustain: true).lazy.map {|val|
104
104
  val * depth
105
105
  }.each(&block)
106
106
  end
107
107
 
108
- def plot_data(samplerate: 44100)
109
- note_on = note_on_envelope(samplerate, sustain: false)
110
- note_off = note_off_envelope(samplerate, sustain: false)
108
+ def plot_data(framerate: 44100)
109
+ note_on = note_on_envelope(framerate, sustain: false)
110
+ note_off = note_off_envelope(framerate, sustain: false)
111
111
  last = 0.0
112
112
 
113
113
  xs = []
@@ -127,8 +127,8 @@ module Synthesizer
127
127
  {x: xs, y: ys}
128
128
  end
129
129
 
130
- def plot(samplerate: 44100)
131
- data = plot_data(samplerate: samplerate)
130
+ def plot(framerate: 44100)
131
+ data = plot_data(framerate: framerate)
132
132
  Plotly::Plot.new(data: [data])
133
133
  end
134
134
  end
@@ -17,20 +17,20 @@ module Synthesizer
17
17
  @rate = rate
18
18
  end
19
19
 
20
- def generator(note_perform, samplerate, &block)
20
+ def generator(note_perform, framerate, &block)
21
21
  Enumerator.new do |yld|
22
- delta = @rate / samplerate
22
+ delta = @rate / framerate
23
23
 
24
24
  pos = ShapePos.new(phase: @phase)
25
25
 
26
26
  # delay
27
- rate = @delay * samplerate
27
+ rate = @delay * framerate
28
28
  rate.to_i.times {|i|
29
29
  yld << 0.0
30
30
  }
31
31
 
32
32
  # attack
33
- rate = @attack * samplerate
33
+ rate = @attack * framerate
34
34
  rate.to_i.times {|i|
35
35
  x = i.to_f / rate
36
36
  y = @attack_curve[x]
@@ -45,17 +45,17 @@ module Synthesizer
45
45
  end.each(&block)
46
46
  end
47
47
 
48
- def amp_generator(note_perform, samplerate, depth, &block)
48
+ def amp_generator(note_perform, framerate, depth, &block)
49
49
  bottom = 1.0 - depth
50
50
 
51
- generator(note_perform, samplerate).lazy.map {|val|
51
+ generator(note_perform, framerate).lazy.map {|val|
52
52
  val = (val + 1) / 2
53
53
  val * depth + bottom
54
54
  }.each(&block)
55
55
  end
56
56
 
57
- def balance_generator(note_perform, samplerate, depth, &block)
58
- generator(note_perform, samplerate).lazy.map {|val|
57
+ def balance_generator(note_perform, framerate, depth, &block)
58
+ generator(note_perform, framerate).lazy.map {|val|
59
59
  val * depth
60
60
  }.each(&block)
61
61
  end
@@ -14,14 +14,14 @@ module Synthesizer
14
14
  end
15
15
 
16
16
  # @param mod [Synthesizer::Modulation]
17
- # @param depth [Float] (-1.0~1.0)
17
+ # @param depth [Float] depth. volume => percent(-1.0~1.0, default=1.0), filter freq => relative value(hz), other => relative value
18
18
  def add(mod, depth: 1.0)
19
19
  depth ||= 1.0
20
- if depth<-1.0
21
- depth = -1.0
22
- elsif 1.0<depth
23
- depth = 1.0
24
- end
20
+ #if depth<-1.0
21
+ # depth = -1.0
22
+ #elsif 1.0<depth
23
+ # depth = 1.0
24
+ #end
25
25
 
26
26
  @mods << [mod, depth]
27
27
  self
@@ -35,7 +35,7 @@ module Synthesizer
35
35
  end
36
36
  end
37
37
 
38
- def self.amp_generator(note_perform, samplerate, *modvals)
38
+ def self.amp_generator(note_perform, framerate, *modvals)
39
39
  modvals = modvals.flatten.compact
40
40
 
41
41
  # value
@@ -45,7 +45,7 @@ module Synthesizer
45
45
  mods = []
46
46
  modvals.each {|modval|
47
47
  modval.mods.each {|mod, depth|
48
- mods << mod.amp_generator(note_perform, samplerate, depth)
48
+ mods << mod.amp_generator(note_perform, framerate, depth)
49
49
  }
50
50
  }
51
51
 
@@ -57,7 +57,7 @@ module Synthesizer
57
57
  end
58
58
  end
59
59
 
60
- def self.balance_generator(note_perform, samplerate, *modvals, center: 0)
60
+ def self.balance_generator(note_perform, framerate, *modvals, center: 0)
61
61
  modvals = modvals.flatten.compact
62
62
 
63
63
  # value
@@ -68,7 +68,7 @@ module Synthesizer
68
68
  mods = []
69
69
  modvals.each {|modval|
70
70
  modval.mods.each {|mod, depth|
71
- mods << mod.balance_generator(note_perform, samplerate, depth)
71
+ mods << mod.balance_generator(note_perform, framerate, depth)
72
72
  }
73
73
  }
74
74
 
@@ -1,7 +1,8 @@
1
1
  module Synthesizer
2
- class Mono
2
+ class MonoSynth
3
3
 
4
4
  attr_reader :oscillators
5
+ attr_reader :filter
5
6
  attr_reader :amplifier
6
7
  attr_reader :processor
7
8
 
@@ -14,8 +15,9 @@ module Synthesizer
14
15
  # @param oscillators [Synthesizer::Oscillator] oscillator
15
16
  # @param amplifier [Synthesizer::Amplifier] amplifier
16
17
  # @param soundinfo [AudioStream::SoundInfo]
17
- def initialize(oscillators:, amplifier:, glide: 0.1, quality: Quality::LOW, soundinfo:)
18
+ def initialize(oscillators:, filter: nil, amplifier:, glide: 0.1, quality: Quality::LOW, soundinfo:)
18
19
  @oscillators = [oscillators].flatten.compact
20
+ @filter = filter
19
21
  @amplifier = amplifier
20
22
 
21
23
  @quality = quality
@@ -1,7 +1,8 @@
1
1
  module Synthesizer
2
- class Poly
2
+ class PolySynth
3
3
 
4
4
  attr_reader :oscillators
5
+ attr_reader :filter
5
6
  attr_reader :amplifier
6
7
  attr_reader :processor
7
8
 
@@ -12,10 +13,12 @@ module Synthesizer
12
13
  attr_accessor :pitch_bend
13
14
 
14
15
  # @param oscillators [Synthesizer::Oscillator] Oscillator
16
+ # @param filter [Synthesizer::Filter] filter
15
17
  # @param amplifier [Synthesizer::Amplifier] amplifier
16
18
  # @param soundinfo [AudioStream::SoundInfo]
17
- def initialize(oscillators:, amplifier:, quality: Quality::LOW, soundinfo:)
19
+ def initialize(oscillators:, filter: nil, amplifier:, quality: Quality::LOW, soundinfo:)
18
20
  @oscillators = [oscillators].flatten.compact
21
+ @filter = filter
19
22
  @amplifier = amplifier
20
23
 
21
24
  @quality = quality
@@ -4,26 +4,35 @@ module Synthesizer
4
4
  def generator(osc, note_perform, &block)
5
5
  Enumerator.new do |y|
6
6
  synth = note_perform.synth
7
+ filter = synth.filter
7
8
  amp = synth.amplifier
8
9
  channels = synth.soundinfo.channels
9
10
  window_size = synth.soundinfo.window_size
10
- samplerate = synth.soundinfo.samplerate
11
+ framerate = synth.soundinfo.samplerate
11
12
 
12
- volume_mod = ModulationValue.amp_generator(note_perform, samplerate, osc.volume, amp.volume)
13
- pan_mod = ModulationValue.balance_generator(note_perform, samplerate, osc.pan, amp.pan)
14
- tune_semis_mod = ModulationValue.balance_generator(note_perform, samplerate, osc.tune_semis, amp.tune_semis, synth.glide&.to_modval)
15
- tune_cents_mod = ModulationValue.balance_generator(note_perform, samplerate, osc.tune_cents, amp.tune_cents)
13
+ # Oscillator, Amplifier
14
+ volume_mod = ModulationValue.amp_generator(note_perform, framerate, osc.volume, amp.volume)
15
+ pan_mod = ModulationValue.balance_generator(note_perform, framerate, osc.pan, amp.pan)
16
+ tune_semis_mod = ModulationValue.balance_generator(note_perform, framerate, osc.tune_semis, amp.tune_semis, synth.glide&.to_modval)
17
+ tune_cents_mod = ModulationValue.balance_generator(note_perform, framerate, osc.tune_cents, amp.tune_cents)
16
18
 
17
- uni_num_mod = ModulationValue.balance_generator(note_perform, samplerate, osc.uni_num, amp.uni_num, center: 1.0)
18
- uni_detune_mod = ModulationValue.balance_generator(note_perform, samplerate, osc.uni_detune, amp.uni_detune)
19
+ uni_num_mod = ModulationValue.balance_generator(note_perform, framerate, osc.uni_num, amp.uni_num, center: 1.0)
20
+ uni_detune_mod = ModulationValue.balance_generator(note_perform, framerate, osc.uni_detune, amp.uni_detune)
19
21
  unison = Unison.new(note_perform, osc.shape, osc.phase)
20
22
 
23
+ # Filter
24
+ filter_mod = nil
25
+ if filter
26
+ filter_mod = filter.generator(note_perform, framerate)
27
+ end
28
+
21
29
  case channels
22
30
  when 1
23
31
  loop {
24
32
  buf = AudioStream::Buffer.float(window_size, channels)
25
33
 
26
34
  window_size.times.each {|i|
35
+ # Oscillator, Amplifier
27
36
  volume = volume_mod.next
28
37
  tune_semis = tune_semis_mod.next + synth.pitch_bend
29
38
  tune_cents = tune_cents_mod.next
@@ -31,8 +40,16 @@ module Synthesizer
31
40
  uni_num = uni_num_mod.next
32
41
  uni_detune = uni_detune_mod.next
33
42
 
34
- val = unison.next(uni_num, uni_detune, volume, 0.0, tune_semis, tune_cents)
35
- buf[i] = (val[0] + val[1]) / 2.0
43
+ sval = unison.next(uni_num, uni_detune, volume, 0.0, tune_semis, tune_cents)
44
+ mval = (sval[0] + sval[1]) / 2.0
45
+
46
+ # Filter
47
+ if filter_mod
48
+ filter_fx = filter_mod.next
49
+ mval = filter_fx.process_mono(mval)
50
+ end
51
+
52
+ buf[i] = mval
36
53
  }
37
54
 
38
55
  y << buf
@@ -42,6 +59,7 @@ module Synthesizer
42
59
  buf = AudioStream::Buffer.float(window_size, channels)
43
60
 
44
61
  window_size.times.each {|i|
62
+ # Oscillator, Amplifier
45
63
  volume = volume_mod.next
46
64
  pan = pan_mod.next
47
65
  tune_semis = tune_semis_mod.next + synth.pitch_bend
@@ -50,7 +68,15 @@ module Synthesizer
50
68
  uni_num = uni_num_mod.next
51
69
  uni_detune = uni_detune_mod.next
52
70
 
53
- buf[i] = unison.next(uni_num, uni_detune, volume, pan, tune_semis, tune_cents)
71
+ sval = unison.next(uni_num, uni_detune, volume, pan, tune_semis, tune_cents)
72
+
73
+ # Filter
74
+ if filter_mod
75
+ filter_fx = filter_mod.next
76
+ sval = filter_fx.process_stereo(sval)
77
+ end
78
+
79
+ buf[i] = sval
54
80
  }
55
81
 
56
82
  y << buf
@@ -4,25 +4,34 @@ module Synthesizer
4
4
  def generator(osc, note_perform, &block)
5
5
  Enumerator.new do |y|
6
6
  synth = note_perform.synth
7
+ filter = synth.filter
7
8
  amp = synth.amplifier
8
9
  channels = synth.soundinfo.channels
9
10
  window_size = synth.soundinfo.window_size
10
- samplerate = synth.soundinfo.samplerate.to_f / window_size
11
+ framerate = synth.soundinfo.samplerate.to_f / window_size
11
12
 
12
- volume_mod = ModulationValue.amp_generator(note_perform, samplerate, osc.volume, amp.volume)
13
- pan_mod = ModulationValue.balance_generator(note_perform, samplerate, osc.pan, amp.pan)
14
- tune_semis_mod = ModulationValue.balance_generator(note_perform, samplerate, osc.tune_semis, amp.tune_semis, synth.glide&.to_modval)
15
- tune_cents_mod = ModulationValue.balance_generator(note_perform, samplerate, osc.tune_cents, amp.tune_cents)
13
+ # Oscillator, Amplifier
14
+ volume_mod = ModulationValue.amp_generator(note_perform, framerate, osc.volume, amp.volume)
15
+ pan_mod = ModulationValue.balance_generator(note_perform, framerate, osc.pan, amp.pan)
16
+ tune_semis_mod = ModulationValue.balance_generator(note_perform, framerate, osc.tune_semis, amp.tune_semis, synth.glide&.to_modval)
17
+ tune_cents_mod = ModulationValue.balance_generator(note_perform, framerate, osc.tune_cents, amp.tune_cents)
16
18
 
17
- uni_num_mod = ModulationValue.balance_generator(note_perform, samplerate, osc.uni_num, amp.uni_num, center: 1.0)
18
- uni_detune_mod = ModulationValue.balance_generator(note_perform, samplerate, osc.uni_detune, amp.uni_detune)
19
+ uni_num_mod = ModulationValue.balance_generator(note_perform, framerate, osc.uni_num, amp.uni_num, center: 1.0)
20
+ uni_detune_mod = ModulationValue.balance_generator(note_perform, framerate, osc.uni_detune, amp.uni_detune)
19
21
  unison = Unison.new(note_perform, osc.shape, osc.phase)
20
22
 
23
+ # Filter
24
+ filter_mod = nil
25
+ if filter
26
+ filter_mod = filter.generator(note_perform, framerate)
27
+ end
28
+
21
29
  case channels
22
30
  when 1
23
31
  loop {
24
32
  buf = AudioStream::Buffer.float(window_size, channels)
25
33
 
34
+ # Oscillator, Amplifier
26
35
  volume = volume_mod.next
27
36
  tune_semis = tune_semis_mod.next + synth.pitch_bend
28
37
  tune_cents = tune_cents_mod.next
@@ -35,12 +44,19 @@ module Synthesizer
35
44
  buf[i] = (val[0] + val[1]) / 2.0
36
45
  }
37
46
 
47
+ # Filter
48
+ if filter_mod
49
+ filter_fx = filter_mod.next
50
+ filter_fx.process!(buf)
51
+ end
52
+
38
53
  y << buf
39
54
  }
40
55
  when 2
41
56
  loop {
42
57
  buf = AudioStream::Buffer.float(window_size, channels)
43
58
 
59
+ # Oscillator, Amplifier
44
60
  volume = volume_mod.next
45
61
  pan = pan_mod.next
46
62
  tune_semis = tune_semis_mod.next + synth.pitch_bend
@@ -53,6 +69,12 @@ module Synthesizer
53
69
  buf[i] = unison.next(uni_num, uni_detune, volume, pan, tune_semis, tune_cents)
54
70
  }
55
71
 
72
+ # Filter
73
+ if filter_mod
74
+ filter_fx = filter_mod.next
75
+ filter_fx.process!(buf)
76
+ end
77
+
56
78
  y << buf
57
79
  }
58
80
  end
@@ -5,7 +5,7 @@ module Synthesizer
5
5
  Sawtooth = ->(phase) { ((phase + 0.5) % 1) * 2 - 1 }
6
6
  Square = ->(phase) { 0.5<=((phase + 0.5) % 1) ? 1.0 : -1.0 }
7
7
  Triangle = ->(phase) {
8
- t = ((phase*4).floor % 4);
8
+ t = ((phase*4).floor % 4)
9
9
  t==0 ? (phase % 0.5)*4 :
10
10
  t==1 ? (2-(phase % 0.5)*4) :
11
11
  t==2 ? (-(phase % 0.5)*4) : (phase % 0.5)*4-2
@@ -1,3 +1,3 @@
1
1
  module Synthesizer
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -30,10 +30,5 @@ Gem::Specification.new do |spec|
30
30
  spec.add_development_dependency "rake", "~> 12.0"
31
31
  spec.add_development_dependency "minitest", "~> 5.0"
32
32
 
33
- spec.add_dependency "audio_stream", ">= 1.0"
34
- spec.add_dependency "ruby-audio", ">= 1.6.1"
35
- spec.add_dependency "coreaudio", ">= 0.0.12"
36
- spec.add_dependency "ruby-fftw3", ">= 1.0.2"
37
- spec.add_dependency "rx", ">= 0.0.3"
38
- spec.add_dependency "rbplotly", ">= 0.1.2"
33
+ spec.add_dependency "audio_stream", ">= 1.2.1"
39
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synthesizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoshida Tetsuya
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-17 00:00:00.000000000 Z
11
+ date: 2019-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -58,84 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.0'
61
+ version: 1.2.1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '1.0'
69
- - !ruby/object:Gem::Dependency
70
- name: ruby-audio
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: 1.6.1
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: 1.6.1
83
- - !ruby/object:Gem::Dependency
84
- name: coreaudio
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: 0.0.12
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: 0.0.12
97
- - !ruby/object:Gem::Dependency
98
- name: ruby-fftw3
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: 1.0.2
104
- type: :runtime
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: 1.0.2
111
- - !ruby/object:Gem::Dependency
112
- name: rx
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: 0.0.3
118
- type: :runtime
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: 0.0.3
125
- - !ruby/object:Gem::Dependency
126
- name: rbplotly
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: 0.1.2
132
- type: :runtime
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: 0.1.2
68
+ version: 1.2.1
139
69
  description: Synthesizer implemented in Ruby.
140
70
  email:
141
71
  - yoshida.eth0@gmail.com
@@ -153,6 +83,7 @@ files:
153
83
  - bin/setup
154
84
  - examples/adsr.ipynb
155
85
  - examples/curves.ipynb
86
+ - examples/lpf.rb
156
87
  - examples/metronome.rb
157
88
  - examples/mono.rb
158
89
  - examples/poly.rb
@@ -161,17 +92,26 @@ files:
161
92
  - lib/audio_stream/audio_input_synth.rb
162
93
  - lib/synthesizer.rb
163
94
  - lib/synthesizer/amplifier.rb
95
+ - lib/synthesizer/filter.rb
96
+ - lib/synthesizer/filter/band_pass_filter.rb
97
+ - lib/synthesizer/filter/high_pass_filter.rb
98
+ - lib/synthesizer/filter/high_shelf_filter.rb
99
+ - lib/synthesizer/filter/low_pass_filter.rb
100
+ - lib/synthesizer/filter/low_shelf_filter.rb
101
+ - lib/synthesizer/filter/parallel.rb
102
+ - lib/synthesizer/filter/peaking_filter.rb
103
+ - lib/synthesizer/filter/serial.rb
164
104
  - lib/synthesizer/modulation.rb
165
105
  - lib/synthesizer/modulation/adsr.rb
166
106
  - lib/synthesizer/modulation/curve.rb
167
107
  - lib/synthesizer/modulation/glide.rb
168
108
  - lib/synthesizer/modulation/lfo.rb
169
109
  - lib/synthesizer/modulation_value.rb
170
- - lib/synthesizer/mono.rb
110
+ - lib/synthesizer/mono_synth.rb
171
111
  - lib/synthesizer/note.rb
172
112
  - lib/synthesizer/note_perform.rb
173
113
  - lib/synthesizer/oscillator.rb
174
- - lib/synthesizer/poly.rb
114
+ - lib/synthesizer/poly_synth.rb
175
115
  - lib/synthesizer/processor.rb
176
116
  - lib/synthesizer/processor/high.rb
177
117
  - lib/synthesizer/processor/low.rb