niki 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/examples/my_song.rb CHANGED
@@ -3,43 +3,51 @@ require 'niki'
3
3
 
4
4
  song = Niki::Song.new :tempo => 127 do
5
5
 
6
- # Configure midi channels
7
- channel :basses, 1
8
- channel :drums, 10
9
- channel :chords, 2
10
- channel :melodies, 3
11
-
12
- configure :drums do |drums|
13
- drums[:kick] = c1
14
- drums[:snare] = c1.sharp
15
- drums[:hh] = g1
16
- drums[:ohh] = g1.sharp
6
+ instrument :bass do
7
+ channel 1
8
+ end
9
+
10
+ instrument :chords do
11
+ channel 2
12
+ end
13
+
14
+ instrument :melody do
15
+ channel 3
16
+ end
17
+
18
+ instrument :drums do
19
+ channel 10
20
+
21
+ note[:kick] = c1
22
+ note[:snare] = c1.sharp
23
+ note[:hh] = g1
24
+ note[:ohh] = g1.sharp
17
25
  end
18
26
 
19
27
  part :intro do
20
28
  # Drums
21
29
  2.times do
22
- drum [:kick, :hh], 8
23
- drum :hh, 8
24
- drum [:snare, :hh], 8
25
- drum :hh, 8
26
-
27
- drum [:kick, :hh], 8
28
- drum :hh, 8
29
- drum [:snare, :hh], 8
30
- drum [:kick, :hh], 8
31
-
32
- drum :hh, 16
33
- drum :hh, 16
34
- drum :hh, 16
35
- drum :hh, 16
36
- drum [:snare, :hh], 8
37
- drum :hh, 8
38
-
39
- drum [:kick, :hh], 8
40
- drum [:kick, :hh], 8
41
- drum [:snare, :hh], 8
42
- drum :ohh, 8
30
+ drums [:kick, :hh], 8
31
+ drums :hh, 8
32
+ drums [:snare, :hh], 8
33
+ drums :hh, 8
34
+
35
+ drums [:kick, :hh], 8
36
+ drums :hh, 8
37
+ drums [:snare, :hh], 8
38
+ drums [:kick, :hh], 8
39
+
40
+ drums :hh, 16
41
+ drums :hh, 16
42
+ drums :hh, 16
43
+ drums :hh, 16
44
+ drums [:snare, :hh], 8
45
+ drums :hh, 8
46
+
47
+ drums [:kick, :hh], 8
48
+ drums [:kick, :hh], 8
49
+ drums [:snare, :hh], 8
50
+ drums :ohh, 8
43
51
  end
44
52
 
45
53
  # Bass
@@ -76,48 +84,48 @@ song = Niki::Song.new :tempo => 127 do
76
84
 
77
85
  part :intro_ending do
78
86
  # Drums
79
- drum [:kick, :hh], 8
80
- drum :hh, 8
81
- drum [:snare, :hh], 8
82
- drum :hh, 8
83
-
84
- drum [:kick, :hh], 8
85
- drum :hh, 8
86
- drum [:snare, :hh], 8
87
- drum [:kick, :hh], 8
88
-
89
- drum :hh, 16
90
- drum :hh, 16
91
- drum :hh, 16
92
- drum :hh, 16
93
- drum [:snare, :hh], 8
94
- drum :hh, 8
95
-
96
- drum [:kick, :hh], 8
97
- drum [:kick, :hh], 8
98
- drum [:snare, :hh], 8
99
- drum :ohh, 8
100
-
101
- # Drum break
102
- drum [:kick, :hh], 8
103
- drum :hh, 8
104
- drum [:kick, :hh], 8
105
- drum :hh, 8
106
- drum [:kick, :hh], 8
107
- drum :hh, 8
108
- drum [:kick, :hh], 8
109
- drum :hh, 8
110
-
111
- drum [:snare, :ooh], 4
112
- drum [:snare, :ooh], 4
113
- drum :snare, 16
114
- drum :snare, 16
115
- drum :kick, 16
116
- drum :kick, 16
117
- drum :snare, 16
118
- drum :snare, 16
119
- drum [:snare, :ooh], 16
120
- drum :snare, 16
87
+ drums [:kick, :hh], 8
88
+ drums :hh, 8
89
+ drums [:snare, :hh], 8
90
+ drums :hh, 8
91
+
92
+ drums [:kick, :hh], 8
93
+ drums :hh, 8
94
+ drums [:snare, :hh], 8
95
+ drums [:kick, :hh], 8
96
+
97
+ drums :hh, 16
98
+ drums :hh, 16
99
+ drums :hh, 16
100
+ drums :hh, 16
101
+ drums [:snare, :hh], 8
102
+ drums :hh, 8
103
+
104
+ drums [:kick, :hh], 8
105
+ drums [:kick, :hh], 8
106
+ drums [:snare, :hh], 8
107
+ drums :ohh, 8
108
+
109
+ # drums break
110
+ drums [:kick, :hh], 8
111
+ drums :hh, 8
112
+ drums [:kick, :hh], 8
113
+ drums :hh, 8
114
+ drums [:kick, :hh], 8
115
+ drums :hh, 8
116
+ drums [:kick, :hh], 8
117
+ drums :hh, 8
118
+
119
+ drums [:snare, :ooh], 4
120
+ drums [:snare, :ooh], 4
121
+ drums :snare, 16
122
+ drums :snare, 16
123
+ drums :kick, 16
124
+ drums :kick, 16
125
+ drums :snare, 16
126
+ drums :snare, 16
127
+ drums [:snare, :ooh], 16
128
+ drums :snare, 16
121
129
 
122
130
  # Bass
123
131
  bass f2, 4
@@ -152,7 +160,7 @@ song = Niki::Song.new :tempo => 127 do
152
160
 
153
161
  part :pre_chorus do
154
162
  bass :from => :intro
155
- drum :from => :intro
163
+ drums :from => :intro
156
164
 
157
165
  melody a2, 4
158
166
  melody a2, 4
@@ -220,47 +228,47 @@ song = Niki::Song.new :tempo => 127 do
220
228
 
221
229
  # Drums
222
230
  7.times do
223
- drum [:kick, :hh], 8
224
- drum :hh, 8
225
- drum [:snare, :kick, :hh], 8
226
- drum :hh, 8
231
+ drums [:kick, :hh], 8
232
+ drums :hh, 8
233
+ drums [:snare, :kick, :hh], 8
234
+ drums :hh, 8
227
235
  end
228
- drum :kick, 8
229
- drum :hh, 16
230
- drum :hh, 16
231
- drum [:snare, :kick], 16
232
- drum :snare, 16
233
- drum [:kick, :ohh], 8
236
+ drums :kick, 8
237
+ drums :hh, 16
238
+ drums :hh, 16
239
+ drums [:snare, :kick], 16
240
+ drums :snare, 16
241
+ drums [:kick, :ohh], 8
234
242
 
235
243
  # Chords
236
- chord a3MIN(2), 2, :base => f3
237
- chord a3MIN(2), 8, :base => f3
238
- chord a3MIN(2), 8, :base => f3
239
- chord a3MIN(2), 8, :base => f3
240
- chord c3MAJ, 4
241
- chord c3MAJ, 4
242
- chord c3MAJ, 8
243
- chord g3MAJ, 2
244
- chord [a3, b3, e4]
245
- chord c3MAJ, 4
246
- chord c3MAJ, 4
247
- chord g3MAJ, 8
248
- chord g3MAJ, 8
249
- chord g3MAJ, 8, :base => f4
250
- chord g3MAJ, 8, :base => e4
244
+ chords a3MIN(2), 2, :base => f3
245
+ chords a3MIN(2), 8, :base => f3
246
+ chords a3MIN(2), 8, :base => f3
247
+ chords a3MIN(2), 8, :base => f3
248
+ chords c3MAJ, 4
249
+ chords c3MAJ, 4
250
+ chords c3MAJ, 8
251
+ chords g3MAJ, 2
252
+ chords [a3, b3, e4]
253
+ chords c3MAJ, 4
254
+ chords c3MAJ, 4
255
+ chords g3MAJ, 8
256
+ chords g3MAJ, 8
257
+ chords g3MAJ, 8, :base => f4
258
+ chords g3MAJ, 8, :base => e4
251
259
  end
252
260
 
253
261
  repeat :chorus
254
262
 
255
263
  part :outro do
256
- drum :from => :intro
264
+ drums :from => :intro
257
265
  bass :from => :intro
258
- chord :from => :chorus
266
+ chords :from => :chorus
259
267
  end
260
268
 
261
269
  part :outro_ending do
262
270
  bass :from => :intro
263
- chord :from => :chorus
271
+ chords :from => :chorus
264
272
  end
265
273
  end
266
274
 
data/lib/niki.rb CHANGED
@@ -3,6 +3,7 @@ require 'core_ext/array'
3
3
  require 'niki/chords'
4
4
  require 'niki/part'
5
5
  require 'niki/song'
6
+ require 'niki/instrument'
6
7
 
7
8
  module Niki
8
9
  end
@@ -0,0 +1,57 @@
1
+ module Niki
2
+ class Instrument
3
+ attr_reader :name, :channel_number
4
+
5
+ include Niki::Chords
6
+
7
+ def initialize(name, song, &block)
8
+ @name = name
9
+ @song = song
10
+ @channel_number = nil
11
+ @macros = {}
12
+
13
+ self.instance_exec(&block)
14
+
15
+ Part.send :include, self.to_module
16
+ end
17
+
18
+ def channel(number)
19
+ @channel_number = number - 1
20
+ end
21
+
22
+ def note
23
+ @macros
24
+ end
25
+
26
+ def to_module
27
+ instrument_name = @name
28
+ macros = @macros
29
+
30
+ Module.new do
31
+ define_method instrument_name do |*args|
32
+ note = args.shift
33
+ duration = args.shift || 1
34
+ options = args.shift || {}
35
+
36
+ if note.is_a?(Hash) && note[:from]
37
+ copy_from_part(note[:from], instrument_name)
38
+ return
39
+ end
40
+
41
+ note = [note].flatten.map do |n|
42
+ if note.is_a?(Fixnum)
43
+ note
44
+ else
45
+ # Try to fetch the note from the symbol
46
+ macros[note]
47
+ end
48
+ end
49
+
50
+ note.push options[:base]
51
+
52
+ register_note(instrument_name, note, duration)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
data/lib/niki/part.rb CHANGED
@@ -1,69 +1,34 @@
1
1
  module Niki
2
2
  class Part
3
- attr_reader :name, :chords, :drums, :basses, :melodies
3
+ attr_reader :name, :notes
4
4
 
5
5
  include Niki::Chords
6
6
 
7
7
  def initialize(name, song, &block)
8
8
  @name = name
9
9
  @song = song
10
- @drum_notes = @song.drum_notes
11
- @chords = []
12
- @drums = []
13
- @basses = []
14
- @melodies = []
10
+ @notes = {}
15
11
  self.instance_eval(&block)
16
12
  end
17
13
 
18
- def chord note, duration = 1, options = {}
19
- if note.is_a?(Hash) && note[:from]
20
- copy_from_part(note[:from], :chords)
21
- return
22
- end
23
-
24
- note.push options[:base]
25
- @chords << [note, calculate_duration(duration)]
26
- end
27
-
28
- def drum note, duration = 1, options = {}
29
- if note.is_a?(Hash) && note[:from]
30
- copy_from_part(note[:from], :drums)
31
- return
32
- end
33
-
34
- drum_note = [note].flatten.map do |n|
35
- @drum_notes[n]
36
- end
37
- @drums << [drum_note, calculate_duration(duration)]
14
+ def for_instrument(instrument_name)
15
+ @notes[instrument_name] || []
38
16
  end
39
17
 
40
- def bass note = nil, duration = 1, options = {}
41
- if note.is_a?(Hash) && note[:from]
42
- copy_from_part(note[:from], :basses)
43
- return
44
- end
18
+ private
45
19
 
46
- @basses << [[note], calculate_duration(duration)]
20
+ def copy_from_part(name, type)
21
+ part = @song.get_part(name)
22
+ @notes[type] = part.send(type)
47
23
  end
48
24
 
49
- def melody note = nil, duration = 1, options = {}
50
- if note.is_a?(Hash) && note[:from]
51
- copy_from_part(note[:from], :melodies)
52
- return
53
- end
54
-
55
- @melodies << [[note], calculate_duration(duration)]
25
+ def register_note(instrument_name, note, duration)
26
+ @notes[instrument_name] ||= []
27
+ @notes[instrument_name] << [note, calculate_duration(duration)]
56
28
  end
57
29
 
58
- private
59
-
60
30
  def calculate_duration(duration)
61
31
  1.to_f / ((@song.tempo.to_f/120) * duration/2)
62
32
  end
63
-
64
- def copy_from_part(name, type)
65
- part = @song.get_part(name)
66
- instance_variable_set(:"@#{type}", part.send(type))
67
- end
68
33
  end
69
34
  end
data/lib/niki/song.rb CHANGED
@@ -2,7 +2,7 @@ require 'unimidi'
2
2
 
3
3
  module Niki
4
4
  class Song
5
- attr_reader :tempo, :drum_notes
5
+ attr_reader :tempo
6
6
 
7
7
  include Niki::Chords
8
8
 
@@ -12,26 +12,19 @@ module Niki
12
12
  def initialize(options, &block)
13
13
  @midi = UniMIDI::Output.first
14
14
  @parts = []
15
+ @instruments = []
15
16
  @channel = {}
16
- @drum_notes = {}
17
17
  @tempo = options[:tempo]
18
18
  self.instance_eval &block
19
19
  end
20
20
 
21
- def channel(instrument, number)
22
- @channel[instrument] = number - 1
23
- end
24
-
25
21
  def part(name, &block)
26
22
  raise "#{name} is already defined!" if has_part?(name)
27
23
  @parts << Part.new(name, self, &block)
28
24
  end
29
25
 
30
- def configure(instrument, &block)
31
- case instrument
32
- when :drums
33
- block.call @drum_notes
34
- end
26
+ def instrument(name, &block)
27
+ @instruments << Instrument.new(name, self, &block)
35
28
  end
36
29
 
37
30
  def repeat(name, options = {})
@@ -42,29 +35,29 @@ module Niki
42
35
 
43
36
  def play
44
37
  @parts.each do |part|
45
- [:basses, :chords, :melodies, :drums].map do |instrument_name|
38
+ @instruments.map do |instrument|
46
39
  Thread.start do
47
- play_part(part, instrument_name)
40
+ play_part(part, instrument)
48
41
  end
49
42
  end.map { |thread| thread.join }
50
43
 
51
- [:basses, :chords, :melodies, :drums].each do |instrument_name|
52
- reset(instrument_name)
44
+ @instruments.each do |instrument|
45
+ reset(instrument)
53
46
  end
54
47
  end
55
48
  end
56
49
 
57
- def play_part(part, instrument_name)
58
- return if part.send(instrument_name).length.zero?
59
- channel = @channel[instrument_name]
50
+ def play_part(part, instrument)
51
+ return if part.for_instrument(instrument.name).length.zero?
52
+ channel = instrument.channel_number
60
53
 
61
54
  @midi.open do |out|
62
- part.send(instrument_name).each do |instrument|
63
- notes = [instrument.first].flatten.compact
55
+ part.for_instrument(instrument.name).each do |notes, duration|
56
+ notes = [notes].flatten.compact
64
57
  notes.each do |note|
65
58
  out.puts NOTE_ON + channel, note, 100
66
59
  end
67
- sleep(instrument.last)
60
+ sleep(duration)
68
61
  notes.each do |note|
69
62
  out.puts NOTE_OFF + channel, note, 100
70
63
  end
@@ -82,12 +75,11 @@ module Niki
82
75
  !!@parts.map(&:name).detect {|part_name| part_name == name }
83
76
  end
84
77
 
85
- def reset(instrument_name)
86
- channel = @channel[instrument_name]
78
+ def reset(instrument)
87
79
  @midi.open do |out|
88
80
  # Reset all notes
89
81
  95.times do |i|
90
- out.puts NOTE_OFF + channel, i, 100
82
+ out.puts NOTE_OFF + instrument.channel_number, i, 100
91
83
  end
92
84
  end
93
85
  end
data/lib/niki/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Niki
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
metadata CHANGED
@@ -1,35 +1,39 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: niki
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.0
3
+ version: !ruby/object:Gem::Version
5
4
  prerelease:
5
+ version: 0.1.1
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Josep M. Bach
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-16 00:00:00.000000000 +02:00
12
+
13
+ date: 2011-08-16 00:00:00 +02:00
13
14
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
16
17
  name: unimidi
17
- requirement: &2154214760 !ruby/object:Gem::Requirement
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
18
20
  none: false
19
- requirements:
20
- - - ! '>='
21
- - !ruby/object:Gem::Version
22
- version: '0'
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
23
25
  type: :runtime
24
- prerelease: false
25
- version_requirements: *2154214760
26
+ version_requirements: *id001
26
27
  description: A DSL to describe and play structured musical pieces, i.e. songs
27
- email:
28
+ email:
28
29
  - josep.m.bach@gmail.com
29
30
  executables: []
31
+
30
32
  extensions: []
33
+
31
34
  extra_rdoc_files: []
32
- files:
35
+
36
+ files:
33
37
  - .gitignore
34
38
  - Gemfile
35
39
  - Gemfile.lock
@@ -41,6 +45,7 @@ files:
41
45
  - lib/core_ext/fixnum.rb
42
46
  - lib/niki.rb
43
47
  - lib/niki/chords.rb
48
+ - lib/niki/instrument.rb
44
49
  - lib/niki/part.rb
45
50
  - lib/niki/song.rb
46
51
  - lib/niki/version.rb
@@ -48,32 +53,30 @@ files:
48
53
  has_rdoc: true
49
54
  homepage: http://github.com/txus/niki
50
55
  licenses: []
56
+
51
57
  post_install_message:
52
58
  rdoc_options: []
53
- require_paths:
59
+
60
+ require_paths:
54
61
  - lib
55
- required_ruby_version: !ruby/object:Gem::Requirement
62
+ required_ruby_version: !ruby/object:Gem::Requirement
56
63
  none: false
57
- requirements:
58
- - - ! '>='
59
- - !ruby/object:Gem::Version
60
- version: '0'
61
- segments:
62
- - 0
63
- hash: -752574128219649690
64
- required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
69
  none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
70
- segments:
71
- - 0
72
- hash: -752574128219649690
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
73
74
  requirements: []
75
+
74
76
  rubyforge_project: niki
75
- rubygems_version: 1.6.2
77
+ rubygems_version: 1.6.1
76
78
  signing_key:
77
79
  specification_version: 3
78
80
  summary: A DSL to describe and play structured musical pieces, i.e. songs
79
81
  test_files: []
82
+