brevity 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.gitignore +7 -0
  4. data/.rspec +1 -0
  5. data/.ruby-version +1 -0
  6. data/.yardopts +1 -0
  7. data/ChangeLog.rdoc +4 -0
  8. data/Gemfile +3 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.rdoc +27 -0
  11. data/Rakefile +67 -0
  12. data/bin/debrief +56 -0
  13. data/brevity.gemspec +28 -0
  14. data/examples/alley_cat.br +50 -0
  15. data/examples/hip.br +15 -0
  16. data/examples/missed_connection.br +6 -0
  17. data/examples/song1.br +11 -0
  18. data/examples/song2.br +10 -0
  19. data/examples/twinkle.br +18 -0
  20. data/lib/brevity/commands/constants.rb +18 -0
  21. data/lib/brevity/commands/expr.rb +17 -0
  22. data/lib/brevity/commands/meter.rb +20 -0
  23. data/lib/brevity/commands/part.rb +47 -0
  24. data/lib/brevity/commands/tempo.rb +13 -0
  25. data/lib/brevity/itemization.rb +73 -0
  26. data/lib/brevity/parsing/expression/dynamic.rb +280 -0
  27. data/lib/brevity/parsing/expression/dynamic.treetop +41 -0
  28. data/lib/brevity/parsing/expression/dynamic_nodes.rb +55 -0
  29. data/lib/brevity/parsing/expression/expression.rb +429 -0
  30. data/lib/brevity/parsing/expression/expression.treetop +39 -0
  31. data/lib/brevity/parsing/expression/expression_nodes.rb +26 -0
  32. data/lib/brevity/parsing/expression/gradual.rb +44 -0
  33. data/lib/brevity/parsing/expression/gradual.treetop +9 -0
  34. data/lib/brevity/parsing/expression/gradual_node.rb +11 -0
  35. data/lib/brevity/parsing/expression/label.rb +75 -0
  36. data/lib/brevity/parsing/expression/label.treetop +9 -0
  37. data/lib/brevity/parsing/expression/label_node.rb +15 -0
  38. data/lib/brevity/parsing/expression/sequence.rb +130 -0
  39. data/lib/brevity/parsing/expression/sequence.treetop +12 -0
  40. data/lib/brevity/parsing/expression/sequence_node.rb +14 -0
  41. data/lib/brevity/parsing/file/command.rb +216 -0
  42. data/lib/brevity/parsing/file/command.treetop +17 -0
  43. data/lib/brevity/parsing/file/command_node.rb +11 -0
  44. data/lib/brevity/parsing/file/comment.rb +178 -0
  45. data/lib/brevity/parsing/file/comment.treetop +21 -0
  46. data/lib/brevity/parsing/file/comment_node.rb +3 -0
  47. data/lib/brevity/parsing/file/file.rb +152 -0
  48. data/lib/brevity/parsing/file/file.treetop +16 -0
  49. data/lib/brevity/parsing/file/file_node.rb +7 -0
  50. data/lib/brevity/parsing/file/path.rb +235 -0
  51. data/lib/brevity/parsing/file/path.treetop +12 -0
  52. data/lib/brevity/parsing/modifiers/duplicate_modifier.rb +65 -0
  53. data/lib/brevity/parsing/modifiers/duplicate_modifier.treetop +11 -0
  54. data/lib/brevity/parsing/modifiers/duplicate_modifier_node.rb +8 -0
  55. data/lib/brevity/parsing/modifiers/modifier.rb +64 -0
  56. data/lib/brevity/parsing/modifiers/modifier.treetop +13 -0
  57. data/lib/brevity/parsing/modifiers/stretch_modifier.rb +69 -0
  58. data/lib/brevity/parsing/modifiers/stretch_modifier.treetop +11 -0
  59. data/lib/brevity/parsing/modifiers/stretch_modifier_node.rb +21 -0
  60. data/lib/brevity/parsing/modifiers/transpose_modifier.rb +69 -0
  61. data/lib/brevity/parsing/modifiers/transpose_modifier.treetop +11 -0
  62. data/lib/brevity/parsing/modifiers/transpose_modifier_node.rb +13 -0
  63. data/lib/brevity/parsing/note/accent.rb +44 -0
  64. data/lib/brevity/parsing/note/accent.treetop +9 -0
  65. data/lib/brevity/parsing/note/duration.rb +203 -0
  66. data/lib/brevity/parsing/note/duration.treetop +23 -0
  67. data/lib/brevity/parsing/note/duration_nodes.rb +19 -0
  68. data/lib/brevity/parsing/note/link.rb +69 -0
  69. data/lib/brevity/parsing/note/link.treetop +11 -0
  70. data/lib/brevity/parsing/note/link_node.rb +19 -0
  71. data/lib/brevity/parsing/note/note.rb +300 -0
  72. data/lib/brevity/parsing/note/note.treetop +30 -0
  73. data/lib/brevity/parsing/note/note_nodes.rb +77 -0
  74. data/lib/brevity/parsing/note/pitch.rb +81 -0
  75. data/lib/brevity/parsing/note/pitch.treetop +9 -0
  76. data/lib/brevity/parsing/note/pitch_node.rb +50 -0
  77. data/lib/brevity/parsing/numbers/nonnegative_integer.rb +53 -0
  78. data/lib/brevity/parsing/numbers/nonnegative_integer.treetop +9 -0
  79. data/lib/brevity/parsing/numbers/positive_integer.rb +91 -0
  80. data/lib/brevity/parsing/numbers/positive_integer.treetop +15 -0
  81. data/lib/brevity/read_file.rb +18 -0
  82. data/lib/brevity/score_maker.rb +64 -0
  83. data/lib/brevity/version.rb +4 -0
  84. data/lib/brevity.rb +53 -0
  85. data/manuals/brevity.pdf +0 -0
  86. data/manuals/brevity.tex +273 -0
  87. data/spec/brevity_spec.rb +8 -0
  88. data/spec/commands/expr_spec.rb +15 -0
  89. data/spec/commands/meter_spec.rb +21 -0
  90. data/spec/commands/part_spec.rb +16 -0
  91. data/spec/commands/tempo_spec.rb +20 -0
  92. data/spec/itemization_spec.rb +46 -0
  93. data/spec/parsing/expression/dynamic_nodes_spec.rb +32 -0
  94. data/spec/parsing/expression/dynamic_spec.rb +23 -0
  95. data/spec/parsing/expression/expression_nodes_spec.rb +87 -0
  96. data/spec/parsing/expression/expression_spec.rb +85 -0
  97. data/spec/parsing/expression/gradual_spec.rb +10 -0
  98. data/spec/parsing/expression/label_node_spec.rb +13 -0
  99. data/spec/parsing/expression/label_spec.rb +35 -0
  100. data/spec/parsing/file/command_node_spec.rb +29 -0
  101. data/spec/parsing/file/command_spec.rb +18 -0
  102. data/spec/parsing/file/comment_spec.rb +14 -0
  103. data/spec/parsing/file/file_node_spec.rb +19 -0
  104. data/spec/parsing/file/file_spec.rb +30 -0
  105. data/spec/parsing/modifiers/modifier_nodes_spec.rb +25 -0
  106. data/spec/parsing/modifiers/modifier_parsers_spec.rb +20 -0
  107. data/spec/parsing/note/accent_spec.rb +27 -0
  108. data/spec/parsing/note/duration_nodes_spec.rb +79 -0
  109. data/spec/parsing/note/duration_spec.rb +69 -0
  110. data/spec/parsing/note/link_node_spec.rb +30 -0
  111. data/spec/parsing/note/link_spec.rb +23 -0
  112. data/spec/parsing/note/note_nodes_spec.rb +82 -0
  113. data/spec/parsing/note/note_spec.rb +188 -0
  114. data/spec/parsing/note/pitch_node_spec.rb +48 -0
  115. data/spec/parsing/note/pitch_spec.rb +23 -0
  116. data/spec/parsing/numbers/nonnegative_integer_spec.rb +11 -0
  117. data/spec/parsing/numbers/positive_integer_spec.rb +17 -0
  118. data/spec/spec_helper.rb +112 -0
  119. metadata +293 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a75a79f97d04f510ba6fe4b19c2f9d16ad4e29c4
4
+ data.tar.gz: ffd37ed1f4e1bdb122b5482fb06c6de9a9798549
5
+ SHA512:
6
+ metadata.gz: a68eff07683640d944d6d620bd24f65f14263d399099dedeaea6a402f1bc80de4a05dfea84cb073ddd2f3b552655c6ab628202f58a6545042fb75e31b2e4b35d
7
+ data.tar.gz: 46252d7032b3ec064c85aa59f66685f7d0fdfe90eca956148ce8efcc79b8c936b553e38527ef9db1b088e0d8ae384f735819407b2eca90fd76e49f007372eed9
data/.document ADDED
@@ -0,0 +1,3 @@
1
+ -
2
+ ChangeLog.rdoc
3
+ LICENSE.txt
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ Gemfile.lock
2
+ doc/
3
+ pkg/
4
+ vendor/cache/*.gem
5
+ .bundle/*
6
+ bundler_stubs/*
7
+
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup rdoc --title "brevity Documentation" --protected
data/ChangeLog.rdoc ADDED
@@ -0,0 +1,4 @@
1
+ === 0.1.0 / 2013-12-24
2
+
3
+ * Initial release:
4
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 James Tunnell
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,27 @@
1
+ = brevity
2
+
3
+ * {Homepage}[https://rubygems.org/gems/brevity]
4
+ * {Documentation}[http://rubydoc.info/gems/brevity/frames]
5
+ * {Email}[mailto:jamestunnell at gmail.com]
6
+
7
+ == Description
8
+
9
+ Parse and process brevity files, used for music notation. Convert them to other formats.
10
+
11
+ == Features
12
+
13
+ == Examples
14
+
15
+ require 'brevity'
16
+
17
+ == Requirements
18
+
19
+ == Install
20
+
21
+ $ gem install brevity
22
+
23
+ == Copyright
24
+
25
+ Copyright (c) 2013 James Tunnell
26
+
27
+ See LICENSE.txt for details.
data/Rakefile ADDED
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+
5
+ begin
6
+ require 'bundler'
7
+ rescue LoadError => e
8
+ warn e.message
9
+ warn "Run `gem install bundler` to install Bundler."
10
+ exit -1
11
+ end
12
+
13
+ begin
14
+ Bundler.setup(:development)
15
+ rescue Bundler::BundlerError => e
16
+ warn e.message
17
+ warn "Run `bundle install` to install missing gems."
18
+ exit e.status_code
19
+ end
20
+
21
+ require 'rake'
22
+
23
+ require 'rspec/core/rake_task'
24
+ RSpec::Core::RakeTask.new
25
+
26
+ task :test => :spec
27
+ task :default => :spec
28
+
29
+ require 'yard'
30
+ YARD::Rake::YardocTask.new
31
+ task :doc => :yard
32
+
33
+ require "bundler/gem_tasks"
34
+
35
+ def rb_fname fname
36
+ basename = File.basename(fname, File.extname(fname))
37
+ dirname = File.dirname(fname)
38
+ "#{dirname}/#{basename}.rb"
39
+ end
40
+
41
+ task :build_parsers do
42
+ wd = Dir.pwd
43
+ Dir.chdir "lib/brevity/parsing"
44
+ parser_files = Dir.glob(["**/*.treetop","**/*.tt"])
45
+
46
+ if parser_files.empty?
47
+ puts "No parsers found"
48
+ return
49
+ end
50
+
51
+ build_list = parser_files.select do |fname|
52
+ rb_name = rb_fname(fname)
53
+ !File.exists?(rb_name) || (File.mtime(fname) > File.mtime(rb_name))
54
+ end
55
+
56
+ if build_list.any?
57
+ puts "building parsers:"
58
+ build_list.each do |fname|
59
+ puts " #{fname} -> #{rb_fname(fname)}"
60
+ `tt -f #{fname}`
61
+ end
62
+ else
63
+ puts "Parsers are up-to-date"
64
+ end
65
+ Dir.chdir wd
66
+ end
67
+ task :spec => :build_parsers
data/bin/debrief ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'brevity'
4
+ require 'docopt'
5
+ require 'yaml'
6
+
7
+ exe_name = File.basename(__FILE__)
8
+
9
+ doc = <<DOCOPT
10
+ Parses a Brevity file, outputting a music-transcription parts as YAML.
11
+
12
+ Usage:
13
+ #{exe_name} <input>
14
+ #{exe_name} <input> <output>
15
+ #{exe_name} -h | --help
16
+ #{exe_name} --version
17
+
18
+ Options:
19
+ -h --help Show this screen.
20
+ --version Show version.
21
+
22
+ DOCOPT
23
+
24
+ begin
25
+ require "pp"
26
+ args = Docopt::docopt(doc)
27
+ pp args
28
+ rescue Docopt::Exit => e
29
+ puts e.message
30
+ exit
31
+ end
32
+
33
+ fin = args["<input>"]
34
+ print "Reading file '#{fin}'..."
35
+ cmd_nodes = Brevity.read_file fin
36
+ puts "complete"
37
+
38
+ sm = Brevity::ScoreMaker.new
39
+
40
+ print "Processing commands..."
41
+ sm.process_nodes cmd_nodes
42
+ puts "complete"
43
+
44
+ print "Making score..."
45
+ score = sm.make_score
46
+ puts "complete"
47
+
48
+ fout = args["[output]"]
49
+ if fout.nil?
50
+ fout = "#{File.dirname(fin)}/#{File.basename(fin,File.extname(fin))}.yml"
51
+ end
52
+ print "Writing file '#{fout}'..."
53
+ File.open(fout,"w") do |f|
54
+ f.write(YAML.dump(score))
55
+ end
56
+ puts "complete"
data/brevity.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require File.expand_path('../lib/brevity/version', __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "brevity"
7
+ gem.version = Brevity::VERSION
8
+ gem.summary = %q{Parse and process brevity files. Convert them to other formats.}
9
+ gem.description = %q{Parse and process brevity files, used for music notation. Convert them to other formats.}
10
+ gem.license = "MIT"
11
+ gem.authors = ["James Tunnell"]
12
+ gem.email = "jamestunnell@gmail.com"
13
+ gem.homepage = "https://rubygems.org/gems/brevity"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_development_dependency 'bundler', '~> 1.0'
21
+ gem.add_development_dependency 'rake', '~> 0.8'
22
+ gem.add_development_dependency 'rspec', '~> 2.4'
23
+ gem.add_development_dependency 'yard', '~> 0.8'
24
+ gem.add_development_dependency 'pry'
25
+
26
+ gem.add_dependency 'treetop'
27
+ gem.add_dependency 'music-transcription', '~> 0.7'
28
+ end
@@ -0,0 +1,50 @@
1
+ \meter{4}{/4}
2
+ \tempo{120}
3
+
4
+ #-------------------------------------------------------------------------
5
+
6
+ \expr{r1}{ /4C5 /4B4 /4A4 /4Ab4 /4G4 /4Ab4 /4A4 /4 /4G4 /4Ab4 /4A4 }
7
+ \expr{r2}{ r1 /4Bb4 /4B4 3/4 }
8
+ \expr{r3}{ r1 /4F4 /4E4 3/4 }
9
+ \expr{r4}{ r1 /4B4 /4C5 2/4 mf /4C5 }
10
+
11
+ \part{r}{f}{
12
+ r2 r3 r2 r4
13
+
14
+ /4D5 /2D5 /4Ab4 /4A4 /2 /4C5
15
+ /4D5 /2D5 /4Gb4 /4D4 /2 /4C5
16
+ /4D5 /2D5 /4F4 /4Gb4 3/4
17
+
18
+ /4D5 /4C5 /4B4 /4A4 /4G4 /4Gb4 /4F4 /4
19
+ /4C5 /4B4 /4A4 /4Ab4 /4G4 /4Ab4 /4A3 /4
20
+ /4G4 /4Ab4 /4A4 /4Bb4 /4B4 3/4
21
+
22
+ r1 /4B4 /4C5 3/4
23
+ }
24
+
25
+ #-------------------------------------------------------------------------
26
+
27
+ \expr{l1}{ /4E3,C4 }
28
+ \expr{l2}{ /4F3,B4 }
29
+ \expr{l3}{ (/4G2 /4A2 /4G2)=/4 }
30
+ \expr{l4}{
31
+ /4C2 l1 /4G2 l1 /4C2 l1 l1 l3
32
+ /4C2 l1 /4E2 /4Eb2 /4D2 (/4G2,G3 /4Gb2,Gb3 /4G2,G3)=/4 /4Ab2,Ab3 /4G2,G3
33
+ /4D2 l2 /4G2 l2 /4D2 l2 l2 l3
34
+ }
35
+ \expr{l5}{
36
+ l4
37
+ /4D2 /4F3,B3 /4G2,F3,A3 /4F3,G3
38
+ }
39
+
40
+ \part{l}{mf}{
41
+ l5 /4C2 /4E2 /4Eb2 /4D2
42
+ l5 /4C2,E3,C4 /4C2 /4D2 mp /4E2,Ab3
43
+
44
+ /4F2,F3,A3 /4F3,A3 /4C2 /4Db4 /4F2,D4 /4C4 /4C2,A3 /4F3
45
+ /4C3,E3,G3 /4E3,G3 /4G2 /4Eb4 /4C2,E4 /4C4 /4G2,A3 /4G3
46
+ /4D2,Gb3,C4 /4Gb3,C4 /4A2 /4Db4 /4D2,D4 /4C4 /4A2,A3 /4Gb3
47
+ /4D2 /4E2 /4F2 /4Gb2,C4 /4G2,B3 /4A2,A3 /4B2,G3 /4G2
48
+
49
+ l4 /4D2 /4F2 /4E2 /4D2 /4C2 /4Db2,Ab2,F3,Bb3,Eb4 /2C2,G2,E3,A3,D4
50
+ }
data/examples/hip.br ADDED
@@ -0,0 +1,15 @@
1
+ \meter{4}{/4}
2
+ \tempo{120}
3
+
4
+ \expr{bass}{
5
+ /6Bb2 /4 /3Ab2 /6F2 /12Ab2
6
+ /6Bb2 /4 /3Ab2 /4Ab2
7
+ }
8
+
9
+ \expr{lead}{
10
+ /6Bb3 /4 5/18Db4 /36Eb4 /36Db4 /6Ab4 /12Db4
11
+ /6Bb3 /4 11/24Db4 /8C4
12
+ }
13
+
14
+ \part{Bass}{mf}{ bass:2 bass+2 bass }
15
+ \part{Lead}{mf}{ lead:2 lead+2 lead }
@@ -0,0 +1,6 @@
1
+ \meter{4}{/4}
2
+ \tempo{120}
3
+
4
+ \expr{a}{ /4Eb2 /4 /4Bb2 /4 /4Eb2 /8 /8B2 /4Bb2 /4Ab2 }
5
+ \expr{b}{ /4Bb2 /8 5/8F3 /4Bb2 /8 5/8F3 }
6
+ \part{bass}{mf}{ (a:2 b b+1):2 }
data/examples/song1.br ADDED
@@ -0,0 +1,11 @@
1
+ \meter{4}{/4}
2
+ \tempo{120}
3
+
4
+ \expr{a}{ 3/8C2 /4Eb2 5/16F2 /16Eb2
5
+ /8 /4C2 /4Eb2 3/8 }
6
+ \expr{b}{
7
+ /8 /8Bb3:4 /4C4 /4A3 /8G3 /8F3 5/16G3 1/16E3 /8E3 /8
8
+ /8 /8Bb3:4 /4C4 /8A3 /8E4 /8E4 /8D4 /8C4 /2 }
9
+
10
+ \part{1}{mf}{ a:4 }
11
+ \part{2}{mf}{ b:2 }
data/examples/song2.br ADDED
@@ -0,0 +1,10 @@
1
+ \meter{4}{/4}
2
+ \tempo{120}
3
+
4
+ \expr{a}{ 1C4 1Bb3 1Ab3 /2G3 /2Bb3 }
5
+ \expr{b}{ 3/8E5 1D5 1C5 5/8C5 /2C5 /2D5 }
6
+ \expr{c}{ /8 /4G5 /2F5 /4 /4F5 /2Eb5 /4 /4Eb5 /2Eb5 /8 /2Eb5 /2F5 }
7
+
8
+ \part{1}{mf}{ a:2 }
9
+ \part{2}{mf}{ b:2 }
10
+ \part{3}{mf}{ c:2 }
@@ -0,0 +1,18 @@
1
+ \meter{4}{/4}
2
+ \tempo{90}
3
+
4
+ # A
5
+
6
+ \expr{rhA}{ /4C4:2 /4G4:2 /4A4:2 /2G4
7
+ /4F4:2 /4E4:2 /4D4:2 /2C4 }
8
+
9
+ \expr{lhA}{ 1E3 /2F3 /2E3
10
+ /2A3 /2G3 /2F3 /2E3 }
11
+
12
+ # B
13
+
14
+ \expr{rhB}{ /4G4:2 /4F4:2 /4E4:2 /2D4 }
15
+ \expr{lhB}{ 1C4 /2C4 /2G3 }
16
+
17
+ \part{L. Hand}{mf}{ rhA rhB:2 rhA }
18
+ \part{R. Hand}{f }{ lhA lhB:2 lhA }
@@ -0,0 +1,18 @@
1
+ module Brevity
2
+ module Commands
3
+ ENV_START_TEMPO = :start_tempo
4
+ ENV_START_METER = :start_meter
5
+ ENV_EXPRS = :exprs
6
+ ENV_PARTS = :parts
7
+ ENV_TEMPO_CHANGES = :tempo_changes
8
+ ENV_METER_CHANGES = :meter_changes
9
+
10
+ EXPR_PARSER = ExpressionParser.new
11
+ LABEL_PARSER = LabelParser.new
12
+ DYNAMIC_PARSER = DynamicParser.new
13
+
14
+ def class_const sym
15
+ self.class.const_get(sym)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ module Brevity
2
+ module Commands
3
+ def expr label_str, expr_str
4
+ label_node = LABEL_PARSER.parse(label_str)
5
+ expr_node = EXPR_PARSER.parse(expr_str)
6
+
7
+ if label_node.nil?
8
+ raise ArgumentError, "Could not parse label string '#{label_str}'"
9
+ end
10
+ if expr_node.nil?
11
+ raise ArgumentError, "Could not parse expr string '#{expr_str}'"
12
+ end
13
+
14
+ @env[ENV_EXPRS][label_node.to_key] = expr_node.primitives(@env[ENV_EXPRS])
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ module Brevity
2
+ module Commands
3
+ def meter beats_per_measure_str, beat_dur_str
4
+ beats_per_measure_node = PositiveIntegerParser.new.parse(beats_per_measure_str)
5
+ beat_dur_node = DurationParser.new.parse(beat_dur_str)
6
+
7
+ if beats_per_measure_node.nil?
8
+ raise ArgumentError, "Could not parse beats per measure string '#{beats_per_measure_str}'"
9
+ end
10
+ if beat_dur_node.nil?
11
+ raise ArgumentError, "Could not parse beat duration string '#{beat_dur_str}'"
12
+ end
13
+
14
+ @env[ENV_START_METER] = Music::Transcription::Meter.new(
15
+ beats_per_measure_node.to_i,
16
+ beat_dur_node.to_r
17
+ )
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,47 @@
1
+ module Brevity
2
+ module Commands
3
+ def part name_str, startdynamic_str, expr_str
4
+ dyn_node = DYNAMIC_PARSER.parse(startdynamic_str.strip)
5
+ expr_node = EXPR_PARSER.parse(expr_str)
6
+
7
+ if dyn_node.nil?
8
+ raise ArgumentError, "Could not parse start dynamic string '#{startdynamic_str}'"
9
+ end
10
+ if expr_node.nil?
11
+ raise ArgumentError, "Could not parse expr string '#{expr_str}'"
12
+ end
13
+
14
+ startdyn = dyn_node.to_dynamic
15
+ notes = []
16
+ dynamic_changes = {}
17
+ offset = 0.to_r
18
+ change_mark = nil
19
+
20
+ expr_node.primitives(@env[ENV_EXPRS]).each do |p|
21
+ case p
22
+ when Music::Transcription::Note
23
+ note = p
24
+ notes.push note
25
+ offset += note.duration
26
+ when Music::Transcription::Dynamic
27
+ dynamic = p
28
+ if change_mark.nil?
29
+ change = Music::Transcription::Change::Immediate.new(dynamic)
30
+ else
31
+ duration = offset - change_mark
32
+ change = Music::Transcription::Change::Gradual.new(dynamic,duration)
33
+ change_mark = nil
34
+ end
35
+ dynamic_changes[offset] = change
36
+ when GradualNode
37
+ change_mark = offset
38
+ end
39
+ end
40
+
41
+ @env[ENV_PARTS][name_str] = Music::Transcription::Part.new(
42
+ startdyn,
43
+ notes: notes,
44
+ dynamic_changes: dynamic_changes)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,13 @@
1
+ module Brevity
2
+ module Commands
3
+ def tempo beats_per_minute_str
4
+ bpm_node = PositiveIntegerParser.new.parse(beats_per_minute_str)
5
+
6
+ if bpm_node.nil?
7
+ raise ArgumentError, "Could not parse beats per minute string '#{beats_per_minute_str}'"
8
+ end
9
+
10
+ @env[ENV_START_TEMPO] = bpm_node.to_i
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,73 @@
1
+ module Brevity
2
+ class Itemization
3
+ attr_reader :notes, :dynamic_changes, :tempo_changes, :duration
4
+
5
+ def initialize notes:[], dynamic_changes:{}, tempo_changes:{}
6
+ @notes = notes
7
+ @dynamic_changes = dynamic_changes
8
+ @tempo_changes = tempo_changes
9
+ @duration = @notes.map{ |n| n.duration }.each.inject(0.to_r,:+)
10
+ end
11
+
12
+ def eql?(other)
13
+ self == other
14
+ end
15
+
16
+ def clone
17
+ Marshal.load(Marshal.dump(self))
18
+ end
19
+
20
+ def ==(other)
21
+ (self.notes == other.notes) &&
22
+ (self.dynamic_changes == other.dynamic_changes) &&
23
+ (self.tempo_changes == other.tempo_changes)
24
+ end
25
+
26
+ def append other
27
+ self.clone.append! other
28
+ end
29
+
30
+ def append! other
31
+ other.dynamic_changes.each do |offset,change|
32
+ @dynamic_changes[offset + @duration] = change
33
+ end
34
+ other.tempo_changes.each do |offset,change|
35
+ @tempo_changes[offset + @duration] = change
36
+ end
37
+ @notes += other.notes
38
+ @duration += other.duration
39
+
40
+ return self
41
+ end
42
+
43
+ def calc_duration
44
+ @notes.each.inject(0.to_r,:+)
45
+ end
46
+
47
+ def stretch ratio
48
+ self.clone.stretch! ratio
49
+ end
50
+
51
+ def stretch! ratio
52
+ @notes.each_index do |i|
53
+ n1 = @notes[i]
54
+ @notes[i] = Music::Transcription::Note.new(n1.duration * ratio, n1.pitches, links: n1.links, accent: n1.accent)
55
+ end
56
+ @dynamic_changes = Hash[ @dynamic_changes.map {|k,v| [k*ratio,v] }]
57
+ @tempo_changes = Hash[ @tempo_changes.map {|k,v| [k*ratio,v] }]
58
+ return self
59
+ end
60
+
61
+ def transpose diff
62
+ self.clone.transpose! diff
63
+ end
64
+
65
+ def transpose! diff
66
+ @notes[0...-1].each do |note|
67
+ note.transpose_pitches_and_links! diff
68
+ end
69
+ @notes[-1].transpose_pitches_only! diff
70
+ return self
71
+ end
72
+ end
73
+ end