zgomot 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.document +5 -0
  2. data/LICENSE +22 -0
  3. data/README.rdoc +7 -0
  4. data/Rakefile +24 -0
  5. data/VERSION +1 -0
  6. data/bin/zgomot +2 -0
  7. data/examples/arp_chords.rb +15 -0
  8. data/examples/full_scale_notes.rb +15 -0
  9. data/examples/inv_chords.rb +15 -0
  10. data/examples/modes_notes.rb +16 -0
  11. data/examples/notes.rb +18 -0
  12. data/examples/percs.rb +20 -0
  13. data/examples/percs_multi.rb +18 -0
  14. data/examples/phase_notes.rb +20 -0
  15. data/examples/prog_chords.rb +15 -0
  16. data/examples/prog_chords_multi_vel_length.rb +15 -0
  17. data/examples/prog_chords_rest.rb +15 -0
  18. data/examples/prog_notes.rb +15 -0
  19. data/examples/prog_notes_multi_vel_length.rb +15 -0
  20. data/examples/prog_notes_rest.rb +15 -0
  21. data/examples/progressive_modes.rb +51 -0
  22. data/examples/reverse_chords.rb +15 -0
  23. data/examples/scale_chords.rb +15 -0
  24. data/examples/scale_notes.rb +15 -0
  25. data/examples/scales_notes.rb +19 -0
  26. data/examples/simple_chords.rb +15 -0
  27. data/examples/simple_markov.rb +24 -0
  28. data/examples/simple_notes.rb +15 -0
  29. data/examples/simple_notes_length.rb +17 -0
  30. data/examples/simple_notes_velocity.rb +17 -0
  31. data/examples/zgomot.yml +3 -0
  32. data/lib/zgomot/boot.rb +56 -0
  33. data/lib/zgomot/comp/chord.rb +171 -0
  34. data/lib/zgomot/comp/markov.rb +60 -0
  35. data/lib/zgomot/comp/mode.rb +66 -0
  36. data/lib/zgomot/comp/note.rb +29 -0
  37. data/lib/zgomot/comp/pattern.rb +63 -0
  38. data/lib/zgomot/comp/perc.rb +94 -0
  39. data/lib/zgomot/comp/permutation.rb +17 -0
  40. data/lib/zgomot/comp/pitch_class.rb +63 -0
  41. data/lib/zgomot/comp/progression.rb +132 -0
  42. data/lib/zgomot/comp/scale.rb +32 -0
  43. data/lib/zgomot/comp.rb +11 -0
  44. data/lib/zgomot/config.rb +51 -0
  45. data/lib/zgomot/main.rb +51 -0
  46. data/lib/zgomot/midi/channel.rb +92 -0
  47. data/lib/zgomot/midi/clock.rb +101 -0
  48. data/lib/zgomot/midi/dispatcher.rb +92 -0
  49. data/lib/zgomot/midi/interface.rb +29 -0
  50. data/lib/zgomot/midi/note.rb +104 -0
  51. data/lib/zgomot/midi/stream.rb +76 -0
  52. data/lib/zgomot/midi.rb +6 -0
  53. data/lib/zgomot/patches/object.rb +11 -0
  54. data/lib/zgomot/patches/time.rb +10 -0
  55. data/lib/zgomot/patches.rb +2 -0
  56. data/lib/zgomot.rb +14 -0
  57. data/lib/zlive.rb +7 -0
  58. metadata +178 -0
@@ -0,0 +1,132 @@
1
+ ##############################################################################################################
2
+ module Zgomot::Comp
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class Progression
6
+
7
+ #.........................................................................................................
8
+ attr_reader :mode, :length, :velocity, :clock, :tonic, :items, :item
9
+
10
+ #.........................................................................................................
11
+ def initialize(args)
12
+ @length, @velocity, @item = [args[:length]].flatten, [args[:velocity]].flatten, args[:item]
13
+ @items = (1..7).to_a
14
+ self.mode!(args[:mode])
15
+ @tonic = case args[:tonic]
16
+ when Array then args[:tonic]
17
+ when Symbol then [args[:tonic], 4]
18
+ when nil then [:C,4]
19
+ else raise(Zgomot::Error, "#{args[:tonic].inspect} is invalid tonic")
20
+ end
21
+ end
22
+
23
+ #.........................................................................................................
24
+ def pitches
25
+ last_pitch, octave = tonic; pitch = [last_pitch]
26
+ mode[0..-2].each_index{|i| pitch << PitchClass.next(tonic.first, sum(mode[0..i]))}
27
+ pitch[1..-1].map do |p|
28
+ octave += 1 if p < last_pitch; last_pitch = p.value; [last_pitch, octave]
29
+ end.unshift(tonic)
30
+ end
31
+
32
+ #.........................................................................................................
33
+ def new_respond_to?(meth, include_private=false)
34
+ old_respond_to?(meth) || (not notes.select{|n| n.respond_to?(meth)}.empty?)
35
+ end
36
+ alias_method :old_respond_to?, :respond_to?
37
+ alias_method :respond_to?, :new_respond_to?
38
+
39
+ #.........................................................................................................
40
+ def method_missing(meth, *args, &blk)
41
+ if not notes.select{|n| n.respond_to?(meth)}.empty?
42
+ @notes = notes.map do |n|
43
+ n.respond_to?(meth) ? n.send(meth, *args, &blk) : n
44
+ end
45
+ else
46
+ @notes = nil
47
+ items.send(meth, *args, &blk)
48
+ end
49
+ self
50
+ end
51
+
52
+ #.........................................................................................................
53
+ # transforms
54
+ #.........................................................................................................
55
+ def tonic!(v)
56
+ @notes = nil; @tonic = v; self
57
+ end
58
+
59
+ #.........................................................................................................
60
+ def mode!(v)
61
+ @notes = nil; @mode = v.kind_of?(Mode) ? v : Mode.new(v); self
62
+ end
63
+
64
+ #.........................................................................................................
65
+ def octave!(oct)
66
+ @notes = nil; @octave = oct; self
67
+ end
68
+
69
+ #.........................................................................................................
70
+ def [](*args)
71
+ @items = args.flatten; self
72
+ end
73
+
74
+ #.........................................................................................................
75
+ def velocity=(v)
76
+ notes.each{|n| n.velocity = v}
77
+ end
78
+
79
+ #.........................................................................................................
80
+ def length=(v)
81
+ notes.each{|n| n.length = v}
82
+ end
83
+
84
+ #.........................................................................................................
85
+ # midi interface
86
+ def length_to_sec
87
+ notes.inject(0.0){|s,n| s += n.length_to_sec}
88
+ end
89
+
90
+ #.........................................................................................................
91
+ def time=(time)
92
+ @clock = Zgomot::Midi::Clock.new
93
+ clock.update(time)
94
+ notes.each do |n|
95
+ n.time = clock.current_time
96
+ clock.update(n.length_to_sec)
97
+ end
98
+ end
99
+
100
+ #.........................................................................................................
101
+ def channel=(c)
102
+ notes.each{|n| n.channel = c}
103
+ end
104
+
105
+ #.........................................................................................................
106
+ def to_midi
107
+ notes.map{|n| n.to_midi}
108
+ end
109
+
110
+ #.........................................................................................................
111
+ def offset_time=(t)
112
+ notes.each{|n| n.offset_time = t}
113
+ end
114
+
115
+ #.........................................................................................................
116
+ def notes
117
+ @notes ||= item.notes(self)
118
+ end
119
+
120
+ #.........................................................................................................
121
+ def sum(a)
122
+ a.inject(0) {|s,n| s+n}
123
+ end
124
+
125
+ #.........................................................................................................
126
+ private :sum
127
+
128
+ #### Progression
129
+ end
130
+
131
+ #### Zgomot::Comp
132
+ end
@@ -0,0 +1,32 @@
1
+ ##############################################################################################################
2
+ module Zgomot::Comp
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class Scale
6
+
7
+ #####-------------------------------------------------------------------------------------------------------
8
+ attr_reader :intervals, :shift, :scale
9
+
10
+ #.........................................................................................................
11
+ def initialize(int, shift)
12
+ @intervals = int
13
+ @shift = shift - 1
14
+ @scale = int.clone
15
+ self.shift.times{self.next}
16
+ end
17
+
18
+ #.........................................................................................................
19
+ def next
20
+ scale.push(scale.shift)
21
+ end
22
+
23
+ #.........................................................................................................
24
+ def method_missing(method, *args, &blk )
25
+ scale.send(method, *args, &blk)
26
+ end
27
+
28
+ #### Scale
29
+ end
30
+
31
+ #### Zgomot::Comp
32
+ end
@@ -0,0 +1,11 @@
1
+ require 'zgomot/comp/pattern'
2
+ require 'zgomot/comp/chord'
3
+ require 'zgomot/comp/note'
4
+ require 'zgomot/comp/scale'
5
+ require 'zgomot/comp/mode'
6
+ require 'zgomot/comp/perc'
7
+ require 'zgomot/comp/progression'
8
+ require 'zgomot/comp/pitch_class'
9
+ require 'zgomot/comp/markov'
10
+
11
+
@@ -0,0 +1,51 @@
1
+ ##############################################################################################################
2
+ module Zgomot
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class Error < Exception; end
6
+
7
+ #.........................................................................................................
8
+ VERSION = "0.0.0"
9
+ PLAY_DELAY = 1.0
10
+ DISPATCHER_POLL = 1.133
11
+
12
+ #.........................................................................................................
13
+ DEFAULT_CONFIG = {
14
+ :beats_per_minute => 120,
15
+ :time_signature => '4/4',
16
+ :resolution => '1/32'
17
+ }
18
+
19
+ #.........................................................................................................
20
+ @config_file = "zgomot.yml"
21
+ @app_path = File.dirname($0)
22
+ @log_file = STDOUT
23
+ @live = false
24
+
25
+ ####......................................................................................................
26
+ class << self
27
+
28
+ #.......................................................................................................
29
+ attr_accessor :config_file, :app_path, :log_file, :config, :live
30
+
31
+ #.......................................................................................................
32
+ def logger; @logger ||= Logger.new(STDOUT); end
33
+ def logger=(logger); @logger = logger; end
34
+
35
+ #.......................................................................................................
36
+ def add_path(dir)
37
+ File.join(Zgomot.app_path, dir)
38
+ end
39
+
40
+ #### self
41
+ end
42
+
43
+ #.......................................................................................................
44
+ @config_file = add_path(config_file)
45
+ user_config = if File.exist?(config_file)
46
+ (c = File.open(config_file) {|yf| YAML::load(yf)}) ? c : {}
47
+ else; {}; end
48
+ @config = DEFAULT_CONFIG.inject({}){|r,(k,v)| r.update(k => (user_config[k.to_s] || v))}
49
+
50
+ end
51
+
@@ -0,0 +1,51 @@
1
+ ##############################################################################################################
2
+ module Zgomot
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ module Delegator
6
+
7
+ #####-------------------------------------------------------------------------------------------------------
8
+ class << self
9
+
10
+ #.........................................................................................................
11
+ def delegate(del, *methods)
12
+ methods.each do |method_name|
13
+ class_eval <<-RUBY
14
+ def #{method_name.to_s}(*args, &blk)
15
+ ::#{del}.send(#{method_name.inspect}, *args, &blk)
16
+ end
17
+ RUBY
18
+ end
19
+ end
20
+
21
+ #### self
22
+ end
23
+
24
+ delegate Zgomot::Boot, :before_start
25
+ delegate Zgomot::Midi::Stream, :str, :play, :streams
26
+ delegate Zgomot::Midi::Channel, :ch
27
+ delegate Zgomot::Midi::Dispatcher, :clock
28
+ delegate Zgomot::Comp::Pattern, :np, :cp, :c, :n, :pr
29
+ delegate Zgomot::Comp::Markov, :mark
30
+
31
+ #### Delegator
32
+ end
33
+
34
+ #### AgentXmpp
35
+ end
36
+
37
+ ##############################################################################################################
38
+ include Zgomot::Delegator
39
+
40
+ ##############################################################################################################
41
+ at_exit do
42
+ unless Zgomot.live
43
+ Zgomot::Boot.boot
44
+ Zgomot::Midi::Stream.streams.each{|s| s.thread.join}
45
+ loop do
46
+ break if Zgomot::Midi::Dispatcher.done?
47
+ sleep(Zgomot::DISPATCHER_POLL)
48
+ end
49
+ end
50
+ Zgomot.logger.info "ZGOMOT IS FINISHED"
51
+ end
@@ -0,0 +1,92 @@
1
+ ##############################################################################################################
2
+ module Zgomot::Midi
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class Channel
6
+
7
+ #.........................................................................................................
8
+ @channels = []
9
+
10
+ #####-------------------------------------------------------------------------------------------------------
11
+ class << self
12
+
13
+ #.........................................................................................................
14
+ attr_reader :channels
15
+
16
+ #.........................................................................................................
17
+ def ch(num=0, opts={})
18
+ (channels << new(is_valid(num), opts)).last
19
+ end
20
+
21
+ #.........................................................................................................
22
+ def is_valid(num)
23
+ nums = [num].flatten
24
+ valid = nums.select{|n| 0 <= n and n <= 15}
25
+ valid.length.eql?(nums.length) ? num : raise(Zgomot::Error, "channel number invalid: 1<= channel <= 16")
26
+ end
27
+
28
+ #.........................................................................................................
29
+ def release(chan)
30
+ channels.delete_if{|c| c.eql?(chan)}
31
+ end
32
+
33
+ #### self
34
+ end
35
+
36
+ #####-------------------------------------------------------------------------------------------------------
37
+ attr_reader :number, :clock, :pattern
38
+
39
+ #.........................................................................................................
40
+ def initialize(num, opts={})
41
+ @number = num
42
+ @clock = Clock.new
43
+ @pattern = []
44
+ end
45
+
46
+ #.........................................................................................................
47
+ def <<(pat)
48
+ pat = Zgomot::Comp::Pattern.new(pat) unless pat.kind_of?(Zgomot::Comp::Pattern)
49
+ pat.seq.each do |p|
50
+ p.time = clock.current_time
51
+ p.channel = number
52
+ @pattern << p.clone
53
+ clock.update(p.length_to_sec)
54
+ end; self
55
+ end
56
+
57
+ #.........................................................................................................
58
+ def method_missing(meth, *args, &blk )
59
+ pattern.send(meth, *args, &blk); reset_pattern_time; self
60
+ end
61
+
62
+ #.........................................................................................................
63
+ def length_to_sec
64
+ clock.current_time.to_f
65
+ end
66
+
67
+ #.........................................................................................................
68
+ # transforms
69
+ #.........................................................................................................
70
+ def time_shift(secs)
71
+ pattern.each{|p| p.offset_time=secs}; self
72
+ end
73
+
74
+ #.........................................................................................................
75
+ # pattern
76
+ #.........................................................................................................
77
+ def reset_pattern_time
78
+ @clock = Clock.new
79
+ pattern.each do |pat|
80
+ pat.time = clock.current_time
81
+ clock.update(pat.length_to_sec)
82
+ end
83
+ end
84
+
85
+ #.........................................................................................................
86
+ private :reset_pattern_time
87
+
88
+ #### Channel
89
+ end
90
+
91
+ #### Zgomot::Midi
92
+ end
@@ -0,0 +1,101 @@
1
+ ##############################################################################################################
2
+ module Zgomot::Midi
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class Time
6
+
7
+ #.........................................................................................................
8
+ attr_reader :measure, :beat, :tick, :seconds
9
+
10
+ #.........................................................................................................
11
+ def initialize(arg=nil)
12
+ if arg.kind_of?(Hash)
13
+ [:measure, :beat, :tick].each{|a| raise(Zgomot::Error, "#{a} is a required argument") unless args.include?(a)}
14
+ init_with_measure_beat_tick(arg)
15
+ elsif arg.nil?; init_with_nil
16
+ elsif arg.kind_of?(Float); init_with_seconds(arg); end
17
+ end
18
+
19
+ #.........................................................................................................
20
+ def to_s
21
+ "#{measure}.#{beat}.#{tick}"
22
+ end
23
+
24
+ #.........................................................................................................
25
+ def to_f
26
+ seconds
27
+ end
28
+
29
+ private
30
+
31
+ #.........................................................................................................
32
+ def init_with_seconds(sec)
33
+ @seconds = sec
34
+ @measure = (sec/Clock.measure_sec).to_i
35
+ @beat = ((sec % Clock.measure_sec)/Clock.beat_sec).to_i
36
+ @tick = ((sec - measure*Clock.measure_sec - beat*Clock.beat_sec)/Clock.tick_sec).to_i
37
+ end
38
+
39
+ #.........................................................................................................
40
+ def init_with_measure_beat_tick(args)
41
+ @measure, @beat, @tick = args[:measure], args[:beat], args[:tick]
42
+ @seconds = (measure*Clock.measure_sec + beat*Clock.beat_sec + tick*Clock.tick_sec).to_f
43
+ end
44
+
45
+ #.........................................................................................................
46
+ def init_with_nil
47
+ @measure, @beat, @tick, @seconds = 0, 0, 0, 0.0
48
+ end
49
+
50
+ #### Time
51
+ end
52
+
53
+ #####-------------------------------------------------------------------------------------------------------
54
+ class Clock
55
+
56
+ #.........................................................................................................
57
+ @beats_per_measure, @beat_note = Zgomot.config[:time_signature].split('/').map{|v| v.to_f}
58
+ @beats_per_minute = Zgomot.config[:beats_per_minute].to_f
59
+ @resolution = Zgomot.config[:resolution].split('/').last.to_f
60
+ @beat_sec= 60.0/@beats_per_minute
61
+ @whole_note_sec = @beat_sec*@beat_note
62
+ @measure_sec = @beat_sec*@beats_per_measure
63
+ @tick_sec = @whole_note_sec/(@resolution)
64
+
65
+ #####-------------------------------------------------------------------------------------------------------
66
+ class << self
67
+
68
+ #.........................................................................................................
69
+ attr_accessor :beat_note, :beats_per_measure, :beats_per_minute, :resolution,
70
+ :beat_sec, :whole_note_sec, :measure_sec, :tick_sec
71
+
72
+ #### self
73
+ end
74
+
75
+ #...........................................................................................................
76
+ attr_reader :current_time
77
+
78
+ #...........................................................................................................
79
+ def initialize
80
+ @current_time = Time.new
81
+ end
82
+
83
+ #...........................................................................................................
84
+ def update(time=nil)
85
+ csecs = if time.kind_of?(Float)
86
+ current_time.to_f + time
87
+ elsif time.kind_of?(Zgomot::Midi::Time)
88
+ current_time.to_f + time.to_f
89
+ elsif time.nil?
90
+ current_time.to_f + Clock.tick_sec
91
+ else
92
+ raise(Zgomot::Error, "argument must by of type Float or Zgomot::Midi::Time")
93
+ end
94
+ @current_time = Time.new(csecs)
95
+ end
96
+
97
+ #### Clock
98
+ end
99
+
100
+ #### Zgomot ::Midi
101
+ end
@@ -0,0 +1,92 @@
1
+ ##############################################################################################################
2
+ module Zgomot::Midi
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class Dispatcher
6
+
7
+ #.........................................................................................................
8
+ @queue, @playing = [], []
9
+ @qmutex, @qdispatch = Mutex.new, Mutex.new
10
+
11
+ #.........................................................................................................
12
+ @clock = Clock.new
13
+ @tick = Clock.tick_sec
14
+
15
+ #####-------------------------------------------------------------------------------------------------------
16
+ class << self
17
+
18
+ #.........................................................................................................
19
+ attr_reader :resolution, :queue, :thread, :clock, :tick, :qmutex, :qdispatch, :playing, :last_time
20
+
21
+ #.........................................................................................................
22
+ def flush
23
+ @queue.clear
24
+ end
25
+ #.........................................................................................................
26
+ def done?
27
+ qdispatch.synchronize{queue.empty? and playing.empty?}
28
+ end
29
+
30
+ #.........................................................................................................
31
+ def enqueue(ch)
32
+ qmutex.synchronize do
33
+ @queue += ch.pattern.map{|p| p.to_midi}.flatten.compact.select{|n| not n.pitch_class.eql?(:R)}
34
+ end
35
+ end
36
+
37
+ #.........................................................................................................
38
+ def dequeue(time)
39
+ qmutex.synchronize do
40
+ queue.partition{|n| n.play_at <= time}
41
+ end
42
+ end
43
+
44
+ #.........................................................................................................
45
+ def dispatch(now)
46
+ qdispatch.synchronize do
47
+ ready, @queue = dequeue(now)
48
+ notes_off(now)
49
+ notes_on(ready)
50
+ end
51
+ end
52
+
53
+ #.........................................................................................................
54
+ def notes_on(notes)
55
+ notes.each do |n|
56
+ Zgomot.logger.info "NOTE ON: #{n.channel} : #{n.to_s} : #{n.time.to_s} : #{clock.current_time.to_s}"
57
+ Interface.driver.note_on(n.midi, n.channel, (127*n.velocity).to_i)
58
+ end
59
+ @playing += notes
60
+ end
61
+
62
+ #.........................................................................................................
63
+ def notes_off(time)
64
+ turn_off, @playing = playing.partition{|n| (n.play_at+n.length_to_sec) <= time}
65
+ turn_off.each do |n|
66
+ Zgomot.logger.info "NOTE OFF:#{n.channel} : #{n.to_s} : #{n.time.to_s} : #{clock.current_time.to_s}"
67
+ Interface.driver.note_off(n.midi, n.channel, (127*n.velocity).to_i)
68
+ end
69
+ end
70
+
71
+ #.........................................................................................................
72
+ private :dispatch, :notes_on, :notes_off
73
+
74
+ #### self
75
+ end
76
+
77
+ #.........................................................................................................
78
+ @thread = Thread.new do
79
+ loop do
80
+ now = ::Time.now.truncate_to(Clock.tick_sec)
81
+ dispatch(now)
82
+ clock.update(last_time.nil? ? tick : now-last_time)
83
+ @last_time = now
84
+ sleep(tick)
85
+ end
86
+ end
87
+
88
+ #### Dispatcher
89
+ end
90
+
91
+ #### Zgomot::Midi
92
+ end
@@ -0,0 +1,29 @@
1
+ ##############################################################################################################
2
+ module Zgomot::Midi
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class Interface
6
+
7
+ #####-------------------------------------------------------------------------------------------------------
8
+ class << self
9
+
10
+ #.........................................................................................................
11
+ attr_reader :driver
12
+
13
+ #.........................................................................................................
14
+ def method_missing(method, *args, &blk )
15
+ @driver.send(method, *args, &blk)
16
+ end
17
+
18
+ #### self
19
+ end
20
+
21
+ #.........................................................................................................
22
+ @driver = MIDIator::Interface.new
23
+ driver.autodetect_driver
24
+
25
+ #### Interface
26
+ end
27
+
28
+ #### Zgomot::Midi
29
+ end