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 ADDED
@@ -0,0 +1,4 @@
1
+ lib/**/*.rb
2
+ -
3
+ CHANGELOG.md
4
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.ly
2
+ *.pdf
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ### 0.2.0 : 04/22/10
2
+
3
+ * Reimplementation of code.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "spec"
4
+ gem "yard"
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
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.dirname(__FILE__) + '/../lib/webern'
4
+ require 'optparse'
5
+
6
+ if ARGV.is_all_integers?
7
+ Webern.new(*ARGV.map(&:to_i))
8
+ else
9
+ Webern.new(*ARGV)
10
+ end
data/lib/core_ext.rb ADDED
@@ -0,0 +1,11 @@
1
+ class Array
2
+ def is_all_integers?
3
+ self.all?{|element| element.to_i.to_s == element }
4
+ rescue Exception
5
+ false
6
+ end
7
+
8
+ def generate_row_from_letters
9
+ self.map{|element| self.sort.index(element) }
10
+ end
11
+ end
@@ -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
@@ -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,5 @@
1
+ require 'spec'
2
+
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
5
+ require 'webern'
@@ -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
@@ -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
@@ -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