zgomot 1.0.0 → 1.0.1

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