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