niki 0.1.0 → 0.1.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/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
+