webern 0.2.0 → 0.3.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/.gitignore +19 -1
- data/Gemfile +3 -3
- data/Guardfile +8 -0
- data/README.md +30 -29
- data/Rakefile +4 -83
- data/lib/webern.rb +2 -16
- data/lib/webern/formatters/base.rb +15 -0
- data/lib/webern/formatters/lilypond.rb +43 -0
- data/lib/webern/formatters/pdf.rb +18 -0
- data/lib/webern/formatters/text.rb +34 -0
- data/lib/webern/row.rb +21 -31
- data/lib/webern/version.rb +3 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/webern/row_spec.rb +73 -0
- data/spec/webern_spec.rb +8 -53
- data/webern.gemspec +30 -0
- metadata +174 -66
- data/.document +0 -4
- data/CHANGELOG.md +0 -3
- data/LICENSE +0 -20
- data/VERSION +0 -1
- data/bin/webern +0 -10
- data/lib/core_ext.rb +0 -11
- data/lib/webern/lilypond_builder.rb +0 -62
- data/lib/webern/matrix.rb +0 -26
- data/spec/array_spec.rb +0 -22
- data/spec/helper.rb +0 -5
- data/spec/lilypond_builder_spec.rb +0 -40
- data/spec/matrix_spec.rb +0 -22
- data/spec/row_spec.rb +0 -29
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
gem
|
4
|
-
|
3
|
+
# Specify your gem's dependencies in webern.gemspec
|
4
|
+
gemspec
|
data/Guardfile
ADDED
data/README.md
CHANGED
@@ -1,50 +1,51 @@
|
|
1
|
-
#
|
1
|
+
# Webern
|
2
2
|
|
3
|
-
|
3
|
+
Transforms user input into a complete 12-tone row and computes all 48 (at most) possible rows that result from the matrix of that row.
|
4
4
|
|
5
|
-
|
5
|
+
Possible outputs:
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
row, and then output all 48 possible rows created by that matrix to a .pdf file using the LilyPond notational
|
11
|
-
language.
|
7
|
+
* text
|
8
|
+
* pdf
|
9
|
+
* lilypond
|
12
10
|
|
13
11
|
## Installation
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
~$ gem install gemcutter
|
13
|
+
Add this line to your application's Gemfile:
|
18
14
|
|
19
|
-
|
15
|
+
gem 'webern'
|
20
16
|
|
21
|
-
|
17
|
+
And then execute:
|
22
18
|
|
23
|
-
|
19
|
+
$ bundle
|
24
20
|
|
25
|
-
|
21
|
+
Or install it yourself as:
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
No other gems are required, but you do need [LilyPond][lilypond] to generate the .pdf file.
|
23
|
+
$ gem install webern
|
30
24
|
|
31
25
|
## Usage
|
32
26
|
|
33
|
-
|
27
|
+
Create a row of the numbers 0 - 11
|
28
|
+
|
29
|
+
row = Webern::Row.new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
|
34
30
|
|
35
|
-
|
36
|
-
|
37
|
-
~$ webern michael berkowitz
|
31
|
+
You do not need to provide a full row. `Webern` will fill out the missing
|
32
|
+
numbers by adding them in ascending order to the end of the provided row.
|
38
33
|
|
39
|
-
|
34
|
+
row = Webern::Row.new(5, 4, 8, 7, 10, 11, 3, 2) #=> [5, 4, 8, 7, 10, 11, 3, 2, 0, 1, 6, 9]
|
40
35
|
|
41
|
-
|
36
|
+
Then choose a format in which to output either the matrix (text or pdf) or all
|
37
|
+
possible rows resulting from that matrix (lilypond).
|
42
38
|
|
43
|
-
|
39
|
+
Webern::Formatters.Text.new(row).print_to_file('filename.txt)
|
40
|
+
Webern::Formatters.Pdf.new(row).print_to_file('filename.pdf)
|
41
|
+
Webern::Formatters.Lilypond.new(row).print_to_file('filename.ly')
|
44
42
|
|
45
|
-
|
43
|
+
The `lilypond` executable is required in order to convert the resulting `filename.ly` file to PDF.
|
46
44
|
|
47
|
-
|
45
|
+
## Contributing
|
48
46
|
|
49
|
-
|
50
|
-
|
47
|
+
1. Fork it
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create new Pull Request
|
data/Rakefile
CHANGED
@@ -1,85 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require '
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
|
4
|
-
|
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
|
4
|
+
RSpec::Core::RakeTask.new('spec')
|
19
5
|
|
20
|
-
|
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
|
6
|
+
task default: :spec
|
data/lib/webern.rb
CHANGED
@@ -1,19 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
%w{ core_ext lilypond_builder matrix row }.each {|file| require file }
|
1
|
+
require "webern/version"
|
2
|
+
Dir[File.dirname(__FILE__) + '/**/*.rb'].each {|file| require file}
|
5
3
|
|
6
4
|
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
5
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Webern
|
2
|
+
module Formatters
|
3
|
+
class Base
|
4
|
+
PITCH_CLASSES = %w{ C C# D Eb E F F# G Ab A Bb B }
|
5
|
+
def initialize(prime_row, show_pitch_classes=true)
|
6
|
+
@prime_row = prime_row
|
7
|
+
@show_pitch_classes = show_pitch_classes
|
8
|
+
end
|
9
|
+
|
10
|
+
def pitch_value(n)
|
11
|
+
@show_pitch_classes ? PITCH_CLASSES[n] : n.to_s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Webern
|
2
|
+
module Formatters
|
3
|
+
class Lilypond < Base
|
4
|
+
def write_to_file(filename)
|
5
|
+
File.open(filename, 'w') do |f|
|
6
|
+
f << LILYPOND_HEADER
|
7
|
+
f << "rows = {\n"
|
8
|
+
f << "\\time 12/4\n"
|
9
|
+
f << "\\override Staff.Stem #'transparent = ##t\n"
|
10
|
+
{p: :prime, i: :inversion, r: :retrograde, ri: :retrograde_inversion}.each do |key, transformation|
|
11
|
+
(0..11).each do |transposition|
|
12
|
+
f << "\\mark \"#{key}#{transposition}\" "
|
13
|
+
f << @prime_row.send(transformation).zero.transpose(transposition).map{|n| lilypond_pitch(n) }.join(' ') + "\n"
|
14
|
+
end
|
15
|
+
f << "\\bar \"||\"\n"
|
16
|
+
end
|
17
|
+
f << "}\n"
|
18
|
+
f << LILYPOND_SCORE_BLOCK
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def lilypond_pitch(n)
|
23
|
+
%w{ c'' cs'' d'' ef'' e'' f' fs' g' af' a' bf' b' }[n]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
LILYPOND_HEADER = <<-pond
|
30
|
+
\\version "2.16.2"
|
31
|
+
\\include "english.ly"
|
32
|
+
|
33
|
+
#(set-global-staff-size 13)
|
34
|
+
|
35
|
+
pond
|
36
|
+
|
37
|
+
LILYPOND_SCORE_BLOCK = <<-pond
|
38
|
+
\\score {
|
39
|
+
<<
|
40
|
+
\\new Staff \\rows
|
41
|
+
>>
|
42
|
+
}
|
43
|
+
pond
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'prawn'
|
2
|
+
|
3
|
+
module Webern
|
4
|
+
module Formatters
|
5
|
+
class Pdf < Base
|
6
|
+
def write_to_file(filename)
|
7
|
+
data = @prime_row.inversion.map do |i|
|
8
|
+
@prime_row.transpose(i).map do |n|
|
9
|
+
pitch_value(n)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
Prawn::Document.generate(filename) do |pdf|
|
13
|
+
pdf.table data, cell_style: { width: 42, height: 42, align: :center, padding: 10}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Webern
|
2
|
+
module Formatters
|
3
|
+
class Text < Base
|
4
|
+
def draw
|
5
|
+
output($stdout)
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
def write_to_file(filename)
|
10
|
+
File.open(filename, 'w') do |f|
|
11
|
+
output(f)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def output(target)
|
18
|
+
@prime_row.inversion.each do |i|
|
19
|
+
target << border_row
|
20
|
+
target << empty_row
|
21
|
+
target << @prime_row.transpose(i).map{|n| pitch_cell(n) }.join + "|\n"
|
22
|
+
target << empty_row
|
23
|
+
end
|
24
|
+
target << border_row
|
25
|
+
end
|
26
|
+
|
27
|
+
def border_row; ('|---------' * 12) + "|\n"; end
|
28
|
+
def empty_row; ('| ' * 12) + "|\n"; end
|
29
|
+
def pitch_cell(n)
|
30
|
+
'| %s ' % (pitch_value(n)).rjust(2)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/webern/row.rb
CHANGED
@@ -1,53 +1,43 @@
|
|
1
1
|
module Webern
|
2
2
|
class Row < Array
|
3
|
-
def initialize(*
|
4
|
-
@row =
|
5
|
-
|
6
|
-
@row = process_strings if @row.any?{|element| element.is_a?(String) }
|
7
|
-
@row = complete_row[0..11]
|
8
|
-
replace @row
|
3
|
+
def initialize(*row)
|
4
|
+
@row = row
|
5
|
+
replace complete_row
|
9
6
|
end
|
10
7
|
|
11
|
-
def
|
12
|
-
|
13
|
-
def inversion
|
14
|
-
Row.new *map{|note| (12 - note) % 12 }
|
8
|
+
def zero!
|
9
|
+
replace zero
|
15
10
|
end
|
16
11
|
|
17
|
-
def
|
18
|
-
Row.new *
|
12
|
+
def prime
|
13
|
+
Row.new *self
|
19
14
|
end
|
20
15
|
|
21
|
-
def
|
22
|
-
Row.new *map{|
|
16
|
+
def inversion
|
17
|
+
Row.new *self.map{|i| (12 - i) % 12}
|
23
18
|
end
|
24
19
|
|
25
|
-
def
|
26
|
-
|
27
|
-
_remainder = Array(0..11) - @row
|
28
|
-
[@row, _remainder].flatten
|
20
|
+
def retrograde
|
21
|
+
Row.new *self.reverse
|
29
22
|
end
|
30
23
|
|
31
|
-
def
|
32
|
-
|
33
|
-
_letters = full_string.uniq[0..11]
|
34
|
-
_letters.generate_row_from_letters
|
24
|
+
def retrograde_inversion
|
25
|
+
Row.new *self.retrograde.inversion
|
35
26
|
end
|
36
27
|
|
37
|
-
def
|
38
|
-
|
28
|
+
def transpose(distance)
|
29
|
+
Row.new *self.map{|i| (i + distance) % 12 }
|
39
30
|
end
|
40
31
|
|
41
|
-
def
|
42
|
-
|
32
|
+
def zero
|
33
|
+
Row.new *self.map{|i| (i + 12 - self[0]) % 12}
|
43
34
|
end
|
44
35
|
|
45
|
-
|
46
|
-
@row.all?{|element| element.is_a?(String) }
|
47
|
-
end
|
36
|
+
private
|
48
37
|
|
49
|
-
def
|
50
|
-
|
38
|
+
def complete_row
|
39
|
+
missing = Array(0..11) - @row
|
40
|
+
@row + missing
|
51
41
|
end
|
52
42
|
end
|
53
43
|
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Webern::Row do
|
4
|
+
describe 'complete integer row' do
|
5
|
+
# Concerto for Nine Instruments, Op. 24
|
6
|
+
let(:row) { create_row(11, 10, 2, 3, 7, 6, 8, 4, 5, 0, 1, 9) }
|
7
|
+
|
8
|
+
describe '#zero' do
|
9
|
+
it 'should return the row normalized to start on 0' do
|
10
|
+
expect(row.zero).to eq [0, 11, 3, 4, 8, 7, 9, 5, 6, 1, 2, 10]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'transformations' do
|
15
|
+
before { row.zero! }
|
16
|
+
it 'should invert correctly' do
|
17
|
+
expect(row.inversion).to eq [0, 1, 9, 8, 4, 5, 3, 7, 6, 11, 10, 2]
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should retrograde correctly' do
|
21
|
+
expect(row.retrograde).to eq [10, 2, 1, 6, 5, 9, 7, 8, 4, 3, 11, 0]
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should retrograde-inversion correctly' do
|
25
|
+
expect(row.retrograde_inversion).to eq [2, 10, 11, 6, 7, 3, 5, 4, 8, 9, 1, 0]
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should transpose correctly' do
|
29
|
+
expect(row.transpose(2)).to eq [2, 1, 5, 6, 10, 9, 11, 7, 8, 3, 4, 0]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'incomplete integer row' do
|
35
|
+
# String Quartet, Op. 28
|
36
|
+
let(:row) { create_row(10, 9, 0, 11, 3, 4, 1, 2) } # actual ending: 6, 5, 8, 7
|
37
|
+
|
38
|
+
describe 'row completion' do
|
39
|
+
it 'should complete the row in ascending order of remaining pitches' do
|
40
|
+
expect(row).to eq [10, 9, 0, 11, 3, 4, 1, 2, 5, 6, 7, 8]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#zero' do
|
45
|
+
it 'should return the row normalized to start on 0' do
|
46
|
+
expect(row.zero).to eq [0, 11, 2, 1, 5, 6, 3, 4, 7, 8, 9, 10]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'transformations' do
|
51
|
+
before { row.zero! }
|
52
|
+
it 'should invert correctly' do
|
53
|
+
expect(row.inversion).to eq [0, 1, 10, 11, 7, 6, 9, 8, 5, 4, 3, 2]
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should retrograde correctly' do
|
57
|
+
expect(row.retrograde).to eq [10, 9, 8, 7, 4, 3 ,6, 5, 1, 2, 11, 0]
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should retrograde-inversion correctly' do
|
61
|
+
expect(row.retrograde_inversion).to eq [2, 3, 4, 5, 8, 9, 6, 7, 11, 10, 1, 0]
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should transpose correctly' do
|
65
|
+
expect(row.transpose(2)).to eq [2, 1, 4, 3, 7, 8, 5, 6, 9, 10, 11, 0]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def create_row(*args)
|
71
|
+
Webern::Row.new(*args)
|
72
|
+
end
|
73
|
+
end
|
data/spec/webern_spec.rb
CHANGED
@@ -1,55 +1,10 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
|
4
|
-
it
|
5
|
-
Webern.new(
|
6
|
-
|
7
|
-
|
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])
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Webern do
|
4
|
+
it 'should output correctly' do
|
5
|
+
row = Webern::Row.new(11, 10, 2, 3, 7, 6, 8, 4, 5, 0, 1, 9)
|
6
|
+
Webern::Formatters::Text.new(row, false).write_to_file('row.txt')
|
7
|
+
Webern::Formatters::Pdf.new(row).write_to_file('row.pdf')
|
8
|
+
Webern::Formatters::Lilypond.new(row).write_to_file('lilypond-row.ly')
|
54
9
|
end
|
55
10
|
end
|
data/webern.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'webern/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "webern"
|
8
|
+
spec.version = Webern::VERSION
|
9
|
+
spec.authors = ["Michael Berkowitz"]
|
10
|
+
spec.email = ["michael.berkowitz@gmail.com"]
|
11
|
+
spec.description = %q{Transforms user input into a complete 12-tone row and computes all 48 (at most) possible rows that result from the matrix of that row.}
|
12
|
+
spec.summary = %q{Calculates all 48 possible 12-tone rows from the given input}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'prawn'
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency "guard"
|
27
|
+
spec.add_development_dependency "guard-rspec"
|
28
|
+
spec.add_development_dependency "terminal-notifier-guard"
|
29
|
+
spec.add_development_dependency "rb-fsevent"
|
30
|
+
end
|
metadata
CHANGED
@@ -1,87 +1,195 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: webern
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 2
|
8
|
-
- 0
|
9
|
-
version: 0.2.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Michael Berkowitz
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
-
|
12
|
+
date: 2013-04-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: prawn
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.3'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.3'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: guard
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: guard-rspec
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: terminal-notifier-guard
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rb-fsevent
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
description: Transforms user input into a complete 12-tone row and computes all 48
|
143
|
+
(at most) possible rows that result from the matrix of that row.
|
144
|
+
email:
|
145
|
+
- michael.berkowitz@gmail.com
|
146
|
+
executables: []
|
25
147
|
extensions: []
|
26
|
-
|
27
|
-
|
28
|
-
- LICENSE
|
29
|
-
- README.md
|
30
|
-
files:
|
31
|
-
- .document
|
148
|
+
extra_rdoc_files: []
|
149
|
+
files:
|
32
150
|
- .gitignore
|
33
|
-
- CHANGELOG.md
|
34
151
|
- Gemfile
|
35
|
-
-
|
152
|
+
- Guardfile
|
153
|
+
- LICENSE.txt
|
36
154
|
- README.md
|
37
155
|
- Rakefile
|
38
|
-
- VERSION
|
39
|
-
- bin/webern
|
40
|
-
- lib/core_ext.rb
|
41
156
|
- lib/webern.rb
|
42
|
-
- lib/webern/
|
43
|
-
- lib/webern/
|
157
|
+
- lib/webern/formatters/base.rb
|
158
|
+
- lib/webern/formatters/lilypond.rb
|
159
|
+
- lib/webern/formatters/pdf.rb
|
160
|
+
- lib/webern/formatters/text.rb
|
44
161
|
- lib/webern/row.rb
|
45
|
-
-
|
46
|
-
- spec/
|
47
|
-
- spec/
|
48
|
-
- spec/matrix_spec.rb
|
49
|
-
- spec/row_spec.rb
|
162
|
+
- lib/webern/version.rb
|
163
|
+
- spec/spec_helper.rb
|
164
|
+
- spec/webern/row_spec.rb
|
50
165
|
- spec/webern_spec.rb
|
51
|
-
|
52
|
-
homepage:
|
53
|
-
licenses:
|
54
|
-
|
166
|
+
- webern.gemspec
|
167
|
+
homepage: ''
|
168
|
+
licenses:
|
169
|
+
- MIT
|
55
170
|
post_install_message:
|
56
|
-
rdoc_options:
|
57
|
-
|
58
|
-
require_paths:
|
171
|
+
rdoc_options: []
|
172
|
+
require_paths:
|
59
173
|
- lib
|
60
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
requirements:
|
69
|
-
- -
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
|
72
|
-
- 0
|
73
|
-
version: "0"
|
174
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
175
|
+
none: false
|
176
|
+
requirements:
|
177
|
+
- - ! '>='
|
178
|
+
- !ruby/object:Gem::Version
|
179
|
+
version: '0'
|
180
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
|
+
none: false
|
182
|
+
requirements:
|
183
|
+
- - ! '>='
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
74
186
|
requirements: []
|
75
|
-
|
76
187
|
rubyforge_project:
|
77
|
-
rubygems_version: 1.
|
188
|
+
rubygems_version: 1.8.23
|
78
189
|
signing_key:
|
79
190
|
specification_version: 3
|
80
|
-
summary:
|
81
|
-
test_files:
|
82
|
-
- spec/
|
83
|
-
- spec/
|
84
|
-
- spec/lilypond_builder_spec.rb
|
85
|
-
- spec/matrix_spec.rb
|
86
|
-
- spec/row_spec.rb
|
191
|
+
summary: Calculates all 48 possible 12-tone rows from the given input
|
192
|
+
test_files:
|
193
|
+
- spec/spec_helper.rb
|
194
|
+
- spec/webern/row_spec.rb
|
87
195
|
- spec/webern_spec.rb
|
data/.document
DELETED
data/CHANGELOG.md
DELETED
data/LICENSE
DELETED
@@ -1,20 +0,0 @@
|
|
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/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.2.0
|
data/bin/webern
DELETED
data/lib/core_ext.rb
DELETED
@@ -1,62 +0,0 @@
|
|
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
|
data/lib/webern/matrix.rb
DELETED
@@ -1,26 +0,0 @@
|
|
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/spec/array_spec.rb
DELETED
@@ -1,22 +0,0 @@
|
|
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
DELETED
@@ -1,40 +0,0 @@
|
|
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
DELETED
@@ -1,22 +0,0 @@
|
|
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
DELETED
@@ -1,29 +0,0 @@
|
|
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
|