zgomot 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0
1
+ 1.0.1
@@ -91,8 +91,8 @@ module Zgomot::Comp
91
91
  def channel=(chan)
92
92
  notes.each{|n| n.channel = chan}
93
93
  end
94
- def offset_time=(time)
95
- notes.each{|n| n.offset_time = time}
94
+ def offset=(time)
95
+ notes.each{|n| n.offset = time}
96
96
  end
97
97
  def time=(time)
98
98
  @clock = Zgomot::Midi::Clock.new
@@ -87,8 +87,8 @@ module Zgomot::Comp
87
87
  def to_midi
88
88
  notes.map{|n| n.to_midi}
89
89
  end
90
- def offset_time=(t)
91
- notes.each{|n| n.offset_time = t}
90
+ def offset=(t)
91
+ notes.each{|n| n.offset = t}
92
92
  end
93
93
  def notes
94
94
  @notes ||= item.notes(self)
@@ -3,7 +3,6 @@ module Zgomot
3
3
  class Error < Exception; end
4
4
 
5
5
  VERSION = "0.0.0"
6
- PLAY_DELAY = 1.0
7
6
  DISPATCHER_POLL = 1.133
8
7
 
9
8
  DEFAULT_CONFIG = {
@@ -30,7 +30,7 @@ include Zgomot::Delegator
30
30
  at_exit do
31
31
  unless Zgomot.live
32
32
  Zgomot::Boot.boot
33
- Zgomot::Midi::Stream.streams.each{|s| s.thread.join unless s.thread.nil?}
33
+ Zgomot::Midi::Stream.streams.values.each{|s| s.thread.join unless s.thread.nil?}
34
34
  loop do
35
35
  break if Zgomot::Midi::Dispatcher.done?
36
36
  sleep(Zgomot::DISPATCHER_POLL)
@@ -24,10 +24,10 @@ module Zgomot::Midi
24
24
 
25
25
  end
26
26
 
27
- attr_reader :number, :clock, :pattern, :length_to_sec
27
+ attr_reader :number, :clock, :pattern, :length_to_sec, :offset
28
28
 
29
29
  def initialize(num)
30
- @number, @pattern = num, []
30
+ @number, @pattern, @offset = num, [], nil
31
31
  set_clock
32
32
  end
33
33
 
@@ -46,15 +46,16 @@ module Zgomot::Midi
46
46
  end
47
47
 
48
48
  def method_missing(meth, *args, &blk )
49
- pattern.send(meth, *args, &blk); reset_pattern_time; self
49
+ pattern.send(meth, *args, &blk); reset_pattern_time;self
50
50
  end
51
51
 
52
- def time_shift(secs)
53
- pattern.each{|p| p.offset_time= secs}; self
52
+ def set_clock
53
+ @offset, @clock = nil, Clock.new
54
54
  end
55
55
 
56
- def set_clock
57
- @clock = Clock.new
56
+ def offset=(time)
57
+ @offset ||= time
58
+ pattern.each{|p| p.offset = offset}; self
58
59
  end
59
60
 
60
61
  end
@@ -4,12 +4,12 @@ module Zgomot::Midi
4
4
 
5
5
  attr_reader :measure, :beat, :tick, :seconds
6
6
 
7
- def initialize(arg=nil)
8
- if arg.kind_of?(Hash)
7
+ def initialize(args=nil)
8
+ if args.kind_of?(Hash)
9
9
  [:measure, :beat, :tick].each{|a| raise(Zgomot::Error, "#{a} is a required argument") unless args.include?(a)}
10
- init_with_measure_beat_tick(arg)
11
- elsif arg.nil?; init_with_nil
12
- elsif arg.kind_of?(Float); init_with_seconds(arg); end
10
+ init_with_measure_beat_tick(args)
11
+ elsif args.nil?; init_with_nil
12
+ elsif args.kind_of?(Float); init_with_seconds(args); end
13
13
  end
14
14
  def to_s
15
15
  "%d:%d:%d" % [measure, beat, tick]
@@ -17,6 +17,16 @@ module Zgomot::Midi
17
17
  def to_f
18
18
  seconds
19
19
  end
20
+ def +(add_time)
21
+ add_sec = if add_time.kind_of?(Float)
22
+ add_time
23
+ elsif add_time.kind_of?(Zgomot::Midi::Time)
24
+ add_time.to_f
25
+ else
26
+ raise(Zgomot::Error, "#{add_time.class.name} is invalid. Must be Float or Zgomot::Midi::Time")
27
+ end
28
+ self.class.new(seconds+add_sec)
29
+ end
20
30
  private
21
31
  def init_with_seconds(sec)
22
32
  @seconds = sec
@@ -36,12 +46,14 @@ module Zgomot::Midi
36
46
  class Clock
37
47
  class << self
38
48
  attr_accessor :beat_note, :beats_per_measure, :beats_per_minute, :resolution,
39
- :beat_sec, :whole_note_sec, :measure_sec, :tick_sec, :time_signature
49
+ :beat_sec, :whole_note_sec, :measure_sec, :tick_sec, :time_signature,
50
+ :ticks_per_beat
40
51
  def set_config(config)
41
52
  @time_signature = config[:time_signature] || '4/4'
42
53
  @beats_per_minute = (config[:beats_per_minute] || '120').to_f
43
54
  @resolution = (config[:resolution] || '1/32').split('/').last.to_f
44
55
  @beats_per_measure, @beat_note = @time_signature.split('/').map{|v| v.to_f}
56
+ @ticks_per_beat = @resolution/@beats_per_measure
45
57
  @beat_sec= 60.0/@beats_per_minute
46
58
  @whole_note_sec = @beat_sec*@beat_note
47
59
  @measure_sec = @beat_sec*@beats_per_measure
@@ -49,13 +61,30 @@ module Zgomot::Midi
49
61
  end
50
62
  end
51
63
  set_config(Zgomot.config)
52
- attr_reader :current_time
64
+ attr_reader :current_time, :created_at
53
65
  def initialize
54
- @current_time = Time.new
66
+ @current_time, @created_at = Time.new, ::Time.now
55
67
  end
56
68
  def to_s
57
69
  @current_time.to_s
58
70
  end
71
+ def +(add_clock)
72
+ @current_time + if add_clock.knd_of(Float) or add_time.kind_of?(Zgomot::Midi::Time)
73
+ add_clock
74
+ elsif add_time.kind_of?(Zgomot::Midi::Clock)
75
+ add_clock.current_time
76
+ else
77
+ raise(Zgomot::Error, "#{add_clock.class.name} is invalid. Must be Float, Zgomot::Midi::Time or Zgomot::Midi::Clock")
78
+ end
79
+ end
80
+ def absolute_sec
81
+ @current_time + created_at
82
+ end
83
+ def ceil
84
+ Time.new(:measure => @current_time.measure + 1,
85
+ :beat => 0,
86
+ :tick => 0)
87
+ end
59
88
  def update(time=nil)
60
89
  csecs = if time.kind_of?(Float)
61
90
  current_time.to_f + time
@@ -3,73 +3,63 @@ module Zgomot::Midi
3
3
  class Dispatcher
4
4
 
5
5
  @queue, @playing = [], []
6
- @qmutex, @qdispatch = Mutex.new, Mutex.new
6
+ @qmutex = Mutex.new
7
7
 
8
8
  @clock = Clock.new
9
9
  @tick = Clock.tick_sec
10
10
 
11
11
  class << self
12
12
 
13
- attr_reader :resolution, :queue, :thread, :clock, :tick, :qmutex, :qdispatch, :playing, :last_time
13
+ attr_reader :resolution, :queue, :thread, :clock, :tick, :qmutex, :qdispatch, :playing
14
14
 
15
15
  def clk
16
16
  clock.to_s
17
17
  end
18
18
 
19
- def flush
20
- @queue.clear
21
- end
22
-
23
- def done?
24
- qdispatch.synchronize{queue.empty? and playing.empty?}
25
- end
26
-
27
19
  def enqueue(ch)
20
+ ch.offset = clock.ceil
28
21
  qmutex.synchronize do
29
- @queue += ch.pattern.map{|p| p.to_midi}.flatten.compact.select{|n| not n.pitch_class.eql?(:R)}
22
+ pattern = ch.pattern.map{|p| p.to_midi}.flatten.compact.select{|n| not n.pitch_class.eql?(:R)}
23
+ @queue += pattern
30
24
  end
31
25
  end
32
26
 
33
- def dequeue(time)
27
+ def dequeue
34
28
  qmutex.synchronize do
35
- queue.partition{|n| n.play_at <= time}
29
+ queue.partition{|n| n.note_on.to_f <= clock.current_time.to_f}
36
30
  end
37
31
  end
38
32
 
39
- def dispatch(now)
40
- qdispatch.synchronize do
41
- ready, @queue = dequeue(now)
42
- notes_off(now)
33
+ private
34
+
35
+ def dispatch
36
+ ready, @queue = dequeue
37
+ notes_off
43
38
  notes_on(ready)
44
39
  end
45
- end
46
40
 
47
- def notes_on(notes)
48
- notes.each do |n|
49
- Zgomot.logger.info "NOTE ON: #{n.channel} : #{n.to_s} : #{n.time.to_s} : #{clock.current_time.to_s}"
50
- Zgomot::Drivers::Mgr.note_on(n.midi, n.channel, (127*n.velocity).to_i)
41
+ def notes_on(notes)
42
+ @playing += notes
43
+ notes.each do |n|
44
+ Zgomot.logger.info "NOTE ON: #{n.channel} : #{n.to_s} - #{n.time.to_s} - #{n.note_on.to_s} - #{clock.current_time.to_s}"
45
+ Zgomot::Drivers::Mgr.note_on(n.midi, n.channel, (127*n.velocity).to_i)
46
+ end
51
47
  end
52
- @playing += notes
53
- end
54
48
 
55
- def notes_off(time)
56
- turn_off, @playing = playing.partition{|n| (n.play_at+n.length_to_sec) <= time}
57
- turn_off.each do |n|
58
- Zgomot.logger.info "NOTE OFF:#{n.channel} : #{n.to_s} : #{n.time.to_s} : #{clock.current_time.to_s}"
59
- Zgomot::Drivers::Mgr.note_off(n.midi, n.channel, (127*n.velocity).to_i)
49
+ def notes_off
50
+ turn_off, @playing = playing.partition{|n| n.note_off.to_f <= clock.current_time.to_f}
51
+ turn_off.each do |n|
52
+ Zgomot.logger.info "NOTE OFF:#{n.channel} : #{n.to_s} - #{n.time.to_s} - #{n.note_off.to_s} - #{clock.current_time.to_s}"
53
+ Zgomot::Drivers::Mgr.note_off(n.midi, n.channel, (127*n.velocity).to_i)
54
+ end
60
55
  end
61
- end
62
-
63
- private :dispatch, :notes_on, :notes_off
64
56
 
65
57
  end
66
58
 
67
59
  @thread = Thread.new do
68
60
  loop do
69
- now = ::Time.now.truncate_to(Clock.tick_sec)
70
- dispatch(now)
71
- clock.update(last_time.nil? ? tick : now-last_time)
72
- @last_time = now
61
+ dispatch
62
+ clock.update(tick)
73
63
  sleep(tick)
74
64
  end
75
65
  end
@@ -27,7 +27,7 @@ module Zgomot::Midi
27
27
  end
28
28
 
29
29
  attr_reader :pitch_class, :octave, :midi, :time_scale
30
- attr_accessor :time, :offset_time, :channel, :velocity, :length
30
+ attr_accessor :time, :offset, :global_offset, :channel, :velocity, :length
31
31
 
32
32
  def initialize(args)
33
33
  @pitch_class, @octave = case args[:pitch]
@@ -56,14 +56,18 @@ module Zgomot::Midi
56
56
  @octave = oct; self
57
57
  end
58
58
 
59
- def play_at
60
- time.to_f + offset_time.to_f
59
+ def note_on
60
+ time + offset
61
61
  end
62
62
 
63
63
  def length_to_sec
64
64
  time_scale*Clock.whole_note_sec/length
65
65
  end
66
66
 
67
+ def note_off
68
+ note_on + length_to_sec
69
+ end
70
+
67
71
  def to_midi
68
72
  self
69
73
  end
@@ -2,33 +2,32 @@ module Zgomot::Midi
2
2
 
3
3
  class Stream
4
4
 
5
- @streams = []
5
+ @streams = {}
6
6
 
7
7
  class << self
8
8
  attr_reader :streams
9
9
  def str(name, pattern=nil, opts={}, &blk)
10
10
  strm = new(name, blk.arity, pattern, opts)
11
11
  strm.define_meta_class_method(:play, &blk)
12
- @streams << strm
12
+ @streams[name] = strm
13
13
  end
14
14
  def play(name=nil)
15
- start_time = ::Time.now.truncate_to(Clock.tick_sec) + Zgomot::PLAY_DELAY
16
15
  if name.nil?
17
- streams.reduce([]) do |a, s|
16
+ streams.values.reduce([]) do |a, s|
18
17
  if s.status_eql?(:paused)
19
- s.dispatch(start_time + s.delay)
18
+ s.dispatch
20
19
  a << s.name
21
20
  end; a
22
21
  end
23
22
  else
24
23
  apply_to_stream(name){|stream|
25
- stream.status_eql?(:paused) ? (stream.dispatch(start_time + stream.delay); name) : nil}
24
+ stream.status_eql?(:paused) ? (stream.dispatch; name) : nil}
26
25
  end
27
26
  end
28
27
  alias_method :run, :play
29
28
  def pause(name=nil)
30
29
  if name.nil?
31
- streams.each do |stream|
30
+ streams.values.each do |stream|
32
31
  stream.update_status(:paused)
33
32
  end; true
34
33
  else
@@ -45,7 +44,7 @@ module Zgomot::Midi
45
44
  end
46
45
  end
47
46
  def apply_to_stream(name)
48
- stream = streams.find{|s| s.name == name.to_s}
47
+ stream = streams.values.find{|s| s.name == name.to_s}
49
48
  if stream
50
49
  yield stream
51
50
  else
@@ -79,26 +78,25 @@ module Zgomot::Midi
79
78
  def info
80
79
  [name, status, ch.number, ch.clock, count, limit, delay].map(&:to_s)
81
80
  end
82
- def dispatch(start_time)
81
+ def dispatch
83
82
  @count = 0
84
83
  ch.set_clock
85
84
  update_status(:playing)
86
85
  @thread = Thread.new do
87
86
  while(status_eql?(:playing)) do
88
87
  @count += 1
89
- loop_time = ::Time.now
90
88
  break if not limit.eql?(:inf) and count > limit
91
89
  if self.respond_to?(play_meth, true)
92
90
  if pattern = self.send(play_meth)
93
91
  ch << pattern
94
- Dispatcher.enqueue(ch.time_shift(start_time))
92
+ Dispatcher.enqueue(ch)
95
93
  else; break; end
96
94
  else
97
95
  raise(Zgomot::Error, 'str block arity not supported')
98
96
  end
99
97
  Zgomot.logger.info "STREAM:#{count}:#{name}"
100
98
  patterns << Zgomot::Comp::Pattern.new(ch.pattern)
101
- sleep(ch.length_to_sec) if count > 1
99
+ sleep(ch.length_to_sec)
102
100
  end
103
101
  Zgomot.logger.info "STREAM FINISHED:#{name}"
104
102
  update_status(:paused)
@@ -44,7 +44,7 @@ module Zgomot::UI
44
44
  end
45
45
  def format_streams(name=nil)
46
46
  if name.nil?
47
- stream_mgr.streams.map{|stream| format_stream_info(stream)}
47
+ stream_mgr.streams.values.map{|stream| format_stream_info(stream)}
48
48
  else
49
49
  [stream_mgr.apply_to_stream(name.to_s){|stream| stream_info(stream)}]
50
50
  end
@@ -207,7 +207,7 @@ module Zgomot::UI
207
207
  end
208
208
  end
209
209
  def streams
210
- Zgomot::Midi::Stream.streams
210
+ Zgomot::Midi::Stream.streams.values
211
211
  end
212
212
  end
213
213
 
@@ -5,4 +5,4 @@ begin
5
5
  load ENV['HOME'] + '/.zgomot'
6
6
  rescue LoadError; end
7
7
  Zgomot::Boot.boot
8
- Pry.config.prompt_name = "\e[38;5;199mzgomot\e[0m\002"
8
+ Pry.config.prompt_name = "zgomot"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zgomot
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-03 00:00:00.000000000 Z
12
+ date: 2013-08-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi