synthesizer 1.1.0 → 1.2.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.
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