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