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.
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'