musicality 0.8.0 → 0.9.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/ChangeLog.md +27 -1
- data/README.md +153 -10
- data/bin/collidify +102 -0
- data/bin/lilify +57 -29
- data/bin/midify +64 -24
- data/bin/musicality +39 -0
- data/examples/composition/auto_counterpoint.rb +4 -5
- data/examples/composition/part_generator.rb +8 -2
- data/examples/composition/scale_exercise.rb +1 -1
- data/examples/notation/notes.rb +27 -0
- data/examples/notation/parts.rb +51 -0
- data/examples/notation/scores.rb +38 -0
- data/examples/notation/twinkle.rb +34 -0
- data/examples/notation/twinkle.score +33 -0
- data/lib/musicality.rb +46 -11
- data/lib/musicality/composition/dsl/score_dsl.rb +2 -2
- data/lib/musicality/composition/dsl/score_methods.rb +10 -7
- data/lib/musicality/notation/conversion/change_conversion.rb +1 -1
- data/lib/musicality/notation/conversion/note_time_converter.rb +6 -23
- data/lib/musicality/notation/conversion/score_conversion.rb +15 -15
- data/lib/musicality/notation/conversion/score_converter.rb +50 -67
- data/lib/musicality/notation/model/articulations.rb +3 -2
- data/lib/musicality/notation/model/change.rb +15 -6
- data/lib/musicality/notation/model/dynamics.rb +11 -8
- data/lib/musicality/notation/model/instrument.rb +61 -0
- data/lib/musicality/notation/model/instruments.rb +111 -0
- data/lib/musicality/notation/model/key.rb +137 -0
- data/lib/musicality/notation/model/keys.rb +37 -0
- data/lib/musicality/notation/model/link.rb +6 -19
- data/lib/musicality/notation/model/mark.rb +43 -0
- data/lib/musicality/notation/model/marks.rb +11 -0
- data/lib/musicality/notation/model/meter.rb +4 -0
- data/lib/musicality/notation/model/note.rb +42 -28
- data/lib/musicality/notation/model/part.rb +18 -5
- data/lib/musicality/notation/model/pitch.rb +13 -4
- data/lib/musicality/notation/model/score.rb +104 -66
- data/lib/musicality/notation/model/symbols.rb +16 -11
- data/lib/musicality/notation/parsing/articulation_parsing.rb +38 -38
- data/lib/musicality/notation/parsing/articulation_parsing.treetop +14 -14
- data/lib/musicality/notation/parsing/link_parsing.rb +6 -6
- data/lib/musicality/notation/parsing/link_parsing.treetop +3 -3
- data/lib/musicality/notation/parsing/mark_parsing.rb +138 -0
- data/lib/musicality/notation/parsing/mark_parsing.treetop +31 -0
- data/lib/musicality/notation/parsing/note_node.rb +19 -12
- data/lib/musicality/notation/parsing/note_parsing.rb +218 -87
- data/lib/musicality/notation/parsing/note_parsing.treetop +9 -5
- data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +7 -2
- data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.treetop +1 -1
- data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.rb +6 -4
- data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.treetop +1 -1
- data/lib/musicality/notation/util/function.rb +41 -18
- data/lib/musicality/packable.rb +156 -0
- data/lib/musicality/performance/conversion/glissando_converter.rb +2 -2
- data/lib/musicality/performance/conversion/note_sequence_extractor.rb +223 -70
- data/lib/musicality/performance/conversion/portamento_converter.rb +5 -2
- data/lib/musicality/performance/conversion/score_collator.rb +70 -64
- data/lib/musicality/performance/midi/midi_events.rb +3 -3
- data/lib/musicality/performance/midi/midi_settings.rb +127 -0
- data/lib/musicality/performance/midi/midi_util.rb +8 -2
- data/lib/musicality/performance/midi/part_sequencer.rb +19 -18
- data/lib/musicality/performance/midi/score_sequencer.rb +13 -9
- data/lib/musicality/performance/midi/score_sequencing.rb +5 -5
- data/lib/musicality/performance/model/attack.rb +8 -0
- data/lib/musicality/performance/model/duration_functions.rb +23 -0
- data/lib/musicality/performance/model/note_sequence.rb +52 -95
- data/lib/musicality/performance/model/separation.rb +10 -0
- data/lib/musicality/performance/supercollider/add_actions.rb +13 -0
- data/lib/musicality/performance/supercollider/bundle.rb +18 -0
- data/lib/musicality/performance/supercollider/conductor.rb +125 -0
- data/lib/musicality/performance/supercollider/group.rb +71 -0
- data/lib/musicality/performance/supercollider/message.rb +26 -0
- data/lib/musicality/performance/supercollider/node.rb +122 -0
- data/lib/musicality/performance/supercollider/performer.rb +123 -0
- data/lib/musicality/performance/supercollider/score_conducting.rb +17 -0
- data/lib/musicality/performance/supercollider/server.rb +8 -0
- data/lib/musicality/performance/supercollider/synth.rb +43 -0
- data/lib/musicality/performance/supercollider/synthdef.rb +57 -0
- data/lib/musicality/performance/supercollider/synthdef_settings.rb +23 -0
- data/lib/musicality/performance/supercollider/synthdefs.rb +1654 -0
- data/lib/musicality/{composition/model/pitch_class.rb → pitch_class.rb} +1 -1
- data/lib/musicality/{composition/model/pitch_classes.rb → pitch_classes.rb} +9 -9
- data/lib/musicality/printing/lilypond/clef.rb +12 -0
- data/lib/musicality/printing/lilypond/key_engraving.rb +9 -0
- data/lib/musicality/printing/lilypond/lilypond_settings.rb +105 -0
- data/lib/musicality/printing/lilypond/meter_engraving.rb +1 -1
- data/lib/musicality/printing/lilypond/note_engraving.rb +112 -30
- data/lib/musicality/printing/lilypond/part_engraver.rb +114 -3
- data/lib/musicality/printing/lilypond/pitch_class_engraving.rb +22 -0
- data/lib/musicality/printing/lilypond/pitch_engraving.rb +2 -15
- data/lib/musicality/printing/lilypond/score_engraver.rb +44 -73
- data/lib/musicality/printing/lilypond/score_engraving.rb +3 -3
- data/lib/musicality/project/create_tasks.rb +31 -0
- data/lib/musicality/project/file_cleaner.rb +19 -0
- data/lib/musicality/project/file_raker.rb +107 -0
- data/lib/musicality/project/load_config.rb +43 -0
- data/lib/musicality/project/project.rb +64 -0
- data/lib/musicality/version.rb +1 -1
- data/musicality.gemspec +3 -0
- data/spec/composition/util/random_sampler_spec.rb +1 -1
- data/spec/notation/conversion/measure_note_map_spec.rb +1 -1
- data/spec/notation/conversion/note_time_converter_spec.rb +5 -85
- data/spec/notation/conversion/score_conversion_spec.rb +6 -41
- data/spec/notation/conversion/score_converter_spec.rb +19 -137
- data/spec/notation/model/change_spec.rb +55 -0
- data/spec/notation/model/key_spec.rb +171 -0
- data/spec/notation/model/link_spec.rb +34 -5
- data/spec/notation/model/meter_spec.rb +15 -0
- data/spec/notation/model/note_spec.rb +33 -27
- data/spec/notation/model/part_spec.rb +53 -4
- data/spec/notation/model/pitch_spec.rb +15 -0
- data/spec/notation/model/score_spec.rb +64 -72
- data/spec/notation/parsing/link_nodes_spec.rb +3 -3
- data/spec/notation/parsing/link_parsing_spec.rb +6 -6
- data/spec/notation/parsing/note_node_spec.rb +34 -9
- data/spec/notation/parsing/note_parsing_spec.rb +11 -9
- data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +4 -0
- data/spec/notation/parsing/pitch_node_spec.rb +0 -1
- data/spec/notation/util/value_computer_spec.rb +2 -2
- data/spec/performance/conversion/glissando_converter_spec.rb +9 -9
- data/spec/performance/conversion/note_sequence_extractor_spec.rb +48 -53
- data/spec/performance/conversion/portamento_converter_spec.rb +11 -9
- data/spec/performance/conversion/score_collator_spec.rb +59 -63
- data/spec/performance/midi/midi_util_spec.rb +22 -8
- data/spec/performance/midi/part_sequencer_spec.rb +2 -2
- data/spec/performance/midi/score_sequencer_spec.rb +12 -10
- data/spec/performance/midi/score_sequencing_spec.rb +2 -2
- data/spec/performance/model/note_sequence_spec.rb +41 -134
- data/spec/printing/note_engraving_spec.rb +204 -0
- data/spec/printing/score_engraver_spec.rb +40 -0
- data/spec/spec_helper.rb +1 -0
- metadata +69 -23
- data/examples/notation/hip.rb +0 -32
- data/examples/notation/missed_connection.rb +0 -26
- data/examples/notation/song1.rb +0 -33
- data/examples/notation/song2.rb +0 -32
- data/lib/musicality/notation/model/links.rb +0 -11
- data/lib/musicality/notation/packing/change_packing.rb +0 -56
- data/lib/musicality/notation/packing/part_packing.rb +0 -31
- data/lib/musicality/notation/packing/score_packing.rb +0 -123
- data/lib/musicality/performance/model/note_attacks.rb +0 -19
- data/lib/musicality/performance/util/note_linker.rb +0 -28
- data/spec/notation/packing/change_packing_spec.rb +0 -304
- data/spec/notation/packing/part_packing_spec.rb +0 -66
- data/spec/notation/packing/score_packing_spec.rb +0 -255
- data/spec/performance/util/note_linker_spec.rb +0 -68
data/bin/midify
CHANGED
@@ -3,25 +3,29 @@
|
|
3
3
|
exe_name = File.basename(__FILE__)
|
4
4
|
|
5
5
|
doc = <<DOCOPT
|
6
|
-
Loads a musicality score from YAML file, and converts it to
|
6
|
+
Loads a musicality score from YAML file, and converts it to one or more MIDI
|
7
|
+
files. If no part names are given, all score parts are selected for MIDI
|
8
|
+
sequencing. Otherwise, only the given parts names will be selected. By default,
|
9
|
+
a single engraving file will be produced. If the --split flag is used, a file
|
10
|
+
will be produced for each part. If --outdir is not given, files will be put in
|
11
|
+
the same directory as the score file.
|
7
12
|
|
8
13
|
Usage:
|
9
|
-
#{exe_name}
|
14
|
+
#{exe_name} SCORE [PART]... [options]
|
10
15
|
#{exe_name} -h | --help
|
11
16
|
#{exe_name} --version
|
12
17
|
|
13
18
|
Arguments:
|
14
|
-
|
15
|
-
PART name of a part in the score
|
16
|
-
|
17
|
-
|
19
|
+
SCORE A musicality score file (may be packed as a hash) in a YAML file
|
20
|
+
PART name of a part in the score (e.g. "lhand")
|
21
|
+
|
18
22
|
Options:
|
23
|
+
--split Make separate files for each part
|
24
|
+
--outdir=OUTD Dir where files will be put (defaults to same dir as score file)
|
19
25
|
--srate=SRATE sampling rate for converting tempo-based score to time-based
|
20
26
|
score, and for sampling dynamic change values [default: 200]
|
21
27
|
-h --help Show this screen.
|
22
28
|
--version Show version.
|
23
|
-
--outfile=OUTF Name of output MIDI file
|
24
|
-
|
25
29
|
DOCOPT
|
26
30
|
|
27
31
|
require 'docopt'
|
@@ -40,16 +44,34 @@ if args["--version"]
|
|
40
44
|
exit
|
41
45
|
end
|
42
46
|
|
47
|
+
SCORE_FILE = args["SCORE"]
|
48
|
+
unless File.exists? SCORE_FILE
|
49
|
+
puts "Score file #{SCORE_FILE} does not exist. Aborting."
|
50
|
+
exit
|
51
|
+
end
|
52
|
+
|
53
|
+
if args["--outdir"]
|
54
|
+
OUTDIR = args["--outdir"]
|
55
|
+
unless Dir.exists? OUTDIR
|
56
|
+
puts "Output directory #{OUTDIR} does not exist. Aborting."
|
57
|
+
exit
|
58
|
+
end
|
59
|
+
else
|
60
|
+
OUTDIR = File.dirname(SCORE_FILE)
|
61
|
+
end
|
62
|
+
|
63
|
+
PARTS = args["PART"]
|
64
|
+
SPLIT = args["--split"]
|
65
|
+
|
43
66
|
require 'yaml'
|
44
67
|
include Musicality
|
45
68
|
|
46
|
-
|
47
|
-
|
48
|
-
print "Reading file '#{fin_name}'..."
|
69
|
+
File.open(SCORE_FILE) do |fin|
|
70
|
+
print "Reading file '#{SCORE_FILE}'..."
|
49
71
|
score = YAML.load(fin.read)
|
50
72
|
|
51
73
|
if score.is_a? Hash
|
52
|
-
score =
|
74
|
+
score = score.unpack
|
53
75
|
end
|
54
76
|
puts "done"
|
55
77
|
|
@@ -60,22 +82,40 @@ File.open(fin_name) do |fin|
|
|
60
82
|
end
|
61
83
|
|
62
84
|
if score.valid?
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
85
|
+
if PARTS.any?
|
86
|
+
selected_parts = PARTS
|
87
|
+
else
|
88
|
+
selected_parts = score.parts.keys
|
89
|
+
end
|
90
|
+
|
67
91
|
print "Making MIDI sequence..."
|
68
92
|
sequencer = ScoreSequencer.new(score)
|
69
|
-
|
93
|
+
outfiles = {}
|
94
|
+
|
95
|
+
if SPLIT
|
96
|
+
selected_parts.each do |selected_part|
|
97
|
+
outfiles[selected_part] = sequencer.make_midi_seq([selected_part])
|
98
|
+
end
|
99
|
+
else
|
100
|
+
outfiles[""] = sequencer.make_midi_seq(selected_parts)
|
101
|
+
end
|
70
102
|
puts "done"
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
103
|
+
|
104
|
+
# part_names = args["PART"]
|
105
|
+
# program_nums = args["PROGRAM"].map {|str| str.to_i }
|
106
|
+
# instr_map = Hash[[part_names,program_nums].transpose]
|
107
|
+
|
108
|
+
base_fout_name = "#{OUTDIR}/#{File.basename(SCORE_FILE,File.extname(SCORE_FILE))}"
|
109
|
+
outfiles.each do |outfile, seq|
|
110
|
+
if outfile.empty?
|
111
|
+
fout_name = "#{base_fout_name}.mid"
|
112
|
+
else
|
113
|
+
fout_name = "#{base_fout_name}_#{outfile}.mid"
|
114
|
+
end
|
115
|
+
print "Writing MIDI file '#{fout_name}'..."
|
116
|
+
File.open(fout_name, 'wb'){ |fout| seq.write(fout) }
|
117
|
+
puts "done"
|
75
118
|
end
|
76
|
-
print "Writing MIDI file '#{fout_name}'..."
|
77
|
-
File.open(fout_name, 'wb'){ |fout| seq.write(fout) }
|
78
|
-
puts "done"
|
79
119
|
else
|
80
120
|
puts "Score is not valid. See errors:"
|
81
121
|
puts score.errors.join("\n")
|
data/bin/musicality
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
exe_name = File.basename(__FILE__)
|
4
|
+
|
5
|
+
doc = <<DOCOPT
|
6
|
+
The 'new' subcommand wll create a new musicality project.
|
7
|
+
|
8
|
+
Usage:
|
9
|
+
#{exe_name} new PROJECT_DIR [options]
|
10
|
+
#{exe_name} -h | --help
|
11
|
+
#{exe_name} --version
|
12
|
+
|
13
|
+
Arguments:
|
14
|
+
PROJECT_DIR Path of an empty directory or directory to be created
|
15
|
+
|
16
|
+
Options:
|
17
|
+
-h --help Show this screen.
|
18
|
+
--version Show version.
|
19
|
+
DOCOPT
|
20
|
+
|
21
|
+
require 'docopt'
|
22
|
+
begin
|
23
|
+
args = Docopt::docopt(doc)
|
24
|
+
puts args
|
25
|
+
rescue Docopt::Exit => e
|
26
|
+
puts e.message
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'musicality'
|
31
|
+
|
32
|
+
if args["--version"]
|
33
|
+
puts "#{exe_name} in musicality v#{Musicality::VERSION}"
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
|
37
|
+
if args["new"]
|
38
|
+
Musicality::Project.new(args["PROJECT_DIR"])
|
39
|
+
end
|
@@ -5,8 +5,8 @@ include Pitches
|
|
5
5
|
bass_pitch_palette = [ C2, D2, E2, F2, G2, A2, B2, C3 ]
|
6
6
|
guitar_pitch_palette = [ C3, D3, E3, F3, G3, A3, B3, C4 ]
|
7
7
|
|
8
|
-
bass = Part.new(Dynamics::MF)
|
9
|
-
guitar = Part.new(Dynamics::MF)
|
8
|
+
bass = Part.new(Dynamics::MF, settings: [MidiSettings::ELECTRIC_BASS_FINGER])
|
9
|
+
guitar = Part.new(Dynamics::MF, settings: [MidiSettings::ELECTRIC_GUITAR_JAZZ])
|
10
10
|
|
11
11
|
def random_melody rhythm, pitch_palette
|
12
12
|
pitches = pitch_palette.sample(rand(2..pitch_palette.size))
|
@@ -43,11 +43,10 @@ end
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
score = Score::
|
46
|
+
score = Score::Tempo.new(Meters::FOUR_FOUR, 120,
|
47
47
|
parts: { "bass" => bass, "guitar" => guitar },
|
48
48
|
program: [ 0...([bass.duration,guitar.duration].min) ]
|
49
49
|
)
|
50
50
|
|
51
|
-
|
52
|
-
seq = ScoreSequencer.new(score.to_timed(200)).make_midi_seq(instr_map)
|
51
|
+
seq = ScoreSequencer.new(score.to_timed(200)).make_midi_seq
|
53
52
|
File.open("./auto_counterpoint.mid", 'wb'){ |fout| seq.write(fout) }
|
@@ -16,8 +16,10 @@ end
|
|
16
16
|
|
17
17
|
rhythm_seq2 = RepeatingSequence.new([3/8.to_r]*4)
|
18
18
|
|
19
|
-
score = Score::
|
19
|
+
score = Score::Tempo.new(SIX_EIGHT,90) do |s|
|
20
20
|
s.parts["main"] = Part.new(Dynamics::MF) do |p|
|
21
|
+
p.settings.push MidiSettings::LEAD_SAWTOOTH
|
22
|
+
|
21
23
|
rhythm_seq = RepeatingSequence.new(([1/8.to_r]*3)*3 + [1/4.to_r,1/8.to_r])
|
22
24
|
selector = RepeatingSequence.new([4,2,0])
|
23
25
|
rhythm = rhythm_seq.take(pitch_seqs.size * rhythm_seq.pattern_size).to_a
|
@@ -27,6 +29,8 @@ score = Score::Measured.new(SIX_EIGHT,90) do |s|
|
|
27
29
|
end
|
28
30
|
|
29
31
|
s.parts["bass"] = Part.new(Dynamics::MP) do |p|
|
32
|
+
p.settings.push MidiSettings::LEAD_SQUARE
|
33
|
+
|
30
34
|
rhythm_seq = RepeatingSequence.new([3/8.to_r]*4)
|
31
35
|
selector = RepeatingSequence.new([-7])
|
32
36
|
rhythm = rhythm_seq.take(pitch_seqs.size * rhythm_seq.pattern_size).to_a
|
@@ -36,6 +40,8 @@ score = Score::Measured.new(SIX_EIGHT,90) do |s|
|
|
36
40
|
end
|
37
41
|
|
38
42
|
s.parts["pluck"] = Part.new(Dynamics::MP) do |p|
|
43
|
+
p.settings.push MidiSettings::ORCHESTRAL_HARP
|
44
|
+
|
39
45
|
rhythm_seq = RepeatingSequence.new(([1/8.to_r]*3)*4)
|
40
46
|
selector = RepeatingSequence.new([0,2,4])
|
41
47
|
rhythm = rhythm_seq.take(pitch_seqs.size * rhythm_seq.pattern_size).to_a
|
@@ -47,5 +53,5 @@ score = Score::Measured.new(SIX_EIGHT,90) do |s|
|
|
47
53
|
s.program = [0...s.measures_long]*2
|
48
54
|
end
|
49
55
|
|
50
|
-
seq = ScoreSequencer.new(score.to_timed(200)).make_midi_seq
|
56
|
+
seq = ScoreSequencer.new(score.to_timed(200)).make_midi_seq
|
51
57
|
File.open("./part_generator.mid", 'wb'){ |fout| seq.write(fout) }
|
@@ -26,7 +26,7 @@ def scale_exercise scale_class, base_pitch, rhythm
|
|
26
26
|
return notes
|
27
27
|
end
|
28
28
|
|
29
|
-
score = Score::
|
29
|
+
score = Score::Tempo.new(FOUR_FOUR,120) do |s|
|
30
30
|
s.parts["scale"] = Part.new(Dynamics::MP) do |p|
|
31
31
|
Heptatonic::Prima::MODES.each do |mode_n,scale_class|
|
32
32
|
[[1/4.to_r,1/4.to_r,1/2.to_r]].each do |rhythm|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'musicality'
|
2
|
+
include Musicality
|
3
|
+
include Pitches
|
4
|
+
|
5
|
+
#
|
6
|
+
# convenience methods for common durations
|
7
|
+
#
|
8
|
+
single = Note.quarter(Ab4)
|
9
|
+
rest = Note.quarter
|
10
|
+
chord = Note.whole([C3,E3,G3])
|
11
|
+
|
12
|
+
#
|
13
|
+
# specific duration + articulation
|
14
|
+
#
|
15
|
+
note = Note.new(Rational(7,8), Bb3, articulation: Articulations::STACCATO)
|
16
|
+
puts note.to_s # => "7/8Bb3."
|
17
|
+
|
18
|
+
#
|
19
|
+
# magic!
|
20
|
+
#
|
21
|
+
puts note.transpose(2).to_s # => "7/8C4."
|
22
|
+
|
23
|
+
#
|
24
|
+
# create notes from a compact syntax
|
25
|
+
#
|
26
|
+
notes = "/4C3 /4D3 /2E3,G3,B3".to_notes
|
27
|
+
puts notes.join(" ") # => "/4C3 /4D3 /2E3,G3,B3"
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'musicality'
|
2
|
+
include Musicality
|
3
|
+
include Pitches
|
4
|
+
include Dynamics
|
5
|
+
|
6
|
+
|
7
|
+
#
|
8
|
+
# Building up a part piece-by-piece
|
9
|
+
#
|
10
|
+
|
11
|
+
# an empty part with no notes and default dynamic (loudness)
|
12
|
+
p = Part.new(MP)
|
13
|
+
|
14
|
+
# add some notes
|
15
|
+
p.notes += "/4C3 /4D3 /2E3,G3,B3".to_notes * 2
|
16
|
+
|
17
|
+
# add dynamic changes
|
18
|
+
p.dynamic_changes[0.5] = Change::Gradual.linear(FF, 0.5)
|
19
|
+
p.dynamic_changes[1] = Change::Immediate.new(MP)
|
20
|
+
|
21
|
+
# Add custom settings for LilyPond engraving
|
22
|
+
p.settings.push LilypondSettings::CLARINET
|
23
|
+
|
24
|
+
# Add custom settings for MIDI conversion
|
25
|
+
p.settings.push MidiSettings::CLARINET
|
26
|
+
|
27
|
+
|
28
|
+
#
|
29
|
+
# Using block initialization to do the same
|
30
|
+
#
|
31
|
+
|
32
|
+
p = Part.new(MP) do |p|
|
33
|
+
p.notes += "/4C3 /4D3 /2E3,G3,B3".to_notes * 2
|
34
|
+
p.dynamic_changes[0.5] = Change::Gradual.linear(FF, 0.5)
|
35
|
+
p.dynamic_changes[1] = Change::Immediate.new(MP)
|
36
|
+
p.settings.push LilypondSettings::CLARINET
|
37
|
+
p.settings.push MidiSettings::CLARINET
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
#
|
42
|
+
# Passing all the pieces as keyword parameters
|
43
|
+
#
|
44
|
+
p = Part.new(MP,
|
45
|
+
notes: "/4C3 /4D3 /2E3,G3,B3".to_notes * 2,
|
46
|
+
dynamic_changes: {
|
47
|
+
0.5 => Change::Gradual.linear(FF, 0.5),
|
48
|
+
1.0 => Change::Immediate.new(MP)
|
49
|
+
},
|
50
|
+
settings: [ LilypondSettings::CLARINET, MidiSettings::CLARINET ]
|
51
|
+
)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'musicality'
|
2
|
+
include Musicality
|
3
|
+
include Pitches
|
4
|
+
include Dynamics
|
5
|
+
include Keys
|
6
|
+
include Meters
|
7
|
+
|
8
|
+
#
|
9
|
+
# Basics of creating a score from scratch
|
10
|
+
#
|
11
|
+
|
12
|
+
# minimum score, with no parts
|
13
|
+
s = Score::Tempo.new(FOUR_FOUR, 120)
|
14
|
+
|
15
|
+
# add a part
|
16
|
+
s.parts["piano"] = Part.new(MP) do |p|
|
17
|
+
p.notes = q(C4,C4,G4,G4,A4,A4) + h(G4) +
|
18
|
+
q(F4,F4,E4,E4,D4,D4) + h(C4)
|
19
|
+
end
|
20
|
+
|
21
|
+
# add a key and tempo change
|
22
|
+
s.key_changes[s.measures_long] = Change::Immediate.new(D_MAJOR)
|
23
|
+
s.tempo_changes[s.measures_long] = Change::Immediate.new(140)
|
24
|
+
s.parts["piano"].notes += transpose(s.parts["piano"].notes, 2)
|
25
|
+
|
26
|
+
|
27
|
+
#
|
28
|
+
# Score conversion
|
29
|
+
#
|
30
|
+
|
31
|
+
# Convert tempo-based score to time-based
|
32
|
+
s.to_timed(200) # requires tempo sampling rate
|
33
|
+
|
34
|
+
# Engrave the score using LilyPond
|
35
|
+
puts s.to_lilypond
|
36
|
+
|
37
|
+
# Convert the score to a MIDI file
|
38
|
+
s.to_midi_seq(200)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'musicality'
|
2
|
+
include Musicality
|
3
|
+
include Meters
|
4
|
+
include Dynamics
|
5
|
+
include Pitches
|
6
|
+
|
7
|
+
score = Score::Tempo.new(FOUR_FOUR, 120, title: "Twinkle, Twinkle, Little Star") do |s|
|
8
|
+
s.parts["rhand"] = Part.new(MF) do |p|
|
9
|
+
a_notes = q(C4,C4,G4,G4,A4,A4) + h(G4) +
|
10
|
+
q(F4,F4,E4,E4,D4,D4) + h(C4)
|
11
|
+
b_notes = q(G4,G4,F4,F4,E4,E4) + h(D4)
|
12
|
+
p.notes += a_notes + b_notes
|
13
|
+
end
|
14
|
+
|
15
|
+
s.parts["lhand"] = Part.new(MF) do |p|
|
16
|
+
Cmaj = [C3,E3,G3]
|
17
|
+
Fmaj = [F2,A2,C3]
|
18
|
+
Gmaj = [G2,B2,D3]
|
19
|
+
|
20
|
+
a_chords = h(Cmaj,Cmaj,Fmaj,Cmaj) +
|
21
|
+
h(Fmaj,Cmaj,Gmaj,Cmaj)
|
22
|
+
b_chords = h(Cmaj,Fmaj,Cmaj,Gmaj)
|
23
|
+
p.notes += a_chords + b_chords
|
24
|
+
end
|
25
|
+
|
26
|
+
s.program.push 0...4
|
27
|
+
s.program.push 4...6
|
28
|
+
s.program.push 4...6
|
29
|
+
s.program.push 0...4
|
30
|
+
end
|
31
|
+
|
32
|
+
File.open('twinkle.ly','w'){|f| f.write(score.to_lilypond) }
|
33
|
+
File.open('twinkle.mid','wb'){|f| score.to_midi_seq(200).write(f) }
|
34
|
+
score.to_osc(200,'twinkle')
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# run me with the following ruby code:
|
2
|
+
# require 'musicality'
|
3
|
+
# include Musicality
|
4
|
+
# include Pitches
|
5
|
+
# ScoreDSL.load('twinkle.score')
|
6
|
+
|
7
|
+
tempo_score Meters::FOUR_FOUR, 120 do
|
8
|
+
title "Twinkle, Twinkle, Little Star"
|
9
|
+
|
10
|
+
Cmaj = [C3,E3,G3]
|
11
|
+
Fmaj = [F2,A2,C3]
|
12
|
+
Gmaj = [G2,B2,D3]
|
13
|
+
section "A" do
|
14
|
+
notes(
|
15
|
+
"rhand" => q(C4,C4,G4,G4,A4,A4) + h(G4) +
|
16
|
+
q(F4,F4,E4,E4,D4,D4) + h(C4),
|
17
|
+
"lhand" => h(Cmaj,Cmaj,Fmaj,Cmaj) +
|
18
|
+
h(Fmaj,Cmaj,Gmaj,Cmaj)
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
section "B" do
|
23
|
+
notes(
|
24
|
+
"rhand" => q(G4,G4,F4,F4,E4,E4) + h(D4),
|
25
|
+
"lhand" => h(Cmaj,Fmaj,Cmaj,Gmaj)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
repeat "B"
|
29
|
+
repeat "A"
|
30
|
+
end
|
31
|
+
|
32
|
+
File.open('twinkle.ly','w'){|f| f.write(score.to_lilypond) }
|
33
|
+
File.open('twinkle.mid','wb'){|f| score.to_midi_seq(200).write(f) }
|
data/lib/musicality.rb
CHANGED
@@ -1,24 +1,31 @@
|
|
1
1
|
# basic core classes
|
2
2
|
require 'musicality/version'
|
3
|
+
require 'musicality/packable'
|
3
4
|
require 'musicality/validatable'
|
4
5
|
require 'musicality/errors'
|
5
6
|
|
7
|
+
require 'musicality/pitch_class'
|
8
|
+
require 'musicality/pitch_classes'
|
9
|
+
|
6
10
|
#
|
7
11
|
# Notation
|
8
12
|
#
|
9
13
|
|
10
14
|
require 'musicality/notation/model/pitch'
|
11
15
|
require 'musicality/notation/model/pitches'
|
12
|
-
require 'musicality/notation/model/links'
|
13
16
|
require 'musicality/notation/model/articulations'
|
14
|
-
require 'musicality/notation/model/symbols'
|
15
17
|
require 'musicality/notation/model/link'
|
18
|
+
require 'musicality/notation/model/mark'
|
19
|
+
require 'musicality/notation/model/marks'
|
20
|
+
require 'musicality/notation/model/symbols'
|
16
21
|
require 'musicality/notation/model/note'
|
17
22
|
require 'musicality/notation/model/dynamics'
|
18
23
|
require 'musicality/notation/model/change'
|
19
24
|
require 'musicality/notation/model/part'
|
20
25
|
require 'musicality/notation/model/meter'
|
21
26
|
require 'musicality/notation/model/meters'
|
27
|
+
require 'musicality/notation/model/key'
|
28
|
+
require 'musicality/notation/model/keys'
|
22
29
|
require 'musicality/notation/model/score'
|
23
30
|
|
24
31
|
require 'treetop'
|
@@ -35,6 +42,7 @@ require 'musicality/notation/parsing/duration_nodes'
|
|
35
42
|
require 'musicality/notation/parsing/articulation_parsing'
|
36
43
|
require 'musicality/notation/parsing/link_parsing'
|
37
44
|
require 'musicality/notation/parsing/link_nodes'
|
45
|
+
require 'musicality/notation/parsing/mark_parsing'
|
38
46
|
require 'musicality/notation/parsing/note_parsing'
|
39
47
|
require 'musicality/notation/parsing/note_node'
|
40
48
|
require 'musicality/notation/parsing/meter_parsing'
|
@@ -42,10 +50,6 @@ require 'musicality/notation/parsing/segment_parsing'
|
|
42
50
|
require 'musicality/notation/parsing/parseable'
|
43
51
|
require 'musicality/notation/parsing/convenience_methods'
|
44
52
|
|
45
|
-
require 'musicality/notation/packing/change_packing'
|
46
|
-
require 'musicality/notation/packing/part_packing'
|
47
|
-
require 'musicality/notation/packing/score_packing'
|
48
|
-
|
49
53
|
require 'musicality/notation/util/interpolation'
|
50
54
|
require 'musicality/notation/util/function'
|
51
55
|
require 'musicality/notation/util/piecewise_function'
|
@@ -71,8 +75,6 @@ require 'musicality/composition/util/random_sampler'
|
|
71
75
|
require 'musicality/composition/util/probabilities'
|
72
76
|
require 'musicality/composition/util/note_generation'
|
73
77
|
|
74
|
-
require 'musicality/composition/model/pitch_class'
|
75
|
-
require 'musicality/composition/model/pitch_classes'
|
76
78
|
require 'musicality/composition/model/scale'
|
77
79
|
require 'musicality/composition/model/scale_class'
|
78
80
|
require 'musicality/composition/model/scale_classes'
|
@@ -89,11 +91,12 @@ require 'musicality/composition/convenience_methods'
|
|
89
91
|
# Performance
|
90
92
|
#
|
91
93
|
|
92
|
-
require 'musicality/performance/model/
|
94
|
+
require 'musicality/performance/model/attack'
|
95
|
+
require 'musicality/performance/model/separation'
|
96
|
+
require 'musicality/performance/model/duration_functions'
|
93
97
|
require 'musicality/performance/model/note_sequence'
|
94
98
|
|
95
99
|
require 'musicality/performance/util/optimization'
|
96
|
-
require 'musicality/performance/util/note_linker'
|
97
100
|
|
98
101
|
require 'musicality/performance/conversion/glissando_converter'
|
99
102
|
require 'musicality/performance/conversion/portamento_converter'
|
@@ -103,17 +106,49 @@ require 'musicality/performance/conversion/score_collator'
|
|
103
106
|
require 'midilib'
|
104
107
|
require 'musicality/performance/midi/midi_util'
|
105
108
|
require 'musicality/performance/midi/midi_events'
|
109
|
+
require 'musicality/performance/midi/midi_settings'
|
106
110
|
require 'musicality/performance/midi/part_sequencer'
|
107
111
|
require 'musicality/performance/midi/score_sequencer'
|
108
112
|
require 'musicality/performance/midi/score_sequencing'
|
109
113
|
|
114
|
+
require 'musicality/performance/supercollider/message'
|
115
|
+
require 'musicality/performance/supercollider/bundle'
|
116
|
+
require 'musicality/performance/supercollider/server'
|
117
|
+
require 'musicality/performance/supercollider/add_actions'
|
118
|
+
require 'musicality/performance/supercollider/node'
|
119
|
+
require 'musicality/performance/supercollider/synth'
|
120
|
+
require 'musicality/performance/supercollider/group'
|
121
|
+
require 'musicality/performance/supercollider/synthdef'
|
122
|
+
require 'musicality/performance/supercollider/synthdefs'
|
123
|
+
require 'musicality/performance/supercollider/performer'
|
124
|
+
require 'musicality/performance/supercollider/conductor'
|
125
|
+
require 'musicality/performance/supercollider/score_conducting'
|
126
|
+
|
110
127
|
#
|
111
128
|
# Printing
|
112
129
|
#
|
113
130
|
|
114
131
|
require 'musicality/printing/lilypond/errors'
|
132
|
+
require 'musicality/printing/lilypond/pitch_class_engraving'
|
115
133
|
require 'musicality/printing/lilypond/pitch_engraving'
|
116
134
|
require 'musicality/printing/lilypond/note_engraving'
|
117
135
|
require 'musicality/printing/lilypond/meter_engraving'
|
136
|
+
require 'musicality/printing/lilypond/key_engraving'
|
137
|
+
require 'musicality/printing/lilypond/clef'
|
138
|
+
require 'musicality/printing/lilypond/lilypond_settings'
|
139
|
+
require 'musicality/printing/lilypond/part_engraver'
|
118
140
|
require 'musicality/printing/lilypond/score_engraver'
|
119
|
-
require 'musicality/printing/lilypond/score_engraving'
|
141
|
+
require 'musicality/printing/lilypond/score_engraving'
|
142
|
+
|
143
|
+
#
|
144
|
+
# Project
|
145
|
+
#
|
146
|
+
|
147
|
+
require 'rake'
|
148
|
+
require 'yaml'
|
149
|
+
require 'rake/tasklib'
|
150
|
+
require 'musicality/project/file_raker'
|
151
|
+
require 'musicality/project/file_cleaner'
|
152
|
+
require 'musicality/project/project'
|
153
|
+
require 'musicality/project/load_config'
|
154
|
+
require 'musicality/project/create_tasks'
|