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