mtk 0.0.3.2 → 0.0.3.3

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 (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