webern 0.2.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.
- data/.document +4 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +50 -0
- data/Rakefile +85 -0
- data/VERSION +1 -0
- data/bin/webern +10 -0
- data/lib/core_ext.rb +11 -0
- data/lib/webern/lilypond_builder.rb +62 -0
- data/lib/webern/matrix.rb +26 -0
- data/lib/webern/row.rb +53 -0
- data/lib/webern.rb +19 -0
- data/spec/array_spec.rb +22 -0
- data/spec/helper.rb +5 -0
- data/spec/lilypond_builder_spec.rb +40 -0
- data/spec/matrix_spec.rb +22 -0
- data/spec/row_spec.rb +29 -0
- data/spec/webern_spec.rb +55 -0
- metadata +87 -0
data/.document
ADDED
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Michael Berkowitz
|
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.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# webern
|
2
|
+
|
3
|
+
### current version: 0.2.0
|
4
|
+
|
5
|
+
[http://github.com/mikowitz/webern][webern]
|
6
|
+
|
7
|
+
## Description
|
8
|
+
|
9
|
+
Taking a 12-tone row generated from user input Webern will create the full matrix based upon this
|
10
|
+
row, and then output all 48 possible rows created by that matrix to a .pdf file using the LilyPond notational
|
11
|
+
language.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Install the gemcutter gem
|
16
|
+
|
17
|
+
~$ gem install gemcutter
|
18
|
+
|
19
|
+
Add gemcutter.org to your gem remote sources
|
20
|
+
|
21
|
+
~$ gem tumble
|
22
|
+
|
23
|
+
Download and install this gem
|
24
|
+
|
25
|
+
~$ gem install crayon
|
26
|
+
|
27
|
+
## Requirements
|
28
|
+
|
29
|
+
No other gems are required, but you do need [LilyPond][lilypond] to generate the .pdf file.
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
|
33
|
+
`Webern` can accept a full 12-tone row, a partial 12-tone row, or a list of strings which will be parsed into a numeric row:
|
34
|
+
|
35
|
+
~$ webern 9 1 4 7 8 2 0 10 5 6 11 3
|
36
|
+
~$ webern 0 6 10 9 4 7
|
37
|
+
~$ webern michael berkowitz
|
38
|
+
|
39
|
+
In the instance where a partial row is given, or the strings given do not provide 12 distinct letters, `Webern` will complete the row with the missing numbers in ascending order. In the example above, `Webern` would complete the row like this:
|
40
|
+
|
41
|
+
[0 6 10 9 4 7] #=> [0 6 10 9 4 7 1 2 3 5 8 11]
|
42
|
+
|
43
|
+
`Webern` will take the completed row and create the full 12-tone matrix, then generate a LilyPond file containing all 48 possible rows contained in the matrix, and output them to a .pdf file.
|
44
|
+
|
45
|
+
## Copyright
|
46
|
+
|
47
|
+
Copyright (c) 2010 Michael Berkowitz. See LICENSE for details.
|
48
|
+
|
49
|
+
[webern]: http://github.com/mikowitz/webern "Webern repository"
|
50
|
+
[lilypond]: http://lilypond.org "LilyPond"
|
data/Rakefile
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "webern"
|
8
|
+
gem.summary = %Q{Creates a .pdf reference sheet for all 12-tone rows generated from a given prime row's matrix.}
|
9
|
+
gem.description = %Q{Taking a 12-tone row generated from user input Webern will create the full matrix based upon this row, and then output all 48 possible rows created by that matrix to a .pdf file using the LilyPond notational language.}
|
10
|
+
gem.email = "michael.berkowitz@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/mikowitz/webern"
|
12
|
+
gem.authors = ["Michael Berkowitz"]
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'spec/rake/spectask'
|
21
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
22
|
+
spec.libs << "lib" << "spec"
|
23
|
+
spec.spec_opts = ["-cfs"]
|
24
|
+
spec.spec_files = FileList["spec/**/*_spec.rb"]
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << "lib" << "spec"
|
29
|
+
spec.pattern = "spec/**/*_spec.rb"
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
task :test => :check_dependencies
|
34
|
+
|
35
|
+
begin
|
36
|
+
require 'reek/adapters/rake_task'
|
37
|
+
Reek::RakeTask.new do |t|
|
38
|
+
t.fail_on_error = true
|
39
|
+
t.verbose = false
|
40
|
+
t.source_files = 'lib/**/*.rb'
|
41
|
+
end
|
42
|
+
rescue LoadError
|
43
|
+
task :reek do
|
44
|
+
abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
begin
|
49
|
+
require 'roodi'
|
50
|
+
require 'roodi_task'
|
51
|
+
RoodiTask.new do |t|
|
52
|
+
t.verbose = false
|
53
|
+
end
|
54
|
+
rescue LoadError
|
55
|
+
task :roodi do
|
56
|
+
abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
task :default => :spec
|
61
|
+
|
62
|
+
begin
|
63
|
+
require 'yard'
|
64
|
+
YARD::Rake::YardocTask.new do |t|
|
65
|
+
t.options = %w{--no-private -mmarkdown}
|
66
|
+
end
|
67
|
+
rescue LoadError
|
68
|
+
task :yardoc do
|
69
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
begin
|
74
|
+
require 'hanna/rdoctask'
|
75
|
+
desc "generate hanna documentation"
|
76
|
+
Rake::RDocTask.new(:hanna) do |t|
|
77
|
+
t.rdoc_files.include("README.md", "License", "lib/**/*.rb")
|
78
|
+
t.main = "README.md"
|
79
|
+
t.rdoc_dir = "hanna"
|
80
|
+
end
|
81
|
+
rescue LoadError
|
82
|
+
task :hanna do
|
83
|
+
abort "hanna is not available. In order to run this task, you must: sudo gem install hanna"
|
84
|
+
end
|
85
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
data/bin/webern
ADDED
data/lib/core_ext.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
module Webern
|
2
|
+
module LilypondBuilder
|
3
|
+
NOTES = %w{c cs d ef e f fs g af a bf b}
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_writer :zero_note
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.current_lilypond_version
|
10
|
+
`lilypond --version`.match(/\d+\.\d+\.\d+/)[0]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.zero_note
|
14
|
+
@zero_note ||= "c"
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.convert_row(row)
|
18
|
+
row.map{|note| NOTES[(note + NOTES.index(self.zero_note)) % 12] }.join(" ")
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.generate_file(matrix)
|
22
|
+
file = [PREAMBLE_BLOCK, "\n"]
|
23
|
+
file << STAFF_BLOCK
|
24
|
+
[:primes, :retrogrades, :inversions, :retrograde_inversions].each do |method|
|
25
|
+
abbrev = method.to_s.scan(/^\w|_\w/).join("").gsub(/_/, "").upcase
|
26
|
+
matrix.send(method).each do |row|
|
27
|
+
first = row[0]
|
28
|
+
row = self.convert_row(row)
|
29
|
+
row = row.sub(" ", "^\\markup{#{abbrev}#{first}} ")
|
30
|
+
file << " #{row}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
file << "\}" << "\n" << SCORE_BLOCK
|
34
|
+
File.open("matrix.ly", "w") do |f|
|
35
|
+
f << file.join("\n")
|
36
|
+
end
|
37
|
+
# TODO: This unless seems a bit messy
|
38
|
+
system("lilypond matrix.ly") unless $0 =~ /spec|rcov/
|
39
|
+
end
|
40
|
+
|
41
|
+
PREAMBLE_BLOCK = <<-STR
|
42
|
+
\\version \"#{self.current_lilypond_version}\"
|
43
|
+
\\include \"english.ly\"
|
44
|
+
#(set-global-staff-size 13)
|
45
|
+
STR
|
46
|
+
|
47
|
+
STAFF_BLOCK = <<-STR
|
48
|
+
rows = {
|
49
|
+
\\override Score.TimeSignature #'stencil = ##f
|
50
|
+
\\clef bass
|
51
|
+
\\time 12/4
|
52
|
+
STR
|
53
|
+
|
54
|
+
SCORE_BLOCK = <<-STR
|
55
|
+
\\score {
|
56
|
+
<<
|
57
|
+
\\new Staff \\rows
|
58
|
+
>>
|
59
|
+
}
|
60
|
+
STR
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Webern
|
2
|
+
class Matrix
|
3
|
+
attr_accessor :prime_row
|
4
|
+
BASIC_ROW = Array(0..11)
|
5
|
+
|
6
|
+
def initialize(row)
|
7
|
+
@prime_row = row
|
8
|
+
end
|
9
|
+
|
10
|
+
def primes
|
11
|
+
BASIC_ROW.map{|note| @prime_row.transpose(note) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def inversions
|
15
|
+
BASIC_ROW.map{|note| @prime_row.transpose(note).inversion }
|
16
|
+
end
|
17
|
+
|
18
|
+
def retrogrades
|
19
|
+
BASIC_ROW.map{|note| @prime_row.transpose(note).retrograde }
|
20
|
+
end
|
21
|
+
|
22
|
+
def retrograde_inversions
|
23
|
+
BASIC_ROW.map{|note| @prime_row.transpose(note).retrograde_inversion }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/webern/row.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Webern
|
2
|
+
class Row < Array
|
3
|
+
def initialize(*_row)
|
4
|
+
@row = _row
|
5
|
+
check_for_valid_row(@row)
|
6
|
+
@row = process_strings if @row.any?{|element| element.is_a?(String) }
|
7
|
+
@row = complete_row[0..11]
|
8
|
+
replace @row
|
9
|
+
end
|
10
|
+
|
11
|
+
def retrograde; Row.new *reverse; end
|
12
|
+
|
13
|
+
def inversion
|
14
|
+
Row.new *map{|note| (12 - note) % 12 }
|
15
|
+
end
|
16
|
+
|
17
|
+
def retrograde_inversion
|
18
|
+
Row.new *inversion.retrograde
|
19
|
+
end
|
20
|
+
|
21
|
+
def transpose(interval)
|
22
|
+
Row.new *map{|note| (note + interval) % 12 }
|
23
|
+
end
|
24
|
+
|
25
|
+
def complete_row
|
26
|
+
return @row if @row.size == 12
|
27
|
+
_remainder = Array(0..11) - @row
|
28
|
+
[@row, _remainder].flatten
|
29
|
+
end
|
30
|
+
|
31
|
+
def process_strings
|
32
|
+
full_string = @row.join("").split("")
|
33
|
+
_letters = full_string.uniq[0..11]
|
34
|
+
_letters.generate_row_from_letters
|
35
|
+
end
|
36
|
+
|
37
|
+
def check_for_valid_row(elements)
|
38
|
+
raise InvalidRow unless row_is_valid_numbers? or row_is_strings?
|
39
|
+
end
|
40
|
+
|
41
|
+
def row_is_valid_numbers?
|
42
|
+
@row.all?{|element| element.is_a?(Fixnum) } and (@row - Array(0..11)).empty?
|
43
|
+
end
|
44
|
+
|
45
|
+
def row_is_strings?
|
46
|
+
@row.all?{|element| element.is_a?(String) }
|
47
|
+
end
|
48
|
+
|
49
|
+
def zero_row
|
50
|
+
transpose(12-self[0])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/webern.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
$:.unshift File.dirname(__FILE__) + "/webern"
|
3
|
+
|
4
|
+
%w{ core_ext lilypond_builder matrix row }.each {|file| require file }
|
5
|
+
|
6
|
+
module Webern
|
7
|
+
class << self
|
8
|
+
attr_accessor :prime_row
|
9
|
+
end
|
10
|
+
|
11
|
+
def Webern.new(*row_elements)
|
12
|
+
@prime_row = Row.new(*row_elements).zero_row
|
13
|
+
@m = Matrix.new(@prime_row)
|
14
|
+
LilypondBuilder.generate_file(@m)
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
InvalidRow = Class.new(Exception)
|
19
|
+
end
|
data/spec/array_spec.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
describe "Array" do
|
2
|
+
describe "is_all_integers?" do
|
3
|
+
before do
|
4
|
+
@all_ints = %w{0 1 2 3 4 5 6 7 8 9 10 11}
|
5
|
+
@no_ints = %w{a b c d e f g h i j k}
|
6
|
+
@mixed = %w{a 1 b 2 c 3 d 4 5 6 7}
|
7
|
+
@bad_input = [{1 => 2}, [1,2,3], :"45"]
|
8
|
+
end
|
9
|
+
it "should return true when all elements are strings of integers" do
|
10
|
+
@all_ints.is_all_integers?.should be_true
|
11
|
+
end
|
12
|
+
it "should return false when no elements are strings of integers" do
|
13
|
+
@no_ints.is_all_integers?.should_not be_true
|
14
|
+
end
|
15
|
+
it "should return false when only some elements are strings of integers" do
|
16
|
+
@mixed.is_all_integers?.should_not be_true
|
17
|
+
end
|
18
|
+
it "should return false when some elements do not have a :to_i method" do
|
19
|
+
@bad_input.is_all_integers?.should_not be_true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
if system("lilypond --version")
|
2
|
+
describe "LilypondBuilder" do
|
3
|
+
it "should find the current lilypond version" do
|
4
|
+
Webern::LilypondBuilder.current_lilypond_version.should =~ /\d+\.\d+\.\d+/
|
5
|
+
end
|
6
|
+
it "should, by default, have 0 == c" do
|
7
|
+
Webern::LilypondBuilder.zero_note = "c"
|
8
|
+
end
|
9
|
+
describe "converting rows into lilypond" do
|
10
|
+
before { @row = Webern::Row.new(0,1,2,3,4,5,6,7,8,9,10,11) }
|
11
|
+
it "should be correctly converted by default to 'c cs d ef e f fs g af a bf b'" do
|
12
|
+
Webern::LilypondBuilder.convert_row(@row).should == "c cs d ef e f fs g af a bf b"
|
13
|
+
end
|
14
|
+
describe "when the zero_note is shifted" do
|
15
|
+
before { Webern::LilypondBuilder.zero_note = "d" }
|
16
|
+
it "should correct convert the chromatic scale to 'd ef e f fs g af a bf b c cs'" do
|
17
|
+
Webern::LilypondBuilder.convert_row(@row).should == "d ef e f fs g af a bf b c cs"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
describe "generating lilypond file" do
|
22
|
+
before do
|
23
|
+
@row = Webern::Row.new(*Array(0..11))
|
24
|
+
@matrix = Webern::Matrix.new(@row)
|
25
|
+
@file_path = File.join(File.dirname(__FILE__), "..", "matrix.ly")
|
26
|
+
puts Webern::LilypondBuilder.generate_file(@matrix)
|
27
|
+
end
|
28
|
+
after do
|
29
|
+
File.delete(@file_path) if File.exists?(@file_path)
|
30
|
+
end
|
31
|
+
it "should create the file" do
|
32
|
+
File.exists?(@file_path).should be_true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
else
|
37
|
+
describe "LilypondBuilder" do
|
38
|
+
it "needs Lilypond to be installed. Check out http://www.lilypond.org"
|
39
|
+
end
|
40
|
+
end
|
data/spec/matrix_spec.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
describe "Matrix" do
|
2
|
+
before { @m = Webern::Matrix.new(Webern::Row.new(0,1,2,3,4,5,6,7,8,9,10,11)) }
|
3
|
+
it "should have the correct prime row" do
|
4
|
+
@m.prime_row.should == Webern::Row.new(*Array(0..11))
|
5
|
+
end
|
6
|
+
it "should have the correct primes" do
|
7
|
+
@m.primes[0].should == @m.prime_row
|
8
|
+
@m.primes[3].should == @m.prime_row.transpose(3)
|
9
|
+
end
|
10
|
+
it "should have the correct inversions" do
|
11
|
+
@m.inversions[0].should == @m.prime_row.inversion
|
12
|
+
@m.inversions[6].should == @m.prime_row.inversion.transpose(6)
|
13
|
+
end
|
14
|
+
it "should have the correct retrogrades" do
|
15
|
+
@m.retrogrades[0].should == @m.prime_row.retrograde
|
16
|
+
@m.retrogrades[8].should == @m.prime_row.retrograde.transpose(8)
|
17
|
+
end
|
18
|
+
it "should have the correct retrograde inversions" do
|
19
|
+
@m.retrograde_inversions[0].should == @m.prime_row.retrograde_inversion
|
20
|
+
@m.retrograde_inversions[1].should == @m.prime_row.retrograde_inversion.transpose(11)
|
21
|
+
end
|
22
|
+
end
|
data/spec/row_spec.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
describe "Row" do
|
2
|
+
describe "a basic row" do
|
3
|
+
before { @row = Webern::Row.new(*Array(0..11)) }
|
4
|
+
it "should create the correct retrograde: [11,10,9,8,7,6,5,4,3,2,1,0]" do
|
5
|
+
@row.retrograde.should == Array(0..11).reverse
|
6
|
+
end
|
7
|
+
it "should create the correct inversion: [0,11,10,9,8,7,6,5,4,3,2,1]" do
|
8
|
+
@row.inversion.should == [0,11,10,9,8,7,6,5,4,3,2,1]
|
9
|
+
end
|
10
|
+
it "should create the correct retrograde inversion: [1,2,3,4,5,6,7,8,9,10,11,0]" do
|
11
|
+
@row.retrograde_inversion.should == [1,2,3,4,5,6,7,8,9,10,11,0]
|
12
|
+
end
|
13
|
+
it "should transpose correctly" do
|
14
|
+
@row.transpose(2).should == [2,3,4,5,6,7,8,9,10,11,0,1]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
describe "a more complex row" do
|
18
|
+
before { @row = Webern::Row.new(0,11,8,2,4,1,3,10,7,5,9,6) }
|
19
|
+
it "should create the correct retrograde: [6,9,5,7,10,3,1,4,2,8,11,0]" do
|
20
|
+
@row.retrograde.should == [6,9,5,7,10,3,1,4,2,8,11,0]
|
21
|
+
end
|
22
|
+
it "should create the correct inversion: [0,1,4,10,8,11,9,2,5,7,3,6]" do
|
23
|
+
@row.inversion.should == [0,1,4,10,8,11,9,2,5,7,3,6]
|
24
|
+
end
|
25
|
+
it "should create the correct retrograde inversion: [7,3,7,5,2,9,11,8,10,4,1,0]" do
|
26
|
+
@row.retrograde_inversion.should == [6,3,7,5,2,9,11,8,10,4,1,0]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/spec/webern_spec.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
def test_with_full_row(row, expected_result)
|
4
|
+
it "should return #{expected_result.inspect} for #{row.inspect}" do
|
5
|
+
Webern.new(*row).prime_row.should == expected_result
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
alias :test_with_incomplete_row :test_with_full_row
|
10
|
+
alias :test_with_complete_string :test_with_full_row
|
11
|
+
alias :test_with_incomplete_string :test_with_full_row
|
12
|
+
|
13
|
+
describe "Webern" do
|
14
|
+
describe "parsing complete rows" do
|
15
|
+
# beginning with 0
|
16
|
+
test_with_full_row(Array(0..11), Array(0..11))
|
17
|
+
test_with_full_row([0,11,10,9,8,7,6,5,4,3,2,1], [0,11,10,9,8,7,6,5,4,3,2,1])
|
18
|
+
|
19
|
+
# not beginning with 0
|
20
|
+
test_with_full_row([1,2,3,9,7,8,6,4,5,0,11,10], [0,1,2,8,6,7,5,3,4,11,10,9])
|
21
|
+
test_with_full_row(Array(0..11).reverse, [0,11,10,9,8,7,6,5,4,3,2,1])
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "parsing incomplete rows" do
|
25
|
+
# beginning with 0
|
26
|
+
test_with_incomplete_row(Array(0..6), Array(0..11))
|
27
|
+
test_with_incomplete_row([0,11,10,9,8,7], [0,11,10,9,8,7,1,2,3,4,5,6])
|
28
|
+
|
29
|
+
# not beginning with 0
|
30
|
+
test_with_incomplete_row([1,2,3,9,7,8,6], [0,1,2,8,6,7,5,11,3,4,9,10])
|
31
|
+
test_with_incomplete_row([11,10,9,8,7,6], [0,11,10,9,8,7,1,2,3,4,5,6])
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "parsing invalid rows" do
|
35
|
+
it "should raise an error for [1,2,3,4,5,6,7,8,9,10,11,12]" do
|
36
|
+
lambda { Webern.new(*Array(1..12)) }.should raise_error Webern::InvalidRow
|
37
|
+
end
|
38
|
+
it "should raise an error for [-1,0,1,2,3]" do
|
39
|
+
lambda { Webern.new(*Array(-1..3)) }.should raise_error Webern::InvalidRow
|
40
|
+
end
|
41
|
+
it "should raise an error for [0,1,2,3,4.5]" do
|
42
|
+
lambda { Webern.new(0,1,2,3,4.5) }.should raise_error Webern::InvalidRow
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "parsing strings that provide a full row" do
|
47
|
+
test_with_complete_string(%w{a b c d e f g h i j k l}, Array(0..11))
|
48
|
+
test_with_complete_string(%w{michael rowe berkowitz}, [0,9,6,8,4,7,11,2,1,3,5,10])
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "parsing strings that do not provide a full row" do
|
52
|
+
test_with_incomplete_string(%w{a b c d e f g}, Array(0..11))
|
53
|
+
test_with_incomplete_string(%w{michael rowe}, [0,10,7,9,6,8,11,2,1,3,4,5])
|
54
|
+
end
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: webern
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Michael Berkowitz
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-04-22 00:00:00 -04:00
|
18
|
+
default_executable: webern
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Taking a 12-tone row generated from user input Webern will create the full matrix based upon this row, and then output all 48 possible rows created by that matrix to a .pdf file using the LilyPond notational language.
|
22
|
+
email: michael.berkowitz@gmail.com
|
23
|
+
executables:
|
24
|
+
- webern
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- LICENSE
|
29
|
+
- README.md
|
30
|
+
files:
|
31
|
+
- .document
|
32
|
+
- .gitignore
|
33
|
+
- CHANGELOG.md
|
34
|
+
- Gemfile
|
35
|
+
- LICENSE
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- VERSION
|
39
|
+
- bin/webern
|
40
|
+
- lib/core_ext.rb
|
41
|
+
- lib/webern.rb
|
42
|
+
- lib/webern/lilypond_builder.rb
|
43
|
+
- lib/webern/matrix.rb
|
44
|
+
- lib/webern/row.rb
|
45
|
+
- spec/array_spec.rb
|
46
|
+
- spec/helper.rb
|
47
|
+
- spec/lilypond_builder_spec.rb
|
48
|
+
- spec/matrix_spec.rb
|
49
|
+
- spec/row_spec.rb
|
50
|
+
- spec/webern_spec.rb
|
51
|
+
has_rdoc: true
|
52
|
+
homepage: http://github.com/mikowitz/webern
|
53
|
+
licenses: []
|
54
|
+
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --charset=UTF-8
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 1.3.6
|
78
|
+
signing_key:
|
79
|
+
specification_version: 3
|
80
|
+
summary: Creates a .pdf reference sheet for all 12-tone rows generated from a given prime row's matrix.
|
81
|
+
test_files:
|
82
|
+
- spec/array_spec.rb
|
83
|
+
- spec/helper.rb
|
84
|
+
- spec/lilypond_builder_spec.rb
|
85
|
+
- spec/matrix_spec.rb
|
86
|
+
- spec/row_spec.rb
|
87
|
+
- spec/webern_spec.rb
|