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 +1 -1
- data/lib/zgomot/comp/chord.rb +2 -2
- data/lib/zgomot/comp/progression.rb +2 -2
- data/lib/zgomot/config.rb +0 -1
- data/lib/zgomot/main.rb +1 -1
- data/lib/zgomot/midi/channel.rb +8 -7
- data/lib/zgomot/midi/clock.rb +37 -8
- data/lib/zgomot/midi/dispatcher.rb +26 -36
- data/lib/zgomot/midi/note.rb +7 -3
- data/lib/zgomot/midi/stream.rb +10 -12
- data/lib/zgomot/ui/output.rb +1 -1
- data/lib/zgomot/ui/windows.rb +1 -1
- data/lib/zgomot_sh.rb +1 -1
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.1
|
data/lib/zgomot/comp/chord.rb
CHANGED
@@ -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
|
95
|
-
notes.each{|n| n.
|
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
|
data/lib/zgomot/config.rb
CHANGED
data/lib/zgomot/main.rb
CHANGED
@@ -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)
|
data/lib/zgomot/midi/channel.rb
CHANGED
@@ -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;
|
49
|
+
pattern.send(meth, *args, &blk); reset_pattern_time;self
|
50
50
|
end
|
51
51
|
|
52
|
-
def
|
53
|
-
|
52
|
+
def set_clock
|
53
|
+
@offset, @clock = nil, Clock.new
|
54
54
|
end
|
55
55
|
|
56
|
-
def
|
57
|
-
@
|
56
|
+
def offset=(time)
|
57
|
+
@offset ||= time
|
58
|
+
pattern.each{|p| p.offset = offset}; self
|
58
59
|
end
|
59
60
|
|
60
61
|
end
|
data/lib/zgomot/midi/clock.rb
CHANGED
@@ -4,12 +4,12 @@ module Zgomot::Midi
|
|
4
4
|
|
5
5
|
attr_reader :measure, :beat, :tick, :seconds
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
if
|
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(
|
11
|
-
elsif
|
12
|
-
elsif
|
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
|
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
|
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
|
-
|
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
|
27
|
+
def dequeue
|
34
28
|
qmutex.synchronize do
|
35
|
-
queue.partition{|n| n.
|
29
|
+
queue.partition{|n| n.note_on.to_f <= clock.current_time.to_f}
|
36
30
|
end
|
37
31
|
end
|
38
32
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
70
|
-
|
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
|
data/lib/zgomot/midi/note.rb
CHANGED
@@ -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, :
|
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
|
60
|
-
time
|
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
|
data/lib/zgomot/midi/stream.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
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
|
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)
|
99
|
+
sleep(ch.length_to_sec)
|
102
100
|
end
|
103
101
|
Zgomot.logger.info "STREAM FINISHED:#{name}"
|
104
102
|
update_status(:paused)
|
data/lib/zgomot/ui/output.rb
CHANGED
@@ -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
|
data/lib/zgomot/ui/windows.rb
CHANGED
data/lib/zgomot_sh.rb
CHANGED
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.
|
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-
|
12
|
+
date: 2013-08-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|