music-performance 0.2.1 → 0.3.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 +4 -4
- data/lib/music-performance/arrangement/midi/midi_events.rb +30 -3
- data/lib/music-performance/arrangement/midi/part_sequencer.rb +18 -14
- data/lib/music-performance/conversion/score_collator.rb +0 -2
- data/lib/music-performance/version.rb +1 -1
- data/spec/conversion/score_collator_spec.rb +18 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0aee433423e514dcf3e7c43cf3e41bedb419773
|
4
|
+
data.tar.gz: 935623cdf53a375dbbe7931f4bbc06857144a3eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 377e4df3573ca96e8b9307f87d8a4dc1cb5aef5bc709c841137649e7c973764b050ac3c2b0777188898c3d663305ec45cf31685a6839a0190f10ead2e9e495b4
|
7
|
+
data.tar.gz: 136086c85244cbcc75168c7de393ceec0df3d1ec6266aff023b8b21876d37c9f07dbacd2cb0f0735319eb1a232139fcc5bbbe020c0156d53d44de9b409971cf0
|
@@ -1,9 +1,36 @@
|
|
1
1
|
module Music
|
2
2
|
module Performance
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
class MidiEvent
|
5
|
+
def <=> other
|
6
|
+
ORDERING[self] <=> ORDERING[other]
|
7
|
+
end
|
8
|
+
|
9
|
+
class NoteOn < MidiEvent
|
10
|
+
attr_reader :notenum, :accented
|
11
|
+
def initialize notenum, accented
|
12
|
+
@notenum, @accented = notenum, accented
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class NoteOff < MidiEvent
|
17
|
+
attr_reader :notenum
|
18
|
+
def initialize notenum
|
19
|
+
@notenum = notenum
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Expression < MidiEvent
|
24
|
+
attr_reader :volume
|
25
|
+
def initialize volume
|
26
|
+
@volume = volume
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
ORDERING = {
|
31
|
+
NoteOff => 0, Expression => 1, NoteOn => 2
|
32
|
+
}
|
33
|
+
end
|
7
34
|
|
8
35
|
end
|
9
36
|
end
|
@@ -3,6 +3,8 @@ module Performance
|
|
3
3
|
|
4
4
|
class PartSequencer
|
5
5
|
def initialize part, dynamics_sample_rate: 50, cents_per_step: 10
|
6
|
+
replace_portamento_with_glissando(part.notes)
|
7
|
+
|
6
8
|
extractor = NoteSequenceExtractor.new(part.notes, cents_per_step)
|
7
9
|
note_sequences = extractor.extract_sequences
|
8
10
|
note_events = gather_note_events(note_sequences)
|
@@ -10,7 +12,7 @@ class PartSequencer
|
|
10
12
|
dynamic_events = gather_dynamic_events(part.start_dynamic,
|
11
13
|
part.dynamic_changes, dynamics_sample_rate)
|
12
14
|
|
13
|
-
@events = (note_events + dynamic_events).
|
15
|
+
@events = (note_events + dynamic_events).sort
|
14
16
|
end
|
15
17
|
|
16
18
|
def make_midi_track midi_sequence, part_name, channel, ppqn
|
@@ -25,12 +27,12 @@ class PartSequencer
|
|
25
27
|
end
|
26
28
|
|
27
29
|
track.events << case event
|
28
|
-
when
|
30
|
+
when MidiEvent::NoteOn
|
29
31
|
vel = MidiUtil.note_velocity(event.accented)
|
30
32
|
MIDI::NoteOn.new(channel, event.notenum, vel, delta)
|
31
|
-
when
|
33
|
+
when MidiEvent::NoteOff
|
32
34
|
MIDI::NoteOff.new(channel, event.notenum, 127, delta)
|
33
|
-
when
|
35
|
+
when MidiEvent::Expression
|
34
36
|
MIDI::Controller.new(channel, MIDI::CC_EXPRESSION_CONTROLLER, event.volume, delta)
|
35
37
|
end
|
36
38
|
|
@@ -41,13 +43,15 @@ class PartSequencer
|
|
41
43
|
|
42
44
|
private
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
def replace_portamento_with_glissando notes
|
47
|
+
notes.each do |note|
|
48
|
+
note.links.each do |pitch,link|
|
49
|
+
if link.is_a? Music::Transcription::Link::Portamento
|
50
|
+
note.links[pitch] = Music::Transcription::Link::Glissando.new(link.target_pitch)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
51
55
|
|
52
56
|
def gather_note_events note_sequences
|
53
57
|
note_events = []
|
@@ -65,8 +69,8 @@ class PartSequencer
|
|
65
69
|
on_at = offset
|
66
70
|
off_at = (i < (pitches.size - 1)) ? pitches[i+1][0] : note_seq.stop
|
67
71
|
|
68
|
-
note_events.push [on_at,
|
69
|
-
note_events.push [off_at,
|
72
|
+
note_events.push [on_at, MidiEvent::NoteOn.new(note_num, accented)]
|
73
|
+
note_events.push [off_at, MidiEvent::NoteOff.new(note_num)]
|
70
74
|
end
|
71
75
|
end
|
72
76
|
return note_events
|
@@ -91,7 +95,7 @@ class PartSequencer
|
|
91
95
|
unless sample == prev
|
92
96
|
offset = Rational(i,sample_rate)
|
93
97
|
volume = MidiUtil.dynamic_to_volume(sample)
|
94
|
-
dynamic_events.push [offset,
|
98
|
+
dynamic_events.push [offset, MidiEvent::Expression.new(volume)]
|
95
99
|
end
|
96
100
|
prev = sample
|
97
101
|
end
|
@@ -82,6 +82,24 @@ describe ScoreCollator do
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
85
|
+
|
86
|
+
it 'should preserve links' do
|
87
|
+
notes = Parsing::notes("1Db4~Bb4")
|
88
|
+
score = Score.new(
|
89
|
+
FOUR_FOUR,120,
|
90
|
+
parts: { "lead" => Part.new(Dynamics::MP, notes: notes) },
|
91
|
+
program: Program.new([0..1,0..1]),
|
92
|
+
)
|
93
|
+
collator = ScoreCollator.new(score)
|
94
|
+
parts = collator.collate_parts
|
95
|
+
|
96
|
+
notes = parts["lead"].notes
|
97
|
+
notes.size.should eq 2
|
98
|
+
notes.each do |note|
|
99
|
+
note.links.should have_key(Db4)
|
100
|
+
note.links[Db4].should be_a Link::Glissando
|
101
|
+
end
|
102
|
+
end
|
85
103
|
end
|
86
104
|
|
87
105
|
describe '#collate_tempo_changes' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: music-performance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Tunnell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|