synthesizer 1.2.0 → 1.3.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: ab192c339eebdc39d867ac206c82454c8b3509f92967e54f4aa4f4660b2e3cdf
4
- data.tar.gz: 86fadad577d12289b652be8bfa4ac55f6a6bad136fa5dc9ce21eac4df3f536e6
3
+ metadata.gz: ba89ee2f086cd7828b8a8f56ac0afaaed912b6140171972ea0a79de35116a8d2
4
+ data.tar.gz: 74ac5e12ea76f79b4d03a3181f24a97901c6381a8f8f7c4f34894f212f234438
5
5
  SHA512:
6
- metadata.gz: ce723ad9a5fd4817ce33f362fb15cdce50132b066c0aff60b203d13e04ab4bef99f947f6e4d871d2a24ad0a66b98aa1b899e72b579d23dbad64245b848ffc94d
7
- data.tar.gz: c42def904f7c6531d2f68d1000c5cd0a4cc2b54088f7af0c3414d3ffa59d1da8750eca6efd961b987953cde385266f187066ca71ba4f41c3bf2798fb0f1fcec3
6
+ metadata.gz: 2fbda5f5c4e4a5f13744ce84f1ba210cc5cf5ae264d4b24b0106650949b8e03d1a2ef24767d832febfd5770dda7805797fccf798a0015be99884371cedb75572
7
+ data.tar.gz: a8aa71eeaca0a941c2b0c7edadaa67610d44084afa7808a4a6488a622be0ab457025339d843854261ad7950f4e03510750feed62fae3083851023d01ca05f982
@@ -0,0 +1,59 @@
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::SquareSawtooth,
18
+ uni_num: ModulationValue.new(4)
19
+ .add(Modulation::Lfo.new(
20
+ )),
21
+ uni_detune: 0.1,
22
+ ),
23
+ ],
24
+ amplifier: Amplifier.new(
25
+ volume: ModulationValue.new(1.0)
26
+ .add(Modulation::Adsr.new(
27
+ attack: 0.05,
28
+ hold: 0.1,
29
+ decay: 0.4,
30
+ sustain: 0.8,
31
+ release: 0.2
32
+ ), depth: 1.0),
33
+ ),
34
+ quality: Quality::LOW,
35
+ soundinfo: soundinfo,
36
+ )
37
+
38
+ se = StepEditor::StGt.new(bpm: 120) {|se|
39
+ se.note(Note.new(60), st: 480, gt: 480*3)
40
+ se.pitch_bend(1, st: 480)
41
+ se.pitch_bend(2, st: 480*2)
42
+ se.complete
43
+ }
44
+
45
+ track1 = AudioInputStepEditor.new(synth, se)
46
+
47
+ stereo_out = AudioOutput.device(soundinfo: soundinfo)
48
+
49
+ track1
50
+ .stream
51
+ .send_to(stereo_out, gain: 0.25)
52
+
53
+
54
+ conductor = Conductor.new(
55
+ input: [track1],
56
+ output: [stereo_out]
57
+ )
58
+ conductor.connect
59
+ conductor.join
@@ -0,0 +1,52 @@
1
+ module AudioStream
2
+ class AudioInputStepEditor < Rx::Subject
3
+ include AudioInput
4
+
5
+ def initialize(synth, step_editor)
6
+ super()
7
+
8
+ @synth = synth
9
+ @step_editor = step_editor
10
+
11
+ @soundinfo = synth.soundinfo
12
+ end
13
+
14
+ def each(&block)
15
+ Enumerator.new do |y|
16
+
17
+ events = Hash.new {|h, k| h[k]=[]}
18
+
19
+ fps = @soundinfo.samplerate.to_f / @soundinfo.window_size
20
+
21
+ @step_editor.events.each {|event|
22
+ pos = event[0]
23
+ events[(pos * fps).to_i] << event
24
+ }
25
+
26
+ catch :break do
27
+ Range.new(0, nil).each {|i|
28
+ if events.has_key?(i)
29
+ events[i].each {|event|
30
+ type = event[1]
31
+
32
+ case type
33
+ when :note_on
34
+ @synth.note_on(event[2], velocity: event[3])
35
+ when :note_off
36
+ @synth.note_off(event[2])
37
+ when :pitch_bend
38
+ @synth.pitch_bend = event[2]
39
+ when :complete
40
+ throw :break
41
+ end
42
+ }
43
+ end
44
+
45
+ buf = @synth.next
46
+ y << buf
47
+ }
48
+ end
49
+ end.each(&block)
50
+ end
51
+ end
52
+ end
data/lib/synthesizer.rb CHANGED
@@ -3,6 +3,8 @@ require 'synthesizer/version'
3
3
  require 'audio_stream'
4
4
  require 'audio_stream/audio_input_synth.rb'
5
5
  require 'audio_stream/audio_input_metronome.rb'
6
+ require 'audio_stream/audio_input_step_editor'
7
+ require 'synthesizer/step_editor'
6
8
 
7
9
  require 'synthesizer/poly_synth'
8
10
  require 'synthesizer/mono_synth'
@@ -45,7 +45,9 @@ module Synthesizer
45
45
  end
46
46
  end
47
47
 
48
- def note_on(note)
48
+ # @param note [Synthesizer::Note]
49
+ # @param velocity [Float] volume percent (0.0~1.0)
50
+ def note_on(note, velocity: 1.0)
49
51
  # Note Off
50
52
  note_off(note)
51
53
 
@@ -54,12 +56,13 @@ module Synthesizer
54
56
  @glide.target = note.num
55
57
  else
56
58
  # Note On
57
- @perform = NotePerform.new(self, note)
59
+ @perform = NotePerform.new(self, note, velocity)
58
60
  @glide.base = note.num
59
61
  end
60
62
  @note_nums << note.num
61
63
  end
62
64
 
65
+ # @param note [Synthesizer::Note]
63
66
  def note_off(note)
64
67
  # Note Off
65
68
  @note_nums.delete_if {|note_num| note_num==note.num}
@@ -3,14 +3,17 @@ module Synthesizer
3
3
 
4
4
  attr_reader :synth
5
5
  attr_reader :note
6
+ attr_reader :velocity
6
7
 
7
- def initialize(synth, note)
8
+ def initialize(synth, note, velocity)
8
9
  @synth = synth
10
+ @note = note
11
+ @velocity = velocity
12
+
9
13
  @processors = synth.oscillators.map {|osc|
10
14
  synth.processor.generator(osc, self)
11
15
  }
12
16
 
13
- @note = note
14
17
  @note_on = true
15
18
  @released = false
16
19
  end
@@ -30,19 +30,21 @@ module Synthesizer
30
30
  end
31
31
 
32
32
  def next
33
+ buf = nil
33
34
  if 0<@performs.length
34
- bufs = @performs.values.map(&:next)
35
+ bufs = @performs.values.map(&:next).compact
35
36
 
36
37
  # delete released note performs
37
38
  @performs.delete_if {|note_num, perform| perform.released? }
38
39
 
39
- bufs.compact.inject(:+)
40
- else
41
- AudioStream::Buffer.float(@soundinfo.window_size, @soundinfo.channels)
40
+ buf = bufs.inject(:+)
42
41
  end
42
+ buf || AudioStream::Buffer.float(@soundinfo.window_size, @soundinfo.channels)
43
43
  end
44
44
 
45
- def note_on(note)
45
+ # @param note [Synthesizer::Note]
46
+ # @param velocity [Float] volume percent (0.0~1.0)
47
+ def note_on(note, velocity: 1.0)
46
48
  # Note Off
47
49
  perform = @performs[note.num]
48
50
  if perform
@@ -50,10 +52,11 @@ module Synthesizer
50
52
  end
51
53
 
52
54
  # Note On
53
- perform = NotePerform.new(self, note)
55
+ perform = NotePerform.new(self, note, velocity)
54
56
  @performs[note.num] = perform
55
57
  end
56
58
 
59
+ # @param note [Synthesizer::Note]
57
60
  def note_off(note)
58
61
  # Note Off
59
62
  perform = @performs[note.num]
@@ -33,7 +33,7 @@ module Synthesizer
33
33
 
34
34
  window_size.times.each {|i|
35
35
  # Oscillator, Amplifier
36
- volume = volume_mod.next
36
+ volume = volume_mod.next * note_perform.velocity
37
37
  tune_semis = tune_semis_mod.next + synth.pitch_bend
38
38
  tune_cents = tune_cents_mod.next
39
39
 
@@ -60,7 +60,7 @@ module Synthesizer
60
60
 
61
61
  window_size.times.each {|i|
62
62
  # Oscillator, Amplifier
63
- volume = volume_mod.next
63
+ volume = volume_mod.next * note_perform.velocity
64
64
  pan = pan_mod.next
65
65
  tune_semis = tune_semis_mod.next + synth.pitch_bend
66
66
  tune_cents = tune_cents_mod.next
@@ -32,7 +32,7 @@ module Synthesizer
32
32
  buf = AudioStream::Buffer.float(window_size, channels)
33
33
 
34
34
  # Oscillator, Amplifier
35
- volume = volume_mod.next
35
+ volume = volume_mod.next * note_perform.velocity
36
36
  tune_semis = tune_semis_mod.next + synth.pitch_bend
37
37
  tune_cents = tune_cents_mod.next
38
38
 
@@ -57,7 +57,7 @@ module Synthesizer
57
57
  buf = AudioStream::Buffer.float(window_size, channels)
58
58
 
59
59
  # Oscillator, Amplifier
60
- volume = volume_mod.next
60
+ volume = volume_mod.next * note_perform.velocity
61
61
  pan = pan_mod.next
62
62
  tune_semis = tune_semis_mod.next + synth.pitch_bend
63
63
  tune_cents = tune_cents_mod.next
@@ -0,0 +1,6 @@
1
+ require 'synthesizer/step_editor/st_gt'
2
+
3
+ module Synthesizer
4
+ module StepEditor
5
+ end
6
+ end
@@ -0,0 +1,55 @@
1
+ module Synthesizer
2
+ module StepEditor
3
+ class StGt
4
+
5
+ attr_reader :ppq
6
+ attr_reader :events
7
+
8
+ def initialize(bpm:, ppq: 480, &block)
9
+ @ppq = ppq
10
+ @seek = 0.0
11
+ @location = 0
12
+ @events = []
13
+ self.bpm = bpm
14
+
15
+ if block_given?
16
+ yield self
17
+ end
18
+ end
19
+
20
+ def bpm=(bpm)
21
+ @ppq_rate = 60.0 / (@ppq.to_f * bpm)
22
+ end
23
+
24
+ def step(st)
25
+ @location += st
26
+ @seek += st * @ppq_rate
27
+ end
28
+
29
+ def location(beats: 4)
30
+ tick = @location % @ppq
31
+ location = (@location - tick) / @ppq
32
+ beat = location % beats
33
+ location = location - beat
34
+ measure = location / beats
35
+
36
+ "#{measure+1}. #{beat+1}. #{tick}"
37
+ end
38
+
39
+ def note(note, st: 0, gt:, vel: 1.0, dev: 0)
40
+ @events << [@seek + dev * @ppq_rate, :note_on, note, vel]
41
+ @events << [@seek + (gt + dev) * @ppq_rate, :note_off, note]
42
+ step(st)
43
+ end
44
+
45
+ def pitch_bend(semis, st: 0, dev: 0)
46
+ @events << [@seek + dev * @ppq_rate, :pitch_bend, semis]
47
+ step(st)
48
+ end
49
+
50
+ def complete
51
+ @events << [@seek, :complete]
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,3 +1,3 @@
1
1
  module Synthesizer
2
- VERSION = "1.2.0"
2
+ VERSION = "1.3.0"
3
3
  end
data/synthesizer.gemspec CHANGED
@@ -30,5 +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.2.1"
33
+ spec.add_dependency "audio_stream", ">= 1.2.2"
34
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.2.0
4
+ version: 1.3.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-18 00:00:00.000000000 Z
11
+ date: 2019-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 1.2.1
61
+ version: 1.2.2
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.2.1
68
+ version: 1.2.2
69
69
  description: Synthesizer implemented in Ruby.
70
70
  email:
71
71
  - yoshida.eth0@gmail.com
@@ -88,7 +88,9 @@ files:
88
88
  - examples/mono.rb
89
89
  - examples/poly.rb
90
90
  - examples/shapes.ipynb
91
+ - examples/step_editor.rb
91
92
  - lib/audio_stream/audio_input_metronome.rb
93
+ - lib/audio_stream/audio_input_step_editor.rb
92
94
  - lib/audio_stream/audio_input_synth.rb
93
95
  - lib/synthesizer.rb
94
96
  - lib/synthesizer/amplifier.rb
@@ -118,6 +120,8 @@ files:
118
120
  - lib/synthesizer/quality.rb
119
121
  - lib/synthesizer/shape.rb
120
122
  - lib/synthesizer/shape_pos.rb
123
+ - lib/synthesizer/step_editor.rb
124
+ - lib/synthesizer/step_editor/st_gt.rb
121
125
  - lib/synthesizer/unison.rb
122
126
  - lib/synthesizer/utils.rb
123
127
  - lib/synthesizer/version.rb