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.
- data/.yardopts +2 -2
- data/DEVELOPMENT_NOTES.md +20 -0
- data/README.md +9 -3
- data/Rakefile +47 -13
- data/bin/mtk +55 -20
- data/examples/crescendo.rb +4 -4
- data/examples/{drum_pattern1.rb → drum_pattern.rb} +8 -8
- data/examples/dynamic_pattern.rb +5 -5
- data/examples/gets_and_play.rb +3 -2
- data/examples/notation.rb +3 -3
- data/examples/play_midi.rb +4 -4
- data/examples/print_midi.rb +2 -2
- data/examples/random_tone_row.rb +3 -3
- data/examples/syntax_to_midi.rb +2 -2
- data/examples/test_output.rb +4 -5
- data/examples/tone_row_melody.rb +7 -5
- data/lib/mtk/core/duration.rb +213 -0
- data/lib/mtk/core/intensity.rb +158 -0
- data/lib/mtk/core/interval.rb +157 -0
- data/lib/mtk/core/pitch.rb +154 -0
- data/lib/mtk/core/pitch_class.rb +194 -0
- data/lib/mtk/events/event.rb +4 -4
- data/lib/mtk/events/note.rb +12 -12
- data/lib/mtk/events/timeline.rb +232 -0
- data/lib/mtk/groups/chord.rb +56 -0
- data/lib/mtk/{helpers → groups}/collection.rb +33 -1
- data/lib/mtk/groups/melody.rb +96 -0
- data/lib/mtk/groups/pitch_class_set.rb +163 -0
- data/lib/mtk/{helpers → groups}/pitch_collection.rb +1 -1
- data/lib/mtk/{midi → io}/dls_synth_device.rb +3 -1
- data/lib/mtk/{midi → io}/dls_synth_output.rb +10 -10
- data/lib/mtk/{midi → io}/jsound_input.rb +2 -2
- data/lib/mtk/{midi → io}/jsound_output.rb +9 -9
- data/lib/mtk/{midi/file.rb → io/midi_file.rb} +13 -13
- data/lib/mtk/{midi/input.rb → io/midi_input.rb} +4 -4
- data/lib/mtk/{midi/output.rb → io/midi_output.rb} +8 -8
- data/lib/mtk/{helpers/lilypond.rb → io/notation.rb} +5 -5
- data/lib/mtk/{midi → io}/unimidi_input.rb +2 -2
- data/lib/mtk/{midi → io}/unimidi_output.rb +14 -9
- data/lib/mtk/{constants → lang}/durations.rb +11 -11
- data/lib/mtk/{constants → lang}/intensities.rb +11 -11
- data/lib/mtk/{constants → lang}/intervals.rb +17 -17
- data/lib/mtk/lang/mtk_grammar.citrus +9 -9
- data/lib/mtk/{constants → lang}/pitch_classes.rb +5 -5
- data/lib/mtk/{constants → lang}/pitches.rb +7 -7
- data/lib/mtk/{helpers → lang}/pseudo_constants.rb +1 -1
- data/lib/mtk/{variable.rb → lang/variable.rb} +1 -1
- data/lib/mtk/numeric_extensions.rb +40 -47
- data/lib/mtk/patterns/for_each.rb +1 -1
- data/lib/mtk/patterns/pattern.rb +3 -3
- data/lib/mtk/sequencers/event_builder.rb +16 -15
- data/lib/mtk/sequencers/legato_sequencer.rb +1 -1
- data/lib/mtk/sequencers/rhythmic_sequencer.rb +1 -1
- data/lib/mtk/sequencers/sequencer.rb +8 -8
- data/lib/mtk/sequencers/step_sequencer.rb +2 -2
- data/lib/mtk.rb +33 -39
- data/spec/mtk/{duration_spec.rb → core/duration_spec.rb} +3 -3
- data/spec/mtk/{intensity_spec.rb → core/intensity_spec.rb} +3 -3
- data/spec/mtk/{interval_spec.rb → core/interval_spec.rb} +1 -1
- data/spec/mtk/{pitch_class_spec.rb → core/pitch_class_spec.rb} +1 -1
- data/spec/mtk/{pitch_spec.rb → core/pitch_spec.rb} +8 -8
- data/spec/mtk/events/event_spec.rb +4 -4
- data/spec/mtk/events/note_spec.rb +8 -8
- data/spec/mtk/{timeline_spec.rb → events/timeline_spec.rb} +47 -47
- data/spec/mtk/{chord_spec.rb → groups/chord_spec.rb} +18 -16
- data/spec/mtk/{helpers → groups}/collection_spec.rb +3 -3
- data/spec/mtk/{melody_spec.rb → groups/melody_spec.rb} +36 -34
- data/spec/mtk/{pitch_class_set_spec.rb → groups/pitch_class_set_spec.rb} +57 -55
- data/spec/mtk/{midi/file_spec.rb → io/midi_file_spec.rb} +17 -17
- data/spec/mtk/{midi/output_spec.rb → io/midi_output_spec.rb} +6 -6
- data/spec/mtk/{constants → lang}/durations_spec.rb +1 -1
- data/spec/mtk/{constants → lang}/intensities_spec.rb +1 -1
- data/spec/mtk/{constants → lang}/intervals_spec.rb +1 -1
- data/spec/mtk/lang/parser_spec.rb +12 -6
- data/spec/mtk/{constants → lang}/pitch_classes_spec.rb +1 -1
- data/spec/mtk/{constants → lang}/pitches_spec.rb +1 -1
- data/spec/mtk/{helpers → lang}/pseudo_constants_spec.rb +2 -2
- data/spec/mtk/{variable_spec.rb → lang/variable_spec.rb} +4 -4
- data/spec/mtk/numeric_extensions_spec.rb +35 -55
- data/spec/mtk/patterns/for_each_spec.rb +1 -1
- data/spec/mtk/patterns/sequence_spec.rb +1 -1
- data/spec/mtk/sequencers/legato_sequencer_spec.rb +2 -2
- data/spec/mtk/sequencers/rhythmic_sequencer_spec.rb +4 -4
- data/spec/mtk/sequencers/step_sequencer_spec.rb +5 -5
- data/spec/spec_helper.rb +7 -6
- metadata +75 -61
- data/ext/mkrf_conf.rb +0 -25
- data/lib/mtk/chord.rb +0 -55
- data/lib/mtk/duration.rb +0 -211
- data/lib/mtk/helpers/convert.rb +0 -36
- data/lib/mtk/helpers/output_selector.rb +0 -67
- data/lib/mtk/intensity.rb +0 -156
- data/lib/mtk/interval.rb +0 -155
- data/lib/mtk/melody.rb +0 -94
- data/lib/mtk/pitch.rb +0 -152
- data/lib/mtk/pitch_class.rb +0 -192
- data/lib/mtk/pitch_class_set.rb +0 -161
- data/lib/mtk/timeline.rb +0 -230
- data/spec/mtk/midi/jsound_input_spec.rb +0 -11
- data/spec/mtk/midi/jsound_output_spec.rb +0 -11
- data/spec/mtk/midi/unimidi_input_spec.rb +0 -11
- 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.
|
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-
|
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/
|
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/
|
90
|
-
- lib/mtk/
|
91
|
-
- lib/mtk/
|
92
|
-
- lib/mtk/
|
93
|
-
- lib/mtk/
|
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/
|
100
|
-
- lib/mtk/
|
101
|
-
- lib/mtk/
|
102
|
-
- lib/mtk/
|
103
|
-
- lib/mtk/
|
104
|
-
- lib/mtk/
|
105
|
-
- lib/mtk/
|
106
|
-
- lib/mtk/
|
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/
|
110
|
-
- lib/mtk/
|
111
|
-
- lib/mtk/
|
112
|
-
- lib/mtk/
|
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/
|
141
|
-
- spec/mtk/
|
142
|
-
- spec/mtk/
|
143
|
-
- spec/mtk/
|
144
|
-
- spec/mtk/
|
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/
|
151
|
-
- spec/mtk/
|
152
|
-
- spec/mtk/
|
153
|
-
- spec/mtk/
|
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/
|
156
|
-
- spec/mtk/
|
157
|
-
- spec/mtk/
|
158
|
-
- spec/mtk/
|
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
|
data/lib/mtk/helpers/convert.rb
DELETED
@@ -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
|