mtk 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +3 -2
- data/DEVELOPMENT_NOTES.md +114 -0
- data/INTRO.md +64 -8
- data/LICENSE.txt +1 -1
- data/README.md +31 -102
- data/Rakefile +56 -18
- data/bin/mtk +215 -0
- data/examples/crescendo.rb +5 -5
- data/examples/drum_pattern1.rb +23 -0
- data/examples/dynamic_pattern.rb +8 -11
- data/examples/gets_and_play.rb +26 -0
- data/examples/notation.rb +22 -0
- data/examples/play_midi.rb +8 -10
- data/examples/random_tone_row.rb +2 -2
- data/examples/syntax_to_midi.rb +28 -0
- data/examples/test_output.rb +8 -0
- data/examples/tone_row_melody.rb +6 -6
- data/lib/mtk.rb +52 -40
- data/lib/mtk/chord.rb +55 -0
- data/lib/mtk/constants/durations.rb +57 -0
- data/lib/mtk/constants/intensities.rb +61 -0
- data/lib/mtk/constants/intervals.rb +73 -0
- data/lib/mtk/constants/pitch_classes.rb +29 -0
- data/lib/mtk/constants/pitches.rb +52 -0
- data/lib/mtk/duration.rb +211 -0
- data/lib/mtk/events/event.rb +119 -0
- data/lib/mtk/events/note.rb +112 -0
- data/lib/mtk/events/parameter.rb +54 -0
- data/lib/mtk/helpers/collection.rb +164 -0
- data/lib/mtk/helpers/convert.rb +36 -0
- data/lib/mtk/helpers/lilypond.rb +162 -0
- data/lib/mtk/helpers/output_selector.rb +67 -0
- data/lib/mtk/helpers/pitch_collection.rb +23 -0
- data/lib/mtk/helpers/pseudo_constants.rb +26 -0
- data/lib/mtk/intensity.rb +156 -0
- data/lib/mtk/interval.rb +155 -0
- data/lib/mtk/lang/mtk_grammar.citrus +190 -13
- data/lib/mtk/lang/parser.rb +29 -0
- data/lib/mtk/melody.rb +94 -0
- data/lib/mtk/midi/dls_synth_device.rb +144 -0
- data/lib/mtk/midi/dls_synth_output.rb +62 -0
- data/lib/mtk/midi/file.rb +67 -32
- data/lib/mtk/midi/input.rb +97 -0
- data/lib/mtk/midi/jsound_input.rb +36 -17
- data/lib/mtk/midi/jsound_output.rb +48 -46
- data/lib/mtk/midi/output.rb +195 -0
- data/lib/mtk/midi/unimidi_input.rb +117 -0
- data/lib/mtk/midi/unimidi_output.rb +121 -0
- data/lib/mtk/{_numeric_extensions.rb → numeric_extensions.rb} +12 -0
- data/lib/mtk/patterns/chain.rb +49 -0
- data/lib/mtk/{pattern → patterns}/choice.rb +14 -8
- data/lib/mtk/patterns/cycle.rb +18 -0
- data/lib/mtk/patterns/for_each.rb +71 -0
- data/lib/mtk/patterns/function.rb +39 -0
- data/lib/mtk/{pattern → patterns}/lines.rb +11 -17
- data/lib/mtk/{pattern → patterns}/palindrome.rb +11 -8
- data/lib/mtk/patterns/pattern.rb +171 -0
- data/lib/mtk/patterns/sequence.rb +20 -0
- data/lib/mtk/pitch.rb +7 -6
- data/lib/mtk/pitch_class.rb +124 -46
- data/lib/mtk/pitch_class_set.rb +58 -35
- data/lib/mtk/sequencers/event_builder.rb +131 -0
- data/lib/mtk/sequencers/legato_sequencer.rb +24 -0
- data/lib/mtk/sequencers/rhythmic_sequencer.rb +28 -0
- data/lib/mtk/{sequencer/abstract_sequencer.rb → sequencers/sequencer.rb} +37 -11
- data/lib/mtk/{sequencer → sequencers}/step_sequencer.rb +4 -4
- data/lib/mtk/timeline.rb +39 -22
- data/lib/mtk/variable.rb +32 -0
- data/spec/mtk/chord_spec.rb +83 -0
- data/spec/mtk/{_constants → constants}/durations_spec.rb +12 -41
- data/spec/mtk/{_constants → constants}/intensities_spec.rb +13 -37
- data/spec/mtk/{_constants → constants}/intervals_spec.rb +14 -32
- data/spec/mtk/{_constants → constants}/pitch_classes_spec.rb +8 -4
- data/spec/mtk/{_constants → constants}/pitches_spec.rb +5 -1
- data/spec/mtk/duration_spec.rb +372 -0
- data/spec/mtk/events/event_spec.rb +234 -0
- data/spec/mtk/events/note_spec.rb +174 -0
- data/spec/mtk/events/parameter_spec.rb +220 -0
- data/spec/mtk/{helper → helpers}/collection_spec.rb +86 -3
- data/spec/mtk/{helper → helpers}/pseudo_constants_spec.rb +2 -2
- data/spec/mtk/intensity_spec.rb +289 -0
- data/spec/mtk/interval_spec.rb +265 -0
- data/spec/mtk/lang/parser_spec.rb +597 -0
- data/spec/mtk/melody_spec.rb +223 -0
- data/spec/mtk/midi/file_spec.rb +16 -16
- data/spec/mtk/midi/jsound_input_spec.rb +11 -0
- data/spec/mtk/midi/jsound_output_spec.rb +11 -0
- data/spec/mtk/midi/output_spec.rb +102 -0
- data/spec/mtk/midi/unimidi_input_spec.rb +11 -0
- data/spec/mtk/midi/unimidi_output_spec.rb +11 -0
- data/spec/mtk/{_numeric_extensions_spec.rb → numeric_extensions_spec.rb} +1 -0
- data/spec/mtk/patterns/chain_spec.rb +110 -0
- data/spec/mtk/{pattern → patterns}/choice_spec.rb +20 -30
- data/spec/mtk/{pattern → patterns}/cycle_spec.rb +25 -35
- data/spec/mtk/patterns/for_each_spec.rb +136 -0
- data/spec/mtk/{pattern → patterns}/function_spec.rb +17 -30
- data/spec/mtk/{pattern → patterns}/lines_spec.rb +11 -27
- data/spec/mtk/{pattern → patterns}/palindrome_spec.rb +13 -29
- data/spec/mtk/patterns/pattern_spec.rb +132 -0
- data/spec/mtk/patterns/sequence_spec.rb +203 -0
- data/spec/mtk/pitch_class_set_spec.rb +23 -21
- data/spec/mtk/pitch_class_spec.rb +151 -39
- data/spec/mtk/pitch_spec.rb +22 -1
- data/spec/mtk/sequencers/event_builder_spec.rb +245 -0
- data/spec/mtk/sequencers/legato_sequencer_spec.rb +45 -0
- data/spec/mtk/sequencers/rhythmic_sequencer_spec.rb +84 -0
- data/spec/mtk/sequencers/sequencer_spec.rb +215 -0
- data/spec/mtk/{sequencer → sequencers}/step_sequencer_spec.rb +35 -13
- data/spec/mtk/timeline_spec.rb +109 -16
- data/spec/mtk/variable_spec.rb +52 -0
- data/spec/spec_coverage.rb +2 -0
- data/spec/spec_helper.rb +3 -0
- metadata +188 -91
- data/lib/mtk/_constants/durations.rb +0 -80
- data/lib/mtk/_constants/intensities.rb +0 -81
- data/lib/mtk/_constants/intervals.rb +0 -85
- data/lib/mtk/_constants/pitch_classes.rb +0 -35
- data/lib/mtk/_constants/pitches.rb +0 -49
- data/lib/mtk/event.rb +0 -70
- data/lib/mtk/helper/collection.rb +0 -114
- data/lib/mtk/helper/event_builder.rb +0 -85
- data/lib/mtk/helper/pseudo_constants.rb +0 -26
- data/lib/mtk/lang/grammar.rb +0 -17
- data/lib/mtk/note.rb +0 -63
- data/lib/mtk/pattern/abstract_pattern.rb +0 -132
- data/lib/mtk/pattern/cycle.rb +0 -51
- data/lib/mtk/pattern/enumerator.rb +0 -26
- data/lib/mtk/pattern/function.rb +0 -46
- data/lib/mtk/pattern/sequence.rb +0 -30
- data/lib/mtk/pitch_set.rb +0 -84
- data/lib/mtk/sequencer/rhythmic_sequencer.rb +0 -29
- data/lib/mtk/transform/invertible.rb +0 -15
- data/lib/mtk/transform/mappable.rb +0 -18
- data/lib/mtk/transform/set_theory_operations.rb +0 -34
- data/lib/mtk/transform/transposable.rb +0 -14
- data/spec/mtk/event_spec.rb +0 -139
- data/spec/mtk/helper/event_builder_spec.rb +0 -92
- data/spec/mtk/lang/grammar_spec.rb +0 -100
- data/spec/mtk/note_spec.rb +0 -115
- data/spec/mtk/pattern/abstract_pattern_spec.rb +0 -45
- data/spec/mtk/pattern/note_cycle_spec.rb.bak +0 -116
- data/spec/mtk/pattern/pitch_cycle_spec.rb.bak +0 -47
- data/spec/mtk/pattern/pitch_sequence_spec.rb.bak +0 -37
- data/spec/mtk/pattern/sequence_spec.rb +0 -151
- data/spec/mtk/pitch_set_spec.rb +0 -198
- data/spec/mtk/sequencer/abstract_sequencer_spec.rb +0 -159
- data/spec/mtk/sequencer/rhythmic_sequencer_spec.rb +0 -49
@@ -1,100 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'mtk/lang/grammar'
|
3
|
-
|
4
|
-
describe MTK::Lang::Grammar do
|
5
|
-
|
6
|
-
def parse syntax, root
|
7
|
-
MTK::Lang::Grammar.parse(syntax, root)
|
8
|
-
end
|
9
|
-
|
10
|
-
describe ".parse" do
|
11
|
-
|
12
|
-
it "should parse pitch sequences" do
|
13
|
-
parse("C4 D4 E4", :pitch_sequence).should == Pattern.PitchSequence(C4, D4, E4)
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should parse pitches" do
|
17
|
-
for pitch_class_name in PitchClass::VALID_NAMES
|
18
|
-
for octave in -1..9
|
19
|
-
parse("#{pitch_class_name}#{octave}", :pitch).should == Pitch[PitchClass[pitch_class_name],octave]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
it "should parse pitch classes" do
|
25
|
-
for pitch_class_name in PitchClass::VALID_NAMES
|
26
|
-
parse(pitch_class_name, :pitch_class).should == PitchClass[pitch_class_name]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should parse intervals" do
|
31
|
-
for interval_name in Intervals::INTERVAL_NAMES
|
32
|
-
parse(interval_name, :interval).should == Intervals[interval_name]
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should parse intensities" do
|
37
|
-
for intensity_name in Intensities::INTENSITY_NAMES
|
38
|
-
parse(intensity_name, :intensity).should == Intensities[intensity_name]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
it "should parse intensities with + and - modifiers" do
|
43
|
-
for intensity_name in Intensities::INTENSITY_NAMES
|
44
|
-
name = "#{intensity_name}+"
|
45
|
-
parse(name, :intensity).should == Intensities[name]
|
46
|
-
name = "#{intensity_name}-"
|
47
|
-
parse(name, :intensity).should == Intensities[name]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should parse durations" do
|
52
|
-
for duration in Durations::DURATION_NAMES
|
53
|
-
parse(duration, :duration).should == Durations[duration]
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
it "should parse durations with . and t modifiers" do
|
58
|
-
for duration in Durations::DURATION_NAMES
|
59
|
-
name = "#{duration}."
|
60
|
-
parse(name, :duration).should == Durations[name]
|
61
|
-
name = "#{duration}t"
|
62
|
-
parse(name, :duration).should == Durations[name]
|
63
|
-
name = "#{duration}..t.t"
|
64
|
-
parse(name, :duration).should == Durations[name]
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
it "should parse ints as numbers" do
|
69
|
-
parse("123", :number).should == 123
|
70
|
-
end
|
71
|
-
|
72
|
-
it "should parse floats as numbers" do
|
73
|
-
parse("1.23", :number).should == 1.23
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should parse floats" do
|
77
|
-
parse("1.23", :float).should == 1.23
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should parse negative floats" do
|
81
|
-
parse("-1.23", :float).should == -1.23
|
82
|
-
end
|
83
|
-
|
84
|
-
it "should parse ints" do
|
85
|
-
parse("123", :int).should == 123
|
86
|
-
end
|
87
|
-
|
88
|
-
it "should parse negative ints" do
|
89
|
-
parse("-123", :int).should == -123
|
90
|
-
end
|
91
|
-
|
92
|
-
it "should parse negative ints" do
|
93
|
-
parse("-123", :int).should == -123
|
94
|
-
end
|
95
|
-
|
96
|
-
it "should give nil as the value for whitespace" do
|
97
|
-
parse(" \t\n", :space).should == nil
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
data/spec/mtk/note_spec.rb
DELETED
@@ -1,115 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe MTK::Note do
|
4
|
-
|
5
|
-
let(:pitch) { C4 }
|
6
|
-
let(:intensity) { mf }
|
7
|
-
let(:duration) { 2.5 }
|
8
|
-
let(:note) { Note.new(pitch, intensity, duration) }
|
9
|
-
|
10
|
-
describe "#pitch" do
|
11
|
-
it "is the pitch used to create the Note" do
|
12
|
-
note.pitch.should == pitch
|
13
|
-
end
|
14
|
-
|
15
|
-
it "is a read-only attribute" do
|
16
|
-
lambda{ note.pitch = D4 }.should raise_error
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe ".from_hash" do
|
21
|
-
it "constructs a Note using a hash" do
|
22
|
-
Note.from_hash({ :pitch => C4, :intensity => intensity, :duration => duration }).should == note
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe '.from_midi' do
|
27
|
-
it "constructs a Note using a MIDI pitch and velocity" do
|
28
|
-
Note.from_midi(C4.to_i, mf*127, 2.5).should == note
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe "#to_midi" do
|
33
|
-
it "converts the Note to an Array of MIDI values: [pitch, velocity, duration]" do
|
34
|
-
note.to_midi.should == [60, (mf*127).round, duration]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe "#to_hash" do
|
39
|
-
it "is a hash containing all the attributes of the Note" do
|
40
|
-
note.to_hash.should == { :pitch => pitch, :intensity => intensity, :duration => duration }
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
describe '#transpose' do
|
45
|
-
it 'adds the given interval to the @pitch' do
|
46
|
-
(note.transpose 2.semitones).should == Note.new(D4, intensity, duration)
|
47
|
-
end
|
48
|
-
it 'does not affect the immutability of the Note' do
|
49
|
-
(note.transpose 2.semitones).should_not == note
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "#invert" do
|
54
|
-
context 'higher center pitch' do
|
55
|
-
it 'inverts the pitch around the given center pitch' do
|
56
|
-
note.invert(Pitch 66).should == Note.new(Pitch(72), intensity, duration)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
context 'lower center pitch' do
|
61
|
-
it 'inverts the pitch around the given center pitch' do
|
62
|
-
note.invert(Pitch 54).should == Note.new(Pitch(48), intensity, duration)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
it "returns the an equal note when given it's pitch as an argument" do
|
67
|
-
note.invert(note.pitch).should == note
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
describe "#==" do
|
72
|
-
it "is true when the pitches, intensities, and durations are equal" do
|
73
|
-
note.should == Note.new(pitch, intensity, duration)
|
74
|
-
end
|
75
|
-
|
76
|
-
it "is false when the pitches are not equal" do
|
77
|
-
note.should_not == Note.new(pitch + 1, intensity, duration)
|
78
|
-
end
|
79
|
-
|
80
|
-
it "is false when the intensities are not equal" do
|
81
|
-
note.should_not == Note.new(pitch, intensity * 0.5, duration)
|
82
|
-
end
|
83
|
-
|
84
|
-
it "is false when the durations are not equal" do
|
85
|
-
note.should_not == Note.new(pitch, intensity, duration * 2)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|
90
|
-
|
91
|
-
describe MTK do
|
92
|
-
|
93
|
-
describe '#Note' do
|
94
|
-
|
95
|
-
it "acts like new for multiple arguments" do
|
96
|
-
Note(C4,mf,1).should == Note.new(C4,mf,1)
|
97
|
-
end
|
98
|
-
|
99
|
-
it "acts like new for an Array of arguments by unpacking (splatting) them" do
|
100
|
-
Note([C4,mf,1]).should == Note.new(C4,mf,1)
|
101
|
-
end
|
102
|
-
|
103
|
-
it "returns the argument if it's already a Note" do
|
104
|
-
note = Note.new(C4,mf,1)
|
105
|
-
Note(note).should be_equal note
|
106
|
-
end
|
107
|
-
|
108
|
-
it "raises an error for types it doesn't understand" do
|
109
|
-
lambda{ Note({:not => :compatible}) }.should raise_error
|
110
|
-
end
|
111
|
-
|
112
|
-
end
|
113
|
-
|
114
|
-
end
|
115
|
-
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe MTK::Pattern::AbstractPattern do
|
4
|
-
|
5
|
-
PATTERN = MTK::Pattern::AbstractPattern
|
6
|
-
|
7
|
-
let(:elements) { [1,2,3] }
|
8
|
-
|
9
|
-
describe "#type" do
|
10
|
-
it "is the :type value from the constuctor's options hash" do
|
11
|
-
PATTERN.new([], :type => :my_type).type.should == :my_type
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "#max_elements" do
|
16
|
-
it "is the :max_elements option the pattern was constructed with" do
|
17
|
-
PATTERN.new([], :max_elements => 1).max_elements.should == 1
|
18
|
-
end
|
19
|
-
|
20
|
-
it "is nil by default" do
|
21
|
-
PATTERN.new([]).max_elements.should be_nil
|
22
|
-
end
|
23
|
-
|
24
|
-
it "causes a StopIteration exception after the number of elements have been emitted" do
|
25
|
-
cycle = PATTERN.new([:anything], :max_elements => 5)
|
26
|
-
5.times { cycle.next }
|
27
|
-
lambda { cycle.next }.should raise_error
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe "#==" do
|
32
|
-
it "is true if the elements and types are equal" do
|
33
|
-
PATTERN.new(elements, :type => :some_type).should == PATTERN.new(elements, :type => :some_type)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "is false if the elements are not equal" do
|
37
|
-
PATTERN.new(elements, :type => :some_type).should_not == PATTERN.new(elements + [4], :type => :some_type)
|
38
|
-
end
|
39
|
-
|
40
|
-
it "is false if the types are not equal" do
|
41
|
-
PATTERN.new(elements, :type => :some_type).should_not == PATTERN.new(elements, :type => :another_type)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
@@ -1,116 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe MTK::Pattern::NoteCycle do
|
4
|
-
|
5
|
-
def note(pitch, intensity=mf, duration=1)
|
6
|
-
Note(pitch, intensity, duration)
|
7
|
-
end
|
8
|
-
|
9
|
-
describe "#new" do
|
10
|
-
it "allows default pitch to be specified" do
|
11
|
-
cycle = Pattern::NoteCycle.new [], [p], [1], :pitch => Gb4
|
12
|
-
cycle.next.should == Note(Gb4, p, 1)
|
13
|
-
end
|
14
|
-
it "allows default intensity to be specified" do
|
15
|
-
cycle = Pattern::NoteCycle.new [C4], [], [1], :intensity => ppp
|
16
|
-
cycle.next.should == Note(C4, ppp, 1)
|
17
|
-
end
|
18
|
-
it "allows default duration to be specified" do
|
19
|
-
cycle = Pattern::NoteCycle.new [C4], [mf], [], :duration => 12
|
20
|
-
cycle.next.should == Note(C4, mf, 12)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe "#next" do
|
25
|
-
it "iterates through the pitch, intensity, and duration list in parallel to emit Notes" do
|
26
|
-
cycle = Pattern::NoteCycle.new [C4, D4, E4], [p, f], [1,2,3,4]
|
27
|
-
cycle.next.should == Note(C4, p, 1)
|
28
|
-
cycle.next.should == Note(D4, f, 2)
|
29
|
-
cycle.next.should == Note(E4, p, 3)
|
30
|
-
cycle.next.should == Note(C4, f, 4)
|
31
|
-
cycle.next.should == Note(D4, p, 1)
|
32
|
-
cycle.next.should == Note(E4, f, 2)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "defaults to Pitch 'C4' when no pitches are given" do
|
36
|
-
cycle = Pattern::NoteCycle.new [], [p,f], [1,2,3]
|
37
|
-
cycle.next.should == Note(C4, p, 1)
|
38
|
-
cycle.next.should == Note(C4, f, 2)
|
39
|
-
cycle.next.should == Note(C4, p, 3)
|
40
|
-
end
|
41
|
-
|
42
|
-
it "defaults to intensity 'mf' when no intensities are given" do
|
43
|
-
cycle = Pattern::NoteCycle.new [C4, D4, E4], nil, [2]
|
44
|
-
cycle.next.should == Note(C4, mf, 2)
|
45
|
-
cycle.next.should == Note(D4, mf, 2)
|
46
|
-
cycle.next.should == Note(E4, mf, 2)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "defaults to duration 1 when no durations are given" do
|
50
|
-
cycle = Pattern::NoteCycle.new [C4, D4, E4], [p, f]
|
51
|
-
cycle.next.should == Note(C4, p, 1)
|
52
|
-
cycle.next.should == Note(D4, f, 1)
|
53
|
-
cycle.next.should == Note(E4, p, 1)
|
54
|
-
end
|
55
|
-
|
56
|
-
it "uses the previous pitch/intensity/duration when it encounters a nil value" do
|
57
|
-
cycle = Pattern::NoteCycle.new [C4, D4, E4, F4, nil], [mp, mf, f, nil], [1, 2, nil]
|
58
|
-
cycle.next.should == Note(C4, mp, 1)
|
59
|
-
cycle.next.should == Note(D4, mf, 2)
|
60
|
-
cycle.next.should == Note(E4, f, 2)
|
61
|
-
cycle.next.should == Note(F4, f, 1)
|
62
|
-
cycle.next.should == Note(F4, mp, 2)
|
63
|
-
cycle.next.should == Note(C4, mf, 2)
|
64
|
-
end
|
65
|
-
|
66
|
-
it "adds Numeric intervals in the pitch list to the previous pitch" do
|
67
|
-
cycle = Pattern::NoteCycle.new [C4, 1, 2, 3]
|
68
|
-
cycle.next.should == note(C4)
|
69
|
-
cycle.next.should == note(C4+1)
|
70
|
-
cycle.next.should == note(C4+1+2)
|
71
|
-
cycle.next.should == note(C4+1+2+3)
|
72
|
-
cycle.next.should == note(C4)
|
73
|
-
end
|
74
|
-
|
75
|
-
it "goes to the nearest Pitch for any PitchClasses in the pitch list" do
|
76
|
-
cycle = Pattern::NoteCycle.new [C4, F, C, G, C]
|
77
|
-
cycle.next.should == note(C4)
|
78
|
-
cycle.next.should == note(F4)
|
79
|
-
cycle.next.should == note(C4)
|
80
|
-
cycle.next.should == note(G3)
|
81
|
-
cycle.next.should == note(C4)
|
82
|
-
end
|
83
|
-
|
84
|
-
it "does not endlessly ascend or descend when alternating between two pitch classes a tritone apart" do
|
85
|
-
cycle = Pattern::NoteCycle.new [C4, Gb, C, Gb, C]
|
86
|
-
cycle.next.should == note(C4)
|
87
|
-
cycle.next.should == note(Gb4)
|
88
|
-
cycle.next.should == note(C4)
|
89
|
-
cycle.next.should == note(Gb4)
|
90
|
-
cycle.next.should == note(C4)
|
91
|
-
end
|
92
|
-
|
93
|
-
it "cycles Note Arrays for pitch list items that are PitchSets" do
|
94
|
-
cycle = Pattern::NoteCycle.new [PitchSet.new([C4, E4, G4]), C4, PitchSet.new([D4, F4, A4])]
|
95
|
-
cycle.next.should == [note(C4), note(E4), note(G4)]
|
96
|
-
cycle.next.should == note(C4)
|
97
|
-
cycle.next.should == [note(D4), note(F4), note(A4)]
|
98
|
-
end
|
99
|
-
|
100
|
-
it "adds numeric intervals to PitchSets" do
|
101
|
-
cycle = Pattern::NoteCycle.new [PitchSet.new([C4, E4, G4]), 2]
|
102
|
-
cycle.next.should == [note(C4), note(E4), note(G4)]
|
103
|
-
cycle.next.should == [note(D4), note(Gb4), note(A4)]
|
104
|
-
end
|
105
|
-
|
106
|
-
it "goes to the nearest Pitch relative to the lowest note in the PitchSet for any PitchClasses in the pitch list" do
|
107
|
-
cycle = Pattern::NoteCycle.new [PitchSet.new([C4, E4, G4]), F, D, Bb]
|
108
|
-
cycle.next.should == [note(C4), note(E4), note(G4)]
|
109
|
-
cycle.next.should == [note(F4), note(A4), note(C5)]
|
110
|
-
cycle.next.should == [note(D4), note(Gb4), note(A4)]
|
111
|
-
cycle.next.should == [note(Bb3), note(D4), note(F4)]
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
|
116
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe MTK::Pattern::PitchCycle do
|
4
|
-
|
5
|
-
describe "#next" do
|
6
|
-
it "enumerates Pitches" do
|
7
|
-
cycle = Pattern::PitchCycle.new [C4, D4, E4]
|
8
|
-
cycle.next.should == C4
|
9
|
-
cycle.next.should == D4
|
10
|
-
cycle.next.should == E4
|
11
|
-
end
|
12
|
-
|
13
|
-
it "adds Numeric elements (intervals) to the previous pitch" do
|
14
|
-
cycle = Pattern::PitchCycle.new [C4, 1, 2, 3]
|
15
|
-
cycle.next.should == C4
|
16
|
-
cycle.next.should == C4+1
|
17
|
-
cycle.next.should == C4+1+2
|
18
|
-
cycle.next.should == C4+1+2+3
|
19
|
-
end
|
20
|
-
|
21
|
-
it "returns a Pitch when encountering a Pitch after another type" do
|
22
|
-
cycle = Pattern::PitchCycle.new [C4, 1, C4]
|
23
|
-
cycle.next
|
24
|
-
cycle.next
|
25
|
-
cycle.next.should == C4
|
26
|
-
end
|
27
|
-
|
28
|
-
it "goes to the nearest Pitch for any PitchClasses in the pitch list" do
|
29
|
-
cycle = Pattern::PitchCycle.new [C4, F, C, G, C]
|
30
|
-
cycle.next.should == C4
|
31
|
-
cycle.next.should == F4
|
32
|
-
cycle.next.should == C4
|
33
|
-
cycle.next.should == G3
|
34
|
-
cycle.next.should == C4
|
35
|
-
end
|
36
|
-
|
37
|
-
it "does not endlessly ascend or descend when alternating between two pitch classes a tritone apart" do
|
38
|
-
cycler = Pattern::PitchCycle.new [C4, Gb, C, Gb, C]
|
39
|
-
cycler.next.should == C4
|
40
|
-
cycler.next.should == Gb4
|
41
|
-
cycler.next.should == C4
|
42
|
-
cycler.next.should == Gb4
|
43
|
-
cycler.next.should == C4
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe MTK::Pattern::PitchSequence do
|
4
|
-
|
5
|
-
let(:pitches) { [C4,D4,E4] }
|
6
|
-
let(:pitch_sequence) { Pattern::PitchSequence.new(pitches) }
|
7
|
-
|
8
|
-
|
9
|
-
describe ".from_pitch_classes" do
|
10
|
-
it "creates a pitch sequence from a list of pitch classes and starting point, selecting the nearest pitch to each pitch class" do
|
11
|
-
Pattern::PitchSequence.from_pitch_classes([C,G,B,Eb,D,C], D3).should == [C3,G2,B2,Eb3,D3,C3]
|
12
|
-
end
|
13
|
-
|
14
|
-
it "defaults to a starting point of C4 (middle C)" do
|
15
|
-
Pattern::PitchSequence.from_pitch_classes([C]).should == [C4]
|
16
|
-
end
|
17
|
-
|
18
|
-
it "doesn't travel within an octave above or below the starting point by default" do
|
19
|
-
Pattern::PitchSequence.from_pitch_classes([C,F,Bb,D,A,E,B]).should == [C4,F4,Bb4,D4,A3,E3,B3]
|
20
|
-
end
|
21
|
-
|
22
|
-
it "allows max distance above or below the starting point to be set via the third argument" do
|
23
|
-
Pattern::PitchSequence.from_pitch_classes([C,F,Bb,D,A,E,B], C4, 6).should == [C4,F4,Bb3,D4,A3,E4,B3]
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
describe MTK::Pattern do
|
31
|
-
|
32
|
-
it "converts the arguments to Pitches when possible" do
|
33
|
-
Pattern.PitchSequence(:C4,:D4,:E4).elements.should == [C4,D4,E4]
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|