mtk 0.0.3.2 → 0.0.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/.yardopts +2 -2
  2. data/DEVELOPMENT_NOTES.md +20 -0
  3. data/README.md +9 -3
  4. data/Rakefile +47 -13
  5. data/bin/mtk +55 -20
  6. data/examples/crescendo.rb +4 -4
  7. data/examples/{drum_pattern1.rb → drum_pattern.rb} +8 -8
  8. data/examples/dynamic_pattern.rb +5 -5
  9. data/examples/gets_and_play.rb +3 -2
  10. data/examples/notation.rb +3 -3
  11. data/examples/play_midi.rb +4 -4
  12. data/examples/print_midi.rb +2 -2
  13. data/examples/random_tone_row.rb +3 -3
  14. data/examples/syntax_to_midi.rb +2 -2
  15. data/examples/test_output.rb +4 -5
  16. data/examples/tone_row_melody.rb +7 -5
  17. data/lib/mtk/core/duration.rb +213 -0
  18. data/lib/mtk/core/intensity.rb +158 -0
  19. data/lib/mtk/core/interval.rb +157 -0
  20. data/lib/mtk/core/pitch.rb +154 -0
  21. data/lib/mtk/core/pitch_class.rb +194 -0
  22. data/lib/mtk/events/event.rb +4 -4
  23. data/lib/mtk/events/note.rb +12 -12
  24. data/lib/mtk/events/timeline.rb +232 -0
  25. data/lib/mtk/groups/chord.rb +56 -0
  26. data/lib/mtk/{helpers → groups}/collection.rb +33 -1
  27. data/lib/mtk/groups/melody.rb +96 -0
  28. data/lib/mtk/groups/pitch_class_set.rb +163 -0
  29. data/lib/mtk/{helpers → groups}/pitch_collection.rb +1 -1
  30. data/lib/mtk/{midi → io}/dls_synth_device.rb +3 -1
  31. data/lib/mtk/{midi → io}/dls_synth_output.rb +10 -10
  32. data/lib/mtk/{midi → io}/jsound_input.rb +2 -2
  33. data/lib/mtk/{midi → io}/jsound_output.rb +9 -9
  34. data/lib/mtk/{midi/file.rb → io/midi_file.rb} +13 -13
  35. data/lib/mtk/{midi/input.rb → io/midi_input.rb} +4 -4
  36. data/lib/mtk/{midi/output.rb → io/midi_output.rb} +8 -8
  37. data/lib/mtk/{helpers/lilypond.rb → io/notation.rb} +5 -5
  38. data/lib/mtk/{midi → io}/unimidi_input.rb +2 -2
  39. data/lib/mtk/{midi → io}/unimidi_output.rb +14 -9
  40. data/lib/mtk/{constants → lang}/durations.rb +11 -11
  41. data/lib/mtk/{constants → lang}/intensities.rb +11 -11
  42. data/lib/mtk/{constants → lang}/intervals.rb +17 -17
  43. data/lib/mtk/lang/mtk_grammar.citrus +9 -9
  44. data/lib/mtk/{constants → lang}/pitch_classes.rb +5 -5
  45. data/lib/mtk/{constants → lang}/pitches.rb +7 -7
  46. data/lib/mtk/{helpers → lang}/pseudo_constants.rb +1 -1
  47. data/lib/mtk/{variable.rb → lang/variable.rb} +1 -1
  48. data/lib/mtk/numeric_extensions.rb +40 -47
  49. data/lib/mtk/patterns/for_each.rb +1 -1
  50. data/lib/mtk/patterns/pattern.rb +3 -3
  51. data/lib/mtk/sequencers/event_builder.rb +16 -15
  52. data/lib/mtk/sequencers/legato_sequencer.rb +1 -1
  53. data/lib/mtk/sequencers/rhythmic_sequencer.rb +1 -1
  54. data/lib/mtk/sequencers/sequencer.rb +8 -8
  55. data/lib/mtk/sequencers/step_sequencer.rb +2 -2
  56. data/lib/mtk.rb +33 -39
  57. data/spec/mtk/{duration_spec.rb → core/duration_spec.rb} +3 -3
  58. data/spec/mtk/{intensity_spec.rb → core/intensity_spec.rb} +3 -3
  59. data/spec/mtk/{interval_spec.rb → core/interval_spec.rb} +1 -1
  60. data/spec/mtk/{pitch_class_spec.rb → core/pitch_class_spec.rb} +1 -1
  61. data/spec/mtk/{pitch_spec.rb → core/pitch_spec.rb} +8 -8
  62. data/spec/mtk/events/event_spec.rb +4 -4
  63. data/spec/mtk/events/note_spec.rb +8 -8
  64. data/spec/mtk/{timeline_spec.rb → events/timeline_spec.rb} +47 -47
  65. data/spec/mtk/{chord_spec.rb → groups/chord_spec.rb} +18 -16
  66. data/spec/mtk/{helpers → groups}/collection_spec.rb +3 -3
  67. data/spec/mtk/{melody_spec.rb → groups/melody_spec.rb} +36 -34
  68. data/spec/mtk/{pitch_class_set_spec.rb → groups/pitch_class_set_spec.rb} +57 -55
  69. data/spec/mtk/{midi/file_spec.rb → io/midi_file_spec.rb} +17 -17
  70. data/spec/mtk/{midi/output_spec.rb → io/midi_output_spec.rb} +6 -6
  71. data/spec/mtk/{constants → lang}/durations_spec.rb +1 -1
  72. data/spec/mtk/{constants → lang}/intensities_spec.rb +1 -1
  73. data/spec/mtk/{constants → lang}/intervals_spec.rb +1 -1
  74. data/spec/mtk/lang/parser_spec.rb +12 -6
  75. data/spec/mtk/{constants → lang}/pitch_classes_spec.rb +1 -1
  76. data/spec/mtk/{constants → lang}/pitches_spec.rb +1 -1
  77. data/spec/mtk/{helpers → lang}/pseudo_constants_spec.rb +2 -2
  78. data/spec/mtk/{variable_spec.rb → lang/variable_spec.rb} +4 -4
  79. data/spec/mtk/numeric_extensions_spec.rb +35 -55
  80. data/spec/mtk/patterns/for_each_spec.rb +1 -1
  81. data/spec/mtk/patterns/sequence_spec.rb +1 -1
  82. data/spec/mtk/sequencers/legato_sequencer_spec.rb +2 -2
  83. data/spec/mtk/sequencers/rhythmic_sequencer_spec.rb +4 -4
  84. data/spec/mtk/sequencers/step_sequencer_spec.rb +5 -5
  85. data/spec/spec_helper.rb +7 -6
  86. metadata +75 -61
  87. data/ext/mkrf_conf.rb +0 -25
  88. data/lib/mtk/chord.rb +0 -55
  89. data/lib/mtk/duration.rb +0 -211
  90. data/lib/mtk/helpers/convert.rb +0 -36
  91. data/lib/mtk/helpers/output_selector.rb +0 -67
  92. data/lib/mtk/intensity.rb +0 -156
  93. data/lib/mtk/interval.rb +0 -155
  94. data/lib/mtk/melody.rb +0 -94
  95. data/lib/mtk/pitch.rb +0 -152
  96. data/lib/mtk/pitch_class.rb +0 -192
  97. data/lib/mtk/pitch_class_set.rb +0 -161
  98. data/lib/mtk/timeline.rb +0 -230
  99. data/spec/mtk/midi/jsound_input_spec.rb +0 -11
  100. data/spec/mtk/midi/jsound_output_spec.rb +0 -11
  101. data/spec/mtk/midi/unimidi_input_spec.rb +0 -11
  102. data/spec/mtk/midi/unimidi_output_spec.rb +0 -11
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mtk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3.2
4
+ version: 0.0.3.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,14 +9,14 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-11 00:00:00.000000000 Z
12
+ date: 2013-06-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: citrus
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - ~>
20
20
  - !ruby/object:Gem::Version
21
21
  version: '2.4'
22
22
  type: :runtime
@@ -24,7 +24,7 @@ dependencies:
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ! '>='
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: '2.4'
30
30
  - !ruby/object:Gem::Dependency
@@ -59,13 +59,28 @@ dependencies:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0.3'
62
+ - !ruby/object:Gem::Dependency
63
+ name: unimidi
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '0.3'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '0.3'
62
78
  description: A music library and domain-specific language for generating music via
63
79
  MIDI.
64
80
  email: adam@compusition.com
65
81
  executables:
66
82
  - mtk
67
- extensions:
68
- - ext/mkrf_conf.rb
83
+ extensions: []
69
84
  extra_rdoc_files: []
70
85
  files:
71
86
  - Rakefile
@@ -76,7 +91,7 @@ files:
76
91
  - .yardopts
77
92
  - bin/mtk
78
93
  - examples/crescendo.rb
79
- - examples/drum_pattern1.rb
94
+ - examples/drum_pattern.rb
80
95
  - examples/dynamic_pattern.rb
81
96
  - examples/gets_and_play.rb
82
97
  - examples/notation.rb
@@ -86,36 +101,39 @@ files:
86
101
  - examples/syntax_to_midi.rb
87
102
  - examples/test_output.rb
88
103
  - examples/tone_row_melody.rb
89
- - lib/mtk/chord.rb
90
- - lib/mtk/constants/durations.rb
91
- - lib/mtk/constants/intensities.rb
92
- - lib/mtk/constants/intervals.rb
93
- - lib/mtk/constants/pitch_classes.rb
94
- - lib/mtk/constants/pitches.rb
95
- - lib/mtk/duration.rb
104
+ - lib/mtk/core/duration.rb
105
+ - lib/mtk/core/intensity.rb
106
+ - lib/mtk/core/interval.rb
107
+ - lib/mtk/core/pitch.rb
108
+ - lib/mtk/core/pitch_class.rb
96
109
  - lib/mtk/events/event.rb
97
110
  - lib/mtk/events/note.rb
98
111
  - lib/mtk/events/parameter.rb
99
- - lib/mtk/helpers/collection.rb
100
- - lib/mtk/helpers/convert.rb
101
- - lib/mtk/helpers/lilypond.rb
102
- - lib/mtk/helpers/output_selector.rb
103
- - lib/mtk/helpers/pitch_collection.rb
104
- - lib/mtk/helpers/pseudo_constants.rb
105
- - lib/mtk/intensity.rb
106
- - lib/mtk/interval.rb
112
+ - lib/mtk/events/timeline.rb
113
+ - lib/mtk/groups/chord.rb
114
+ - lib/mtk/groups/collection.rb
115
+ - lib/mtk/groups/melody.rb
116
+ - lib/mtk/groups/pitch_class_set.rb
117
+ - lib/mtk/groups/pitch_collection.rb
118
+ - lib/mtk/io/dls_synth_device.rb
119
+ - lib/mtk/io/dls_synth_output.rb
120
+ - lib/mtk/io/jsound_input.rb
121
+ - lib/mtk/io/jsound_output.rb
122
+ - lib/mtk/io/midi_file.rb
123
+ - lib/mtk/io/midi_input.rb
124
+ - lib/mtk/io/midi_output.rb
125
+ - lib/mtk/io/notation.rb
126
+ - lib/mtk/io/unimidi_input.rb
127
+ - lib/mtk/io/unimidi_output.rb
128
+ - lib/mtk/lang/durations.rb
129
+ - lib/mtk/lang/intensities.rb
130
+ - lib/mtk/lang/intervals.rb
107
131
  - lib/mtk/lang/mtk_grammar.citrus
108
132
  - lib/mtk/lang/parser.rb
109
- - lib/mtk/melody.rb
110
- - lib/mtk/midi/dls_synth_device.rb
111
- - lib/mtk/midi/dls_synth_output.rb
112
- - lib/mtk/midi/file.rb
113
- - lib/mtk/midi/input.rb
114
- - lib/mtk/midi/jsound_input.rb
115
- - lib/mtk/midi/jsound_output.rb
116
- - lib/mtk/midi/output.rb
117
- - lib/mtk/midi/unimidi_input.rb
118
- - lib/mtk/midi/unimidi_output.rb
133
+ - lib/mtk/lang/pitch_classes.rb
134
+ - lib/mtk/lang/pitches.rb
135
+ - lib/mtk/lang/pseudo_constants.rb
136
+ - lib/mtk/lang/variable.rb
119
137
  - lib/mtk/numeric_extensions.rb
120
138
  - lib/mtk/patterns/chain.rb
121
139
  - lib/mtk/patterns/choice.rb
@@ -126,39 +144,35 @@ files:
126
144
  - lib/mtk/patterns/palindrome.rb
127
145
  - lib/mtk/patterns/pattern.rb
128
146
  - lib/mtk/patterns/sequence.rb
129
- - lib/mtk/pitch.rb
130
- - lib/mtk/pitch_class.rb
131
- - lib/mtk/pitch_class_set.rb
132
147
  - lib/mtk/sequencers/event_builder.rb
133
148
  - lib/mtk/sequencers/legato_sequencer.rb
134
149
  - lib/mtk/sequencers/rhythmic_sequencer.rb
135
150
  - lib/mtk/sequencers/sequencer.rb
136
151
  - lib/mtk/sequencers/step_sequencer.rb
137
- - lib/mtk/timeline.rb
138
- - lib/mtk/variable.rb
139
152
  - lib/mtk.rb
140
- - spec/mtk/chord_spec.rb
141
- - spec/mtk/constants/durations_spec.rb
142
- - spec/mtk/constants/intensities_spec.rb
143
- - spec/mtk/constants/intervals_spec.rb
144
- - spec/mtk/constants/pitch_classes_spec.rb
145
- - spec/mtk/constants/pitches_spec.rb
146
- - spec/mtk/duration_spec.rb
153
+ - spec/mtk/core/duration_spec.rb
154
+ - spec/mtk/core/intensity_spec.rb
155
+ - spec/mtk/core/interval_spec.rb
156
+ - spec/mtk/core/pitch_class_spec.rb
157
+ - spec/mtk/core/pitch_spec.rb
147
158
  - spec/mtk/events/event_spec.rb
148
159
  - spec/mtk/events/note_spec.rb
149
160
  - spec/mtk/events/parameter_spec.rb
150
- - spec/mtk/helpers/collection_spec.rb
151
- - spec/mtk/helpers/pseudo_constants_spec.rb
152
- - spec/mtk/intensity_spec.rb
153
- - spec/mtk/interval_spec.rb
161
+ - spec/mtk/events/timeline_spec.rb
162
+ - spec/mtk/groups/chord_spec.rb
163
+ - spec/mtk/groups/collection_spec.rb
164
+ - spec/mtk/groups/melody_spec.rb
165
+ - spec/mtk/groups/pitch_class_set_spec.rb
166
+ - spec/mtk/io/midi_file_spec.rb
167
+ - spec/mtk/io/midi_output_spec.rb
168
+ - spec/mtk/lang/durations_spec.rb
169
+ - spec/mtk/lang/intensities_spec.rb
170
+ - spec/mtk/lang/intervals_spec.rb
154
171
  - spec/mtk/lang/parser_spec.rb
155
- - spec/mtk/melody_spec.rb
156
- - spec/mtk/midi/file_spec.rb
157
- - spec/mtk/midi/jsound_input_spec.rb
158
- - spec/mtk/midi/jsound_output_spec.rb
159
- - spec/mtk/midi/output_spec.rb
160
- - spec/mtk/midi/unimidi_input_spec.rb
161
- - spec/mtk/midi/unimidi_output_spec.rb
172
+ - spec/mtk/lang/pitch_classes_spec.rb
173
+ - spec/mtk/lang/pitches_spec.rb
174
+ - spec/mtk/lang/pseudo_constants_spec.rb
175
+ - spec/mtk/lang/variable_spec.rb
162
176
  - spec/mtk/numeric_extensions_spec.rb
163
177
  - spec/mtk/patterns/chain_spec.rb
164
178
  - spec/mtk/patterns/choice_spec.rb
@@ -169,20 +183,14 @@ files:
169
183
  - spec/mtk/patterns/palindrome_spec.rb
170
184
  - spec/mtk/patterns/pattern_spec.rb
171
185
  - spec/mtk/patterns/sequence_spec.rb
172
- - spec/mtk/pitch_class_set_spec.rb
173
- - spec/mtk/pitch_class_spec.rb
174
- - spec/mtk/pitch_spec.rb
175
186
  - spec/mtk/sequencers/event_builder_spec.rb
176
187
  - spec/mtk/sequencers/legato_sequencer_spec.rb
177
188
  - spec/mtk/sequencers/rhythmic_sequencer_spec.rb
178
189
  - spec/mtk/sequencers/sequencer_spec.rb
179
190
  - spec/mtk/sequencers/step_sequencer_spec.rb
180
- - spec/mtk/timeline_spec.rb
181
- - spec/mtk/variable_spec.rb
182
191
  - spec/spec_coverage.rb
183
192
  - spec/spec_helper.rb
184
193
  - spec/test.mid
185
- - ext/mkrf_conf.rb
186
194
  homepage: http://github.com/adamjmurray/mtk
187
195
  licenses: []
188
196
  post_install_message:
@@ -195,12 +203,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
195
203
  - - ! '>='
196
204
  - !ruby/object:Gem::Version
197
205
  version: '0'
206
+ segments:
207
+ - 0
208
+ hash: 3315185627907297240
198
209
  required_rubygems_version: !ruby/object:Gem::Requirement
199
210
  none: false
200
211
  requirements:
201
212
  - - ! '>='
202
213
  - !ruby/object:Gem::Version
203
214
  version: '0'
215
+ segments:
216
+ - 0
217
+ hash: 3315185627907297240
204
218
  requirements: []
205
219
  rubyforge_project:
206
220
  rubygems_version: 1.8.25
data/ext/mkrf_conf.rb DELETED
@@ -1,25 +0,0 @@
1
- require 'rubygems'
2
- require 'rubygems/command.rb'
3
- require 'rubygems/dependency_installer.rb'
4
- begin
5
- Gem::Command.build_args = ARGV
6
- rescue NoMethodError
7
- end
8
- inst = Gem::DependencyInstaller.new
9
- begin
10
- if RUBY_PLATFORM == 'java'
11
- puts "Installing jsound gem for MIDI I/O on JRuby"
12
- inst.install 'jsound', '~> 0.1'
13
- else
14
- puts "Installing unimidi gem for MIDI I/O"
15
- inst.install 'unimidi', '>= 0.3'
16
- end
17
- rescue
18
- STERR.puts $!
19
- exit(1)
20
- end
21
-
22
- # This is a hack, see http://www.programmersparadox.com/2012/05/21/gemspec-loading-dependent-gems-based-on-the-users-system/
23
- f = File.open(File.join(File.dirname(__FILE__), "Rakefile"), "w") # create dummy rakefile to indicate success
24
- f.write("task :default\n")
25
- f.close
data/lib/mtk/chord.rb DELETED
@@ -1,55 +0,0 @@
1
- module MTK
2
-
3
- # A sorted collection of distinct {Pitch}es.
4
- #
5
- # The "vertical" (simultaneous) pitch collection.
6
- #
7
- # @see Melody
8
- # @see PitchClassSet
9
- #
10
- class Chord < Melody
11
-
12
- # @param pitches [#to_a] the collection of pitches
13
- # @note duplicate pitches will be removed. See #{Melody} if you want to maintain duplicates.
14
- # @see MTK#Chord
15
- #
16
- def initialize(pitches)
17
- pitches = pitches.to_a.clone
18
- pitches.uniq!
19
- pitches.sort!
20
- @pitches = pitches.freeze
21
- end
22
-
23
- # Generate a chord inversion (positive numbers move the lowest notes up an octave, negative moves the highest notes down)
24
- def inversion(number)
25
- number = number.to_i
26
- pitch_set = Array.new(@pitches.uniq.sort)
27
- if number > 0
28
- number.times do |count|
29
- index = count % pitch_set.length
30
- pitch_set[index] += 12
31
- end
32
- else
33
- number.abs.times do |count|
34
- index = -(count + 1) % pitch_set.length # count from -1 downward to go backwards through the list starting at the end
35
- pitch_set[index] -= 12
36
- end
37
- end
38
- self.class.new pitch_set.sort
39
- end
40
-
41
- # Transpose the chord so that it's lowest pitch is the given pitch class.
42
- def nearest(pitch_class)
43
- self.transpose @pitches.first.pitch_class.distance_to(pitch_class)
44
- end
45
- end
46
-
47
- # Construct an ordered {Melody} with no duplicates.
48
- # @see #Chord
49
- # @see #Melody
50
- def Chord(*anything)
51
- Chord.new Helpers::Convert.to_pitches(*anything)
52
- end
53
- module_function :Chord
54
-
55
- end
data/lib/mtk/duration.rb DELETED
@@ -1,211 +0,0 @@
1
- module MTK
2
-
3
- # A measure of time in musical beats.
4
- # May be negative to indicate a rest, which uses the absolute value for the effective duration.
5
- class Duration
6
-
7
- include Comparable
8
-
9
- # The names of the base durations. See {MTK::Constants::Durations} for more info.
10
- NAMES = %w[w h q i s r x].freeze
11
-
12
- VALUES_BY_NAME = {
13
- 'w' => 4,
14
- 'h' => 2,
15
- 'q' => 1,
16
- 'i' => Rational(1,2),
17
- 's' => Rational(1,4),
18
- 'r' => Rational(1,8),
19
- 'x' => Rational(1,16)
20
- }
21
-
22
- @flyweight = {}
23
-
24
- # The number of beats, typically represented as a Rational
25
- attr_reader :value
26
-
27
- def initialize( length_in_beats )
28
- @value = length_in_beats
29
- end
30
-
31
- # Return a duration, only constructing a new instance when not already in the flyweight cache
32
- def self.[](length_in_beats)
33
- if length_in_beats.is_a? Fixnum
34
- value = length_in_beats
35
- else
36
- value = Rational(length_in_beats)
37
- end
38
- @flyweight[value] ||= new(value)
39
- end
40
-
41
- class << self
42
- alias :from_f :[]
43
- alias :from_i :[]
44
- end
45
-
46
- # Lookup a duration by name.
47
- # This method supports appending any combination of '.' and 't' for more fine-grained values.
48
- # each '.' multiplies by 3/2, and each 't' multiplies by 2/3.
49
- # You may use the prefix '-' to negate the duration (which turns it into a rest of the same length).
50
- # You may also prefix (after the '-' if present) the base duration name with an integer, float, or rational number
51
- # to multiply the base duration value. Rationals are in the form "#{{numerator_integer}}/#{{denominator_integer}}".
52
- # @example lookup value of 'q.', which is 1.5 times a quarter note (1.5 beats):
53
- # MTK::Duration.from_s('q.')
54
- # @example lookup the value of 3/4w, which three-quarters of a whole note (3 beats):
55
- # MTK::Duration.from_s('3/4w')
56
- def self.from_s(s)
57
- if s =~ /^(-)?(\d+([\.\/]\d+)?)?([whqisrx])((\.|t)*)$/i
58
- name = $4.downcase
59
- modifier = $5.downcase
60
- modifier << $1 if $1 # negation
61
- multiplier = $2
62
- else
63
- raise ArgumentError.new("Invalid Duration string '#{s}'")
64
- end
65
-
66
- value = VALUES_BY_NAME[name]
67
- modifier.each_char do |mod|
68
- case mod
69
- when '-' then value *= -1
70
- when '.' then value *= Rational(3,2)
71
- when 't' then value *= Rational(2,3)
72
- end
73
- end
74
-
75
- if multiplier
76
- case multiplier
77
- when /\./
78
- value *= multiplier.to_f
79
- when /\//
80
- numerator, denominator = multiplier.split('/')
81
- value *= Rational(numerator.to_i, denominator.to_i)
82
- else
83
- value *= multiplier.to_i
84
- end
85
- end
86
-
87
- self[value]
88
- end
89
-
90
- class << self
91
- alias :from_name :from_s
92
- end
93
-
94
- # The magnitude (absolute value) of the duration.
95
- # This is the actual duration for rests.
96
- # @see #rest?
97
- def length
98
- @value < 0 ? -@value : @value
99
- end
100
-
101
- # Durations with negative values are rests.
102
- # @see #length
103
- # @see #-@
104
- def rest?
105
- @value < 0
106
- end
107
-
108
- # The number of beats as a floating point number
109
- def to_f
110
- @value.to_f
111
- end
112
-
113
- # The numerical value for the nearest whole number of beats
114
- def to_i
115
- @value.round
116
- end
117
-
118
- def to_s
119
- value = @value.to_s
120
- value = sprintf '%.2f', @value if value.length > 6 # threshold is 6 for no particular reason...
121
- "#{value} #{@value.abs > 1 || @value==0 ? 'beats' : 'beat'}"
122
- end
123
-
124
- def inspect
125
- "#<#{self.class}:#{object_id} @value=#{@value}>"
126
- end
127
-
128
- def ==( other )
129
- if other.is_a? MTK::Duration
130
- other.value == @value
131
- else
132
- other == @value
133
- end
134
- end
135
-
136
- def <=> other
137
- if other.respond_to? :value
138
- @value <=> other.value
139
- else
140
- @value <=> other
141
- end
142
- end
143
-
144
- # Add this duration to another.
145
- # @return a new Duration that has a value of the sum of the arguments.
146
- def + duration
147
- if duration.is_a? MTK::Duration
148
- MTK::Duration[@value + duration.value]
149
- else
150
- MTK::Duration[@value + duration]
151
- end
152
- end
153
-
154
- # Subtract another duration from this one.
155
- # @return a new Duration that has a value of the difference of the arguments.
156
- def - duration
157
- if duration.is_a? MTK::Duration
158
- MTK::Duration[@value - duration.value]
159
- else
160
- MTK::Duration[@value - duration]
161
- end
162
- end
163
-
164
- # Multiply this duration with another.
165
- # @return a new Duration that has a value of the product of the arguments.
166
- def * duration
167
- if duration.is_a? MTK::Duration
168
- MTK::Duration[@value * duration.value]
169
- else
170
- MTK::Duration[@value * duration]
171
- end
172
- end
173
-
174
- # Divide this duration with another.
175
- # @return a new Duration that has a value of the division of the arguments.
176
- def / duration
177
- if duration.is_a? MTK::Duration
178
- MTK::Duration[to_f / duration.value]
179
- else
180
- MTK::Duration[to_f / duration]
181
- end
182
- end
183
-
184
- # Negate the duration value.
185
- # Turns normal durations into rests and vice versa.
186
- # @return a new Duration that has a negated value.
187
- # @see #rest?
188
- def -@
189
- MTK::Duration[@value * -1]
190
- end
191
-
192
- # Allow basic math operations with Numeric objects.
193
- def coerce(other)
194
- return MTK::Duration[other], self
195
- end
196
-
197
- end
198
-
199
- # Construct a {Duration} from any supported type
200
- def Duration(*anything)
201
- anything = anything.first if anything.length == 1
202
- case anything
203
- when Numeric then MTK::Duration[anything]
204
- when String, Symbol then MTK::Duration.from_s(anything)
205
- when Duration then anything
206
- else raise "Duration doesn't understand #{anything.class}"
207
- end
208
- end
209
- module_function :Duration
210
-
211
- end
@@ -1,36 +0,0 @@
1
- module MTK
2
- module Helpers
3
-
4
- module Convert
5
-
6
- def to_pitch_classes(*anything)
7
- anything = anything.first if anything.length == 1
8
- if anything.respond_to? :to_pitch_classes
9
- anything.to_pitch_classes
10
- else
11
- case anything
12
- when Enumerable then anything.map{|item| PitchClass(item) }
13
- else [PitchClass(anything)]
14
- end
15
- end
16
- end
17
- module_function :to_pitch_classes
18
-
19
-
20
- def to_pitches(*anything)
21
- anything = anything.first if anything.length == 1
22
- if anything.respond_to? :to_pitches
23
- anything.to_pitches
24
- else
25
- case anything
26
- when Enumerable then anything.map{|item| Pitch(item) }
27
- else [Pitch(anything)]
28
- end
29
- end
30
- end
31
- module_function :to_pitches
32
-
33
- end
34
-
35
- end
36
- end
@@ -1,67 +0,0 @@
1
- require 'mtk/midi/output'
2
-
3
- module MTK
4
- module Helpers
5
-
6
- # Optional class for loading the preferred platform-specific implementation of an output,
7
- # and methods to assist with selecting an output.
8
- class OutputSelector
9
-
10
- class << self
11
-
12
- def output
13
- MTK::MIDI::Output
14
- end
15
-
16
- # Look for an output by name using case insensitive matching,
17
- # treating underscore like either an underscore or whitespace
18
- def search output_name_pattern
19
- output.find_by_name(/#{output_name_pattern.to_s.sub '_','(_|\\s+)'}/i)
20
- end
21
-
22
- # Command line interface to list output choices and select an output.
23
- def prompt_for_output
24
- devices_by_name = output.devices_by_name
25
- names_by_number = {}
26
-
27
- puts "Available MIDI outputs:"
28
- devices_by_name.keys.each_with_index do |name,index|
29
- number = index+1
30
- names_by_number[number] = name
31
- puts " #{number} => #{name}"
32
- end
33
-
34
- print "Enter the number of the output to test: "
35
- device = nil
36
- loop do
37
- begin
38
- number = STDIN.gets.to_i
39
- name = names_by_number[number]
40
- device = devices_by_name[name]
41
- return output.open(device) if device
42
- rescue
43
- if $DEBUG
44
- puts $!
45
- puts $!.backtrace
46
- end
47
- # keep looping
48
- end
49
- print "Invalid input. Enter a number listed above: "
50
- end
51
- end
52
-
53
-
54
- def ensure_output name=nil
55
- output = nil
56
- if name
57
- output = search name
58
- puts "Output '#{name}' not found." unless output
59
- end
60
- output || prompt_for_output
61
- end
62
-
63
- end
64
-
65
- end
66
- end
67
- end