musicality 0.11.1 → 0.12.0
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.
- checksums.yaml +5 -5
- data/.coveralls.yml +1 -0
- data/.ruby-version +1 -1
- data/.travis.yml +4 -0
- data/ChangeLog.md +11 -0
- data/README.md +3 -0
- data/Rakefile +11 -3
- data/lib/musicality/composition/model/rhythm.rb +33 -0
- data/lib/musicality/composition/model/rhythm_class.rb +30 -0
- data/lib/musicality/composition/sequencing/drum_machine/drum_kit.rb +18 -0
- data/lib/musicality/composition/sequencing/drum_machine/drum_machine.rb +59 -0
- data/lib/musicality/composition/sequencing/drum_machine/drum_parts.rb +21 -0
- data/lib/musicality/composition/sequencing/drum_machine/drum_pattern.rb +66 -0
- data/lib/musicality/composition/sequencing/drum_machine/drum_patterns/pop_drum_patterns.rb +146 -0
- data/lib/musicality/composition/sequencing/note_array.rb +33 -0
- data/lib/musicality/composition/sequencing/note_fifo.rb +73 -0
- data/lib/musicality/composition/sequencing/sequenceable.rb +9 -0
- data/lib/musicality/composition/sequencing/sequencer.rb +35 -0
- data/lib/musicality/errors.rb +2 -2
- data/lib/musicality/notation/model/dynamics.rb +2 -2
- data/lib/musicality/notation/model/key.rb +42 -91
- data/lib/musicality/notation/model/keys.rb +35 -34
- data/lib/musicality/notation/model/note.rb +31 -9
- data/lib/musicality/notation/model/pitch.rb +2 -2
- data/lib/musicality/notation/parsing/convenience_methods.rb +23 -12
- data/lib/musicality/notation/parsing/duration_parsing.rb +3 -3
- data/lib/musicality/notation/parsing/key_parsing.rb +150 -0
- data/lib/musicality/notation/parsing/key_parsing.treetop +37 -0
- data/lib/musicality/notation/parsing/meter_parsing.rb +3 -3
- data/lib/musicality/notation/parsing/numbers/nonnegative_float_parsing.rb +3 -1
- data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +1 -0
- data/lib/musicality/notation/parsing/numbers/nonnegative_rational_parsing.rb +1 -1
- data/lib/musicality/notation/parsing/numbers/positive_float_parsing.rb +4 -1
- data/lib/musicality/notation/parsing/numbers/positive_rational_parsing.rb +1 -1
- data/lib/musicality/notation/parsing/parseable.rb +13 -17
- data/lib/musicality/notation/parsing/pitch_parsing.rb +7 -0
- data/lib/musicality/notation/parsing/segment_parsing.rb +3 -0
- data/lib/musicality/performance/conversion/note_sequence_extractor.rb +82 -134
- data/lib/musicality/performance/model/note_sequence.rb +22 -3
- data/lib/musicality/performance/supercollider/performer.rb +2 -2
- data/lib/musicality/performance/supercollider/sc_drum_kits.rb +29 -0
- data/lib/musicality/performance/supercollider/synthdefs/bass.rb +211 -0
- data/lib/musicality/performance/supercollider/synthdefs/claps.rb +80 -0
- data/lib/musicality/performance/supercollider/synthdefs/cymbals.rb +57 -0
- data/lib/musicality/performance/supercollider/synthdefs/hihats.rb +67 -0
- data/lib/musicality/performance/supercollider/synthdefs/kicks.rb +158 -0
- data/lib/musicality/performance/supercollider/synthdefs/mario.rb +49 -0
- data/lib/musicality/performance/supercollider/{synthdefs.rb → synthdefs/other.rb} +0 -767
- data/lib/musicality/performance/supercollider/synthdefs/pianos.rb +46 -0
- data/lib/musicality/performance/supercollider/synthdefs/snares.rb +169 -0
- data/lib/musicality/performance/supercollider/synthdefs/toms.rb +25 -0
- data/lib/musicality/performance/supercollider/synthdefs/volume.rb +20 -0
- data/lib/musicality/pitch_class.rb +1 -1
- data/lib/musicality/pitch_classes.rb +3 -5
- data/lib/musicality/version.rb +1 -1
- data/lib/musicality.rb +25 -1
- data/musicality.gemspec +3 -2
- data/spec/composition/convenience_methods_spec.rb +8 -8
- data/spec/composition/generation/random_rhythm_generator_spec.rb +5 -5
- data/spec/composition/model/pitch_class_spec.rb +22 -16
- data/spec/composition/model/pitch_classes_spec.rb +5 -5
- data/spec/composition/model/rhythm_class_spec.rb +42 -0
- data/spec/composition/model/rhythm_spec.rb +43 -0
- data/spec/composition/model/scale_class_spec.rb +26 -26
- data/spec/composition/model/scale_spec.rb +38 -38
- data/spec/composition/sequencing/drum_machine/drum_machine_spec.rb +67 -0
- data/spec/composition/sequencing/drum_machine/drum_pattern_spec.rb +58 -0
- data/spec/composition/sequencing/note_array_spec.rb +94 -0
- data/spec/composition/sequencing/note_fifo_spec.rb +183 -0
- data/spec/composition/sequencing/sequencer_spec.rb +76 -0
- data/spec/composition/util/adding_sequence_spec.rb +33 -33
- data/spec/composition/util/compound_sequence_spec.rb +6 -6
- data/spec/composition/util/note_generation_spec.rb +34 -34
- data/spec/composition/util/probabilities_spec.rb +7 -7
- data/spec/composition/util/random_sampler_spec.rb +3 -3
- data/spec/composition/util/repeating_sequence_spec.rb +28 -28
- data/spec/musicality_spec.rb +1 -1
- data/spec/notation/conversion/change_conversion_spec.rb +87 -87
- data/spec/notation/conversion/note_time_converter_spec.rb +22 -22
- data/spec/notation/conversion/score_conversion_spec.rb +1 -1
- data/spec/notation/conversion/score_converter_spec.rb +31 -31
- data/spec/notation/conversion/tempo_conversion_spec.rb +11 -11
- data/spec/notation/model/change_spec.rb +80 -80
- data/spec/notation/model/key_spec.rb +135 -69
- data/spec/notation/model/link_spec.rb +27 -27
- data/spec/notation/model/meter_spec.rb +28 -28
- data/spec/notation/model/note_spec.rb +68 -47
- data/spec/notation/model/part_spec.rb +19 -19
- data/spec/notation/model/pitch_spec.rb +69 -68
- data/spec/notation/model/score_spec.rb +50 -47
- data/spec/notation/parsing/articulation_parsing_spec.rb +4 -4
- data/spec/notation/parsing/convenience_methods_spec.rb +49 -10
- data/spec/notation/parsing/duration_nodes_spec.rb +13 -13
- data/spec/notation/parsing/duration_parsing_spec.rb +10 -10
- data/spec/notation/parsing/key_parsing_spec.rb +19 -0
- data/spec/notation/parsing/link_nodes_spec.rb +7 -7
- data/spec/notation/parsing/link_parsing_spec.rb +4 -4
- data/spec/notation/parsing/meter_parsing_spec.rb +5 -5
- data/spec/notation/parsing/note_node_spec.rb +19 -19
- data/spec/notation/parsing/note_parsing_spec.rb +4 -4
- data/spec/notation/parsing/numbers/nonnegative_float_spec.rb +8 -8
- data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +2 -2
- data/spec/notation/parsing/numbers/nonnegative_rational_spec.rb +1 -1
- data/spec/notation/parsing/numbers/positive_float_spec.rb +8 -8
- data/spec/notation/parsing/numbers/positive_integer_spec.rb +6 -6
- data/spec/notation/parsing/numbers/positive_rational_spec.rb +6 -6
- data/spec/notation/parsing/pitch_node_spec.rb +7 -7
- data/spec/notation/parsing/pitch_parsing_spec.rb +2 -2
- data/spec/notation/parsing/segment_parsing_spec.rb +3 -3
- data/spec/notation/util/function_spec.rb +15 -15
- data/spec/notation/util/transition_spec.rb +12 -12
- data/spec/notation/util/value_computer_spec.rb +35 -36
- data/spec/performance/conversion/glissando_converter_spec.rb +24 -24
- data/spec/performance/conversion/note_sequence_extractor_spec.rb +39 -39
- data/spec/performance/conversion/portamento_converter_spec.rb +23 -23
- data/spec/performance/midi/midi_util_spec.rb +41 -41
- data/spec/performance/midi/part_sequencer_spec.rb +10 -10
- data/spec/performance/midi/score_sequencer_spec.rb +15 -15
- data/spec/performance/midi/score_sequencing_spec.rb +2 -2
- data/spec/performance/util/optimization_spec.rb +9 -9
- data/spec/printing/note_engraving_spec.rb +16 -16
- data/spec/printing/score_engraver_spec.rb +5 -5
- data/spec/spec_helper.rb +5 -0
- metadata +85 -30
@@ -36,18 +36,21 @@ module PositiveFloat
|
|
36
36
|
r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
|
37
37
|
r0 = r1
|
38
38
|
r0.extend(PositiveFloat0)
|
39
|
+
r0.extend(PositiveFloat0)
|
39
40
|
else
|
40
41
|
r2 = _nt_float2
|
41
42
|
if r2
|
42
43
|
r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
|
43
44
|
r0 = r2
|
44
45
|
r0.extend(PositiveFloat0)
|
46
|
+
r0.extend(PositiveFloat0)
|
45
47
|
else
|
46
48
|
r3 = _nt_float3
|
47
49
|
if r3
|
48
50
|
r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true
|
49
51
|
r0 = r3
|
50
52
|
r0.extend(PositiveFloat0)
|
53
|
+
r0.extend(PositiveFloat0)
|
51
54
|
else
|
52
55
|
@index = i0
|
53
56
|
r0 = nil
|
@@ -436,7 +439,7 @@ module PositiveFloat
|
|
436
439
|
r1 = true
|
437
440
|
@index += match_len
|
438
441
|
else
|
439
|
-
terminal_parse_failure("e")
|
442
|
+
terminal_parse_failure('"e"')
|
440
443
|
r1 = nil
|
441
444
|
end
|
442
445
|
s0 << r1
|
@@ -3,28 +3,24 @@ module Musicality
|
|
3
3
|
# to use, include Parseable and define PARSER constant that has #parse method.
|
4
4
|
module Parseable
|
5
5
|
DEFAULT_SPLIT_PATTERN = " "
|
6
|
-
|
6
|
+
|
7
7
|
def self.included(base)
|
8
8
|
base.extend(ClassMethods)
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
module ClassMethods
|
12
|
-
def parser
|
13
|
-
self.const_get(:PARSER)
|
14
|
-
end
|
15
|
-
|
16
|
-
def convert node
|
17
|
-
node.send(self.const_get(:CONVERSION_METHOD))
|
18
|
-
end
|
19
|
-
|
20
12
|
def parse str
|
21
|
-
|
13
|
+
parser = self.const_get(:PARSER)
|
14
|
+
node = parser.parse(str)
|
15
|
+
raise ParseError, "Failed to parse #{str}" if node.nil?
|
16
|
+
|
17
|
+
node.send(self.const_get(:CONVERSION_METHOD))
|
22
18
|
end
|
23
|
-
|
19
|
+
|
24
20
|
def split_parse str, pattern=" "
|
25
|
-
str.split(pattern).map {|x|
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
21
|
+
str.split(pattern).map {|x| parse(x) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
29
25
|
|
30
|
-
end
|
26
|
+
end
|
@@ -252,6 +252,7 @@ module Pitch
|
|
252
252
|
if has_terminal?(@regexps[gr = '\A[Aa]'] ||= Regexp.new(gr), :regexp, index)
|
253
253
|
r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
254
254
|
r0.extend(LetterA0)
|
255
|
+
r0.extend(LetterA0)
|
255
256
|
@index += 1
|
256
257
|
else
|
257
258
|
terminal_parse_failure('[Aa]')
|
@@ -281,6 +282,7 @@ module Pitch
|
|
281
282
|
if has_terminal?(@regexps[gr = '\A[Bb]'] ||= Regexp.new(gr), :regexp, index)
|
282
283
|
r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
283
284
|
r0.extend(LetterB0)
|
285
|
+
r0.extend(LetterB0)
|
284
286
|
@index += 1
|
285
287
|
else
|
286
288
|
terminal_parse_failure('[Bb]')
|
@@ -310,6 +312,7 @@ module Pitch
|
|
310
312
|
if has_terminal?(@regexps[gr = '\A[Cc]'] ||= Regexp.new(gr), :regexp, index)
|
311
313
|
r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
312
314
|
r0.extend(LetterC0)
|
315
|
+
r0.extend(LetterC0)
|
313
316
|
@index += 1
|
314
317
|
else
|
315
318
|
terminal_parse_failure('[Cc]')
|
@@ -339,6 +342,7 @@ module Pitch
|
|
339
342
|
if has_terminal?(@regexps[gr = '\A[Dd]'] ||= Regexp.new(gr), :regexp, index)
|
340
343
|
r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
341
344
|
r0.extend(LetterD0)
|
345
|
+
r0.extend(LetterD0)
|
342
346
|
@index += 1
|
343
347
|
else
|
344
348
|
terminal_parse_failure('[Dd]')
|
@@ -368,6 +372,7 @@ module Pitch
|
|
368
372
|
if has_terminal?(@regexps[gr = '\A[Ee]'] ||= Regexp.new(gr), :regexp, index)
|
369
373
|
r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
370
374
|
r0.extend(LetterE0)
|
375
|
+
r0.extend(LetterE0)
|
371
376
|
@index += 1
|
372
377
|
else
|
373
378
|
terminal_parse_failure('[Ee]')
|
@@ -397,6 +402,7 @@ module Pitch
|
|
397
402
|
if has_terminal?(@regexps[gr = '\A[Ff]'] ||= Regexp.new(gr), :regexp, index)
|
398
403
|
r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
399
404
|
r0.extend(LetterF0)
|
405
|
+
r0.extend(LetterF0)
|
400
406
|
@index += 1
|
401
407
|
else
|
402
408
|
terminal_parse_failure('[Ff]')
|
@@ -426,6 +432,7 @@ module Pitch
|
|
426
432
|
if has_terminal?(@regexps[gr = '\A[Gg]'] ||= Regexp.new(gr), :regexp, index)
|
427
433
|
r0 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
428
434
|
r0.extend(LetterG0)
|
435
|
+
r0.extend(LetterG0)
|
429
436
|
@index += 1
|
430
437
|
else
|
431
438
|
terminal_parse_failure('[Gg]')
|
@@ -7,97 +7,56 @@ class NoteSequenceExtractor
|
|
7
7
|
mark_slurring
|
8
8
|
remove_bad_links
|
9
9
|
calculate_offsets
|
10
|
-
|
10
|
+
|
11
11
|
# now, ready to extract sequences!
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def extract_sequences cents_per_step = 10
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
NoteSequenceExtractor.slur_seqs(cur_seq, next_seq)
|
34
|
-
elsif p1 = map[:full_glissandos].key(p2)
|
35
|
-
cur_seq = cur_seqs.find {|x| x.elements.first.pitch == p1 }
|
36
|
-
NoteSequenceExtractor.glissando_seqs(cur_seq, next_seq)
|
37
|
-
elsif p1 = map[:full_portamentos].key(p2)
|
38
|
-
cur_seq = cur_seqs.find {|x| x.elements.first.pitch == p1 }
|
39
|
-
NoteSequenceExtractor.portamento_seqs(cur_seq, next_seq, cents_per_step)
|
15
|
+
completed_seqs = []
|
16
|
+
continuing_sequences = {}
|
17
|
+
|
18
|
+
@notes.each_with_index do |note, idx|
|
19
|
+
offset = @offsets[idx]
|
20
|
+
duration = note.duration
|
21
|
+
attack = NoteSequenceExtractor.note_attack(note.articulation)
|
22
|
+
separation = NoteSequenceExtractor.note_separation(note.articulation, @slurring_flags[idx])
|
23
|
+
|
24
|
+
next_note = (idx == (@notes.size-1)) ? Note.quarter : @notes[idx+1]
|
25
|
+
continuation_map = NoteSequenceExtractor.continuation_map(note, next_note, separation)
|
26
|
+
|
27
|
+
new_continuing_sequences = {}
|
28
|
+
|
29
|
+
note.pitches.each do |p|
|
30
|
+
seq = if continuing_sequences.has_key?(p)
|
31
|
+
continuing_sequences[p].elements += note_pitch_elements(note, p, Attack::NONE, cents_per_step)
|
32
|
+
continuing_sequences.delete(p)
|
40
33
|
else
|
41
|
-
|
34
|
+
NoteSequence.new(offset, separation, note_pitch_elements(note, p, attack, cents_per_step))
|
42
35
|
end
|
43
|
-
end
|
44
|
-
next_seqs = cur_seqs
|
45
|
-
end
|
46
|
-
complete_seqs += next_seqs
|
47
|
-
return complete_seqs
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def self.tie_seqs(cur_seq, next_seq)
|
53
|
-
cur_seq.elements.last.duration += next_seq.elements.first.duration
|
54
|
-
cur_seq.elements += next_seq.elements[1..-1]
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.slur_seqs(cur_seq, next_seq)
|
58
|
-
if next_seq.elements.first.attack == Attack::NORMAL
|
59
|
-
next_seq.elements.first.attack = Attack::NONE
|
60
|
-
end
|
61
|
-
cur_seq.separation = next_seq.separation
|
62
|
-
cur_seq.elements += next_seq.elements
|
63
|
-
end
|
64
36
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
37
|
+
if continuation_map.include?(p)
|
38
|
+
new_continuing_sequences[continuation_map[p]] = seq
|
39
|
+
else
|
40
|
+
completed_seqs.push seq
|
41
|
+
end
|
42
|
+
end
|
71
43
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
cur_seq.elements += next_seq.elements
|
77
|
-
end
|
78
|
-
|
79
|
-
def seqs_from_note(idx, cents_per_step)
|
80
|
-
map = @maps[idx]
|
81
|
-
note = @notes[idx]
|
82
|
-
attack = NoteSequenceExtractor.note_attack(note.articulation)
|
83
|
-
separation = NoteSequenceExtractor.note_separation(note.articulation, @slurring_flags[idx])
|
84
|
-
offset = @offsets[idx]
|
85
|
-
note.pitches.map do |p|
|
86
|
-
if map[:half_glissandos].has_key?(p)
|
87
|
-
NoteSequence.new(offset, separation,
|
88
|
-
GlissandoConverter.glissando_elements(
|
89
|
-
p, map[:half_glissandos][p], note.duration, attack))
|
90
|
-
elsif map[:half_portamentos].has_key?(p)
|
91
|
-
NoteSequence.new(offset, Separation::NONE,
|
92
|
-
PortamentoConverter.portamento_elements(
|
93
|
-
p, map[:half_portamentos][p], cents_per_step, note.duration, attack))
|
94
|
-
else
|
95
|
-
NoteSequence.new(offset, separation,
|
96
|
-
[NoteSequence::Element.new(note.duration, p, attack)])
|
44
|
+
if continuing_sequences.any?
|
45
|
+
require 'pry'
|
46
|
+
binding.pry
|
47
|
+
# raise "Should be no previous continuing sequences remaining"
|
97
48
|
end
|
49
|
+
continuing_sequences = new_continuing_sequences
|
98
50
|
end
|
51
|
+
|
52
|
+
raise "Should be no previous continuing sequences remaining" if continuing_sequences.any?
|
53
|
+
|
54
|
+
completed_seqs.each {|seq| seq.simplify! }
|
55
|
+
return completed_seqs
|
99
56
|
end
|
100
57
|
|
58
|
+
private
|
59
|
+
|
101
60
|
def self.note_attack articulation
|
102
61
|
case articulation
|
103
62
|
when Articulations::NORMAL then Attack::NORMAL
|
@@ -137,7 +96,7 @@ class NoteSequenceExtractor
|
|
137
96
|
def mark_slurring
|
138
97
|
@slurring_flags = []
|
139
98
|
under_slur = false
|
140
|
-
|
99
|
+
|
141
100
|
@slurring_flags = Array.new(@notes.size) do |i|
|
142
101
|
note = @notes[i]
|
143
102
|
|
@@ -162,7 +121,7 @@ class NoteSequenceExtractor
|
|
162
121
|
end
|
163
122
|
end
|
164
123
|
end
|
165
|
-
|
124
|
+
|
166
125
|
def calculate_offsets
|
167
126
|
offset = 0.to_r
|
168
127
|
@offsets = Array.new(@notes.size) do |i|
|
@@ -171,61 +130,50 @@ class NoteSequenceExtractor
|
|
171
130
|
cur_offset
|
172
131
|
end
|
173
132
|
end
|
174
|
-
|
175
|
-
def self.
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
@notes.each_index do |i|
|
187
|
-
map = { :ties => {}, :slurs => {}, :full_glissandos => {},
|
188
|
-
:full_portamentos => {}, :half_glissandos => {},
|
189
|
-
:half_portamentos => {}}
|
190
|
-
note = @notes[i]
|
191
|
-
|
192
|
-
# Create a dummy note (with no pitches) for the last note to "link" to.
|
193
|
-
# This will allow half glissandos and half portamentos from the last note
|
194
|
-
next_note = (i == (@notes.size-1)) ? Note.quarter : @notes[i+1]
|
195
|
-
|
196
|
-
no_separation = NoteSequenceExtractor.no_separation?(note.articulation, @slurring_flags[i])
|
197
|
-
|
198
|
-
linked = note.pitches & note.links.keys
|
199
|
-
linked.each do |p|
|
200
|
-
l = note.links[p]
|
201
|
-
if l.is_a?(Link::Tie)
|
202
|
-
map[:ties][p] = p
|
203
|
-
elsif l.is_a?(Link::Glissando)
|
204
|
-
if next_note.pitches.include?(l.target_pitch)
|
205
|
-
map[:full_glissandos][p] = l.target_pitch
|
206
|
-
else
|
207
|
-
map[:half_glissandos][p] = l.target_pitch
|
208
|
-
end
|
209
|
-
elsif l.is_a?(Link::Portamento)
|
210
|
-
if next_note.pitches.include?(l.target_pitch)
|
211
|
-
map[:full_portamentos][p] = l.target_pitch
|
212
|
-
else
|
213
|
-
map[:half_portamentos][p] = l.target_pitch
|
214
|
-
end
|
215
|
-
end
|
133
|
+
|
134
|
+
def self.continuation_map note, next_note, separation
|
135
|
+
map = {}
|
136
|
+
|
137
|
+
linked = note.pitches & note.links.keys
|
138
|
+
targeted = []
|
139
|
+
linked.each do |p|
|
140
|
+
l = note.links[p]
|
141
|
+
if l.is_a?(Link::Tie)
|
142
|
+
map[p] = p
|
143
|
+
elsif l.is_a?(Link::TargetedLink) && next_note.pitches.include?(l.target_pitch)
|
144
|
+
map[p] = l.target_pitch
|
216
145
|
end
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
146
|
+
end
|
147
|
+
|
148
|
+
if(separation == Separation::NONE)
|
149
|
+
unlinked = note.pitches - linked
|
150
|
+
untargeted = next_note.pitches - map.values
|
151
|
+
Optimization.linking(unlinked, untargeted).each do |pitch,tgt_pitch|
|
152
|
+
map[pitch] = tgt_pitch
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
return map
|
157
|
+
end
|
158
|
+
|
159
|
+
def note_pitch_elements note, pitch, attack, cents_per_step
|
160
|
+
duration = note.duration
|
161
|
+
link = note.links[pitch]
|
162
|
+
elements = if link && link.is_a?(Link::TargetedLink)
|
163
|
+
tgt_pitch = link.target_pitch
|
164
|
+
case link
|
165
|
+
when Link::Glissando
|
166
|
+
GlissandoConverter.glissando_elements(pitch, tgt_pitch, duration, attack)
|
167
|
+
when Link::Portamento
|
168
|
+
PortamentoConverter.portamento_elements(pitch, tgt_pitch, cents_per_step, duration, attack)
|
169
|
+
else
|
170
|
+
raise "Unexpected targeted link type"
|
225
171
|
end
|
226
|
-
|
227
|
-
|
172
|
+
else
|
173
|
+
[ NoteSequence::Element.new(note.duration, pitch, attack) ]
|
228
174
|
end
|
175
|
+
|
176
|
+
return elements
|
229
177
|
end
|
230
178
|
end
|
231
179
|
|
@@ -27,11 +27,30 @@ class NoteSequence
|
|
27
27
|
@elements = elements
|
28
28
|
end
|
29
29
|
|
30
|
+
# any consecutive elements with the same pitch and no attack will be combined
|
31
|
+
def simplify!
|
32
|
+
return if @elements.none?
|
33
|
+
|
34
|
+
prev_element = @elements[0]
|
35
|
+
idx = 1
|
36
|
+
|
37
|
+
while idx < @elements.size
|
38
|
+
element = @elements[idx]
|
39
|
+
if (element.pitch == prev_element.pitch) && (element.attack == Attack::NONE)
|
40
|
+
prev_element.duration += element.duration
|
41
|
+
@elements.delete_at(idx)
|
42
|
+
else
|
43
|
+
prev_element = element
|
44
|
+
idx += 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
30
49
|
alias start offset
|
31
|
-
|
50
|
+
|
32
51
|
def offsets
|
33
52
|
raise "contains no elements" if elements.empty?
|
34
|
-
|
53
|
+
|
35
54
|
off = @offset
|
36
55
|
elements.map do |e|
|
37
56
|
x = off
|
@@ -39,7 +58,7 @@ class NoteSequence
|
|
39
58
|
x
|
40
59
|
end
|
41
60
|
end
|
42
|
-
|
61
|
+
|
43
62
|
def stop
|
44
63
|
offsets.last + NoteSequence.adjust_duration(elements.last.duration, separation)
|
45
64
|
end
|
@@ -22,7 +22,7 @@ class Performer
|
|
22
22
|
group = create_part_group parent_group, bundles
|
23
23
|
set_start_volume volume_control_bus, bundles
|
24
24
|
add_volume_control group, aux_audio_bus, volume_control_bus, lead_time, bundles
|
25
|
-
add_volume_changes volume_control_bus, lead_time, bundles
|
25
|
+
add_volume_changes group, volume_control_bus, lead_time, bundles
|
26
26
|
add_part_notes group, aux_audio_bus, lead_time, bundles
|
27
27
|
|
28
28
|
bundles
|
@@ -51,7 +51,7 @@ class Performer
|
|
51
51
|
bundles.push vol_control.bundle_queue(lead_time / 2.0)
|
52
52
|
end
|
53
53
|
|
54
|
-
def add_volume_changes volume_control_bus, lead_time, bundles
|
54
|
+
def add_volume_changes group, volume_control_bus, lead_time, bundles
|
55
55
|
# change part volume
|
56
56
|
part.dynamic_changes.each do |offset,change|
|
57
57
|
case change
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Musicality
|
2
|
+
|
3
|
+
module DrumKits
|
4
|
+
|
5
|
+
SC_DRUM_KIT_01 = DrumKit.new(
|
6
|
+
DrumParts::BASS_DRUM => SuperCollider::SynthDefs::KICK2.settings,
|
7
|
+
DrumParts::SNARE_DRUM => SuperCollider::SynthDefs::SNARE_STEIN.settings,
|
8
|
+
DrumParts::CRASH_CYMBAL => SuperCollider::SynthDefs::CYMBALIC_MCLD.settings,
|
9
|
+
DrumParts::CLOSED_HI_HAT => SuperCollider::SynthDefs::CLOSED_HAT.settings,
|
10
|
+
DrumParts::OPEN_HI_HAT => SuperCollider::SynthDefs::OPEN_HAT.settings,
|
11
|
+
DrumParts::HI_TOM => SuperCollider::SynthDefs::TOM1.settings,
|
12
|
+
DrumParts::MED_TOM => SuperCollider::SynthDefs::TOM1.settings,
|
13
|
+
DrumParts::LOW_TOM => SuperCollider::SynthDefs::TOM1.settings,
|
14
|
+
)
|
15
|
+
|
16
|
+
SC_DRUM_KIT_02 = DrumKit.new(
|
17
|
+
DrumParts::BASS_DRUM => SuperCollider::SynthDefs::KICK_CHIRP.settings,
|
18
|
+
DrumParts::SNARE_DRUM => SuperCollider::SynthDefs::SNARE1.settings,
|
19
|
+
DrumParts::CRASH_CYMBAL => SuperCollider::SynthDefs::CYMBALIC_MCLD.settings,
|
20
|
+
DrumParts::CLOSED_HI_HAT => SuperCollider::SynthDefs::HIHAT1.settings,
|
21
|
+
DrumParts::OPEN_HI_HAT => SuperCollider::SynthDefs::HIHAT1.settings(:release => 0.6),
|
22
|
+
DrumParts::HI_TOM => SuperCollider::SynthDefs::FM_TOM.settings,
|
23
|
+
DrumParts::MED_TOM => SuperCollider::SynthDefs::FM_TOM.settings,
|
24
|
+
DrumParts::LOW_TOM => SuperCollider::SynthDefs::FM_TOM.settings,
|
25
|
+
)
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|