musicality 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +27 -1
  3. data/README.md +153 -10
  4. data/bin/collidify +102 -0
  5. data/bin/lilify +57 -29
  6. data/bin/midify +64 -24
  7. data/bin/musicality +39 -0
  8. data/examples/composition/auto_counterpoint.rb +4 -5
  9. data/examples/composition/part_generator.rb +8 -2
  10. data/examples/composition/scale_exercise.rb +1 -1
  11. data/examples/notation/notes.rb +27 -0
  12. data/examples/notation/parts.rb +51 -0
  13. data/examples/notation/scores.rb +38 -0
  14. data/examples/notation/twinkle.rb +34 -0
  15. data/examples/notation/twinkle.score +33 -0
  16. data/lib/musicality.rb +46 -11
  17. data/lib/musicality/composition/dsl/score_dsl.rb +2 -2
  18. data/lib/musicality/composition/dsl/score_methods.rb +10 -7
  19. data/lib/musicality/notation/conversion/change_conversion.rb +1 -1
  20. data/lib/musicality/notation/conversion/note_time_converter.rb +6 -23
  21. data/lib/musicality/notation/conversion/score_conversion.rb +15 -15
  22. data/lib/musicality/notation/conversion/score_converter.rb +50 -67
  23. data/lib/musicality/notation/model/articulations.rb +3 -2
  24. data/lib/musicality/notation/model/change.rb +15 -6
  25. data/lib/musicality/notation/model/dynamics.rb +11 -8
  26. data/lib/musicality/notation/model/instrument.rb +61 -0
  27. data/lib/musicality/notation/model/instruments.rb +111 -0
  28. data/lib/musicality/notation/model/key.rb +137 -0
  29. data/lib/musicality/notation/model/keys.rb +37 -0
  30. data/lib/musicality/notation/model/link.rb +6 -19
  31. data/lib/musicality/notation/model/mark.rb +43 -0
  32. data/lib/musicality/notation/model/marks.rb +11 -0
  33. data/lib/musicality/notation/model/meter.rb +4 -0
  34. data/lib/musicality/notation/model/note.rb +42 -28
  35. data/lib/musicality/notation/model/part.rb +18 -5
  36. data/lib/musicality/notation/model/pitch.rb +13 -4
  37. data/lib/musicality/notation/model/score.rb +104 -66
  38. data/lib/musicality/notation/model/symbols.rb +16 -11
  39. data/lib/musicality/notation/parsing/articulation_parsing.rb +38 -38
  40. data/lib/musicality/notation/parsing/articulation_parsing.treetop +14 -14
  41. data/lib/musicality/notation/parsing/link_parsing.rb +6 -6
  42. data/lib/musicality/notation/parsing/link_parsing.treetop +3 -3
  43. data/lib/musicality/notation/parsing/mark_parsing.rb +138 -0
  44. data/lib/musicality/notation/parsing/mark_parsing.treetop +31 -0
  45. data/lib/musicality/notation/parsing/note_node.rb +19 -12
  46. data/lib/musicality/notation/parsing/note_parsing.rb +218 -87
  47. data/lib/musicality/notation/parsing/note_parsing.treetop +9 -5
  48. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +7 -2
  49. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.treetop +1 -1
  50. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.rb +6 -4
  51. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.treetop +1 -1
  52. data/lib/musicality/notation/util/function.rb +41 -18
  53. data/lib/musicality/packable.rb +156 -0
  54. data/lib/musicality/performance/conversion/glissando_converter.rb +2 -2
  55. data/lib/musicality/performance/conversion/note_sequence_extractor.rb +223 -70
  56. data/lib/musicality/performance/conversion/portamento_converter.rb +5 -2
  57. data/lib/musicality/performance/conversion/score_collator.rb +70 -64
  58. data/lib/musicality/performance/midi/midi_events.rb +3 -3
  59. data/lib/musicality/performance/midi/midi_settings.rb +127 -0
  60. data/lib/musicality/performance/midi/midi_util.rb +8 -2
  61. data/lib/musicality/performance/midi/part_sequencer.rb +19 -18
  62. data/lib/musicality/performance/midi/score_sequencer.rb +13 -9
  63. data/lib/musicality/performance/midi/score_sequencing.rb +5 -5
  64. data/lib/musicality/performance/model/attack.rb +8 -0
  65. data/lib/musicality/performance/model/duration_functions.rb +23 -0
  66. data/lib/musicality/performance/model/note_sequence.rb +52 -95
  67. data/lib/musicality/performance/model/separation.rb +10 -0
  68. data/lib/musicality/performance/supercollider/add_actions.rb +13 -0
  69. data/lib/musicality/performance/supercollider/bundle.rb +18 -0
  70. data/lib/musicality/performance/supercollider/conductor.rb +125 -0
  71. data/lib/musicality/performance/supercollider/group.rb +71 -0
  72. data/lib/musicality/performance/supercollider/message.rb +26 -0
  73. data/lib/musicality/performance/supercollider/node.rb +122 -0
  74. data/lib/musicality/performance/supercollider/performer.rb +123 -0
  75. data/lib/musicality/performance/supercollider/score_conducting.rb +17 -0
  76. data/lib/musicality/performance/supercollider/server.rb +8 -0
  77. data/lib/musicality/performance/supercollider/synth.rb +43 -0
  78. data/lib/musicality/performance/supercollider/synthdef.rb +57 -0
  79. data/lib/musicality/performance/supercollider/synthdef_settings.rb +23 -0
  80. data/lib/musicality/performance/supercollider/synthdefs.rb +1654 -0
  81. data/lib/musicality/{composition/model/pitch_class.rb → pitch_class.rb} +1 -1
  82. data/lib/musicality/{composition/model/pitch_classes.rb → pitch_classes.rb} +9 -9
  83. data/lib/musicality/printing/lilypond/clef.rb +12 -0
  84. data/lib/musicality/printing/lilypond/key_engraving.rb +9 -0
  85. data/lib/musicality/printing/lilypond/lilypond_settings.rb +105 -0
  86. data/lib/musicality/printing/lilypond/meter_engraving.rb +1 -1
  87. data/lib/musicality/printing/lilypond/note_engraving.rb +112 -30
  88. data/lib/musicality/printing/lilypond/part_engraver.rb +114 -3
  89. data/lib/musicality/printing/lilypond/pitch_class_engraving.rb +22 -0
  90. data/lib/musicality/printing/lilypond/pitch_engraving.rb +2 -15
  91. data/lib/musicality/printing/lilypond/score_engraver.rb +44 -73
  92. data/lib/musicality/printing/lilypond/score_engraving.rb +3 -3
  93. data/lib/musicality/project/create_tasks.rb +31 -0
  94. data/lib/musicality/project/file_cleaner.rb +19 -0
  95. data/lib/musicality/project/file_raker.rb +107 -0
  96. data/lib/musicality/project/load_config.rb +43 -0
  97. data/lib/musicality/project/project.rb +64 -0
  98. data/lib/musicality/version.rb +1 -1
  99. data/musicality.gemspec +3 -0
  100. data/spec/composition/util/random_sampler_spec.rb +1 -1
  101. data/spec/notation/conversion/measure_note_map_spec.rb +1 -1
  102. data/spec/notation/conversion/note_time_converter_spec.rb +5 -85
  103. data/spec/notation/conversion/score_conversion_spec.rb +6 -41
  104. data/spec/notation/conversion/score_converter_spec.rb +19 -137
  105. data/spec/notation/model/change_spec.rb +55 -0
  106. data/spec/notation/model/key_spec.rb +171 -0
  107. data/spec/notation/model/link_spec.rb +34 -5
  108. data/spec/notation/model/meter_spec.rb +15 -0
  109. data/spec/notation/model/note_spec.rb +33 -27
  110. data/spec/notation/model/part_spec.rb +53 -4
  111. data/spec/notation/model/pitch_spec.rb +15 -0
  112. data/spec/notation/model/score_spec.rb +64 -72
  113. data/spec/notation/parsing/link_nodes_spec.rb +3 -3
  114. data/spec/notation/parsing/link_parsing_spec.rb +6 -6
  115. data/spec/notation/parsing/note_node_spec.rb +34 -9
  116. data/spec/notation/parsing/note_parsing_spec.rb +11 -9
  117. data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +4 -0
  118. data/spec/notation/parsing/pitch_node_spec.rb +0 -1
  119. data/spec/notation/util/value_computer_spec.rb +2 -2
  120. data/spec/performance/conversion/glissando_converter_spec.rb +9 -9
  121. data/spec/performance/conversion/note_sequence_extractor_spec.rb +48 -53
  122. data/spec/performance/conversion/portamento_converter_spec.rb +11 -9
  123. data/spec/performance/conversion/score_collator_spec.rb +59 -63
  124. data/spec/performance/midi/midi_util_spec.rb +22 -8
  125. data/spec/performance/midi/part_sequencer_spec.rb +2 -2
  126. data/spec/performance/midi/score_sequencer_spec.rb +12 -10
  127. data/spec/performance/midi/score_sequencing_spec.rb +2 -2
  128. data/spec/performance/model/note_sequence_spec.rb +41 -134
  129. data/spec/printing/note_engraving_spec.rb +204 -0
  130. data/spec/printing/score_engraver_spec.rb +40 -0
  131. data/spec/spec_helper.rb +1 -0
  132. metadata +69 -23
  133. data/examples/notation/hip.rb +0 -32
  134. data/examples/notation/missed_connection.rb +0 -26
  135. data/examples/notation/song1.rb +0 -33
  136. data/examples/notation/song2.rb +0 -32
  137. data/lib/musicality/notation/model/links.rb +0 -11
  138. data/lib/musicality/notation/packing/change_packing.rb +0 -56
  139. data/lib/musicality/notation/packing/part_packing.rb +0 -31
  140. data/lib/musicality/notation/packing/score_packing.rb +0 -123
  141. data/lib/musicality/performance/model/note_attacks.rb +0 -19
  142. data/lib/musicality/performance/util/note_linker.rb +0 -28
  143. data/spec/notation/packing/change_packing_spec.rb +0 -304
  144. data/spec/notation/packing/part_packing_spec.rb +0 -66
  145. data/spec/notation/packing/score_packing_spec.rb +0 -255
  146. 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 a MIDI file.
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} <input> [PART PROGRAM] ... [options]
14
+ #{exe_name} SCORE [PART]... [options]
10
15
  #{exe_name} -h | --help
11
16
  #{exe_name} --version
12
17
 
13
18
  Arguments:
14
- input A musicality score file (may be packed as a hash) in YAML format
15
- PART name of a part in the score
16
- PROGRAM MIDI program (instrument) number for the given part
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
- fin_name = args["<input>"]
47
- File.open(fin_name) do |fin|
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 = Score.unpack(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
- part_names = args["PART"]
64
- program_nums = args["PROGRAM"].map {|str| str.to_i }
65
- instr_map = Hash[[part_names,program_nums].transpose]
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
- seq = sequencer.make_midi_seq(instr_map)
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
- fout_name = args["--outfile"]
73
- if fout_name.nil?
74
- fout_name = "#{File.dirname(fin_name)}/#{File.basename(fin_name,File.extname(fin_name))}.mid"
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::Unmeasured.new(120,
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
- instr_map = { "bass" => 32, "guitar" => 25 }
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::Measured.new(SIX_EIGHT,90) do |s|
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("main" => 81, "bass" => 80, "pluck" => 46)
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::Measured.new(FOUR_FOUR,120) do |s|
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/note_attacks'
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'