brevity 0.4.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 (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