mikowitz-webern 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ 2008-11-16
2
+
3
+ Development started. Base dev files created.
@@ -0,0 +1,12 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/webern
6
+ lib/webern.rb
7
+ lib/webern/lilypond_builder.rb
8
+ lib/webern/matrix.rb
9
+ lib/webern/version.rb
10
+ lib/webern/webern.rb
11
+ test/test_webern.rb
12
+ webern.gemspec
@@ -0,0 +1,64 @@
1
+ = Webern
2
+
3
+ http://github.com/mikowitz/webern
4
+
5
+ == DESCRIPTION:
6
+
7
+ Taking a 12-tone row generated from user input (see SYNOPSIS below), Webern will create the full matrix based upon this row, and then output all 48 possible rows created by that matrix out to a .pdf file using the LilyPond notational language.
8
+
9
+
10
+ Rake Tasks Provided:
11
+
12
+ * clear_ly_files - Removes rows.ly, rows.ps, and rows.pdf
13
+ * update_lib - Updates your lib/project_name.rb file to include all files in your lib/project_name/ folder
14
+ * update_manifest - Updates the gems Manifest.txt file to include any added files
15
+
16
+ == FEATURES/PROBLEMS:
17
+
18
+ * Not yet packaged as an installable gem. Coming soon, though. In the meantime, see the INSTALL section below.
19
+
20
+ == SYNOPSIS:
21
+
22
+ Webern can accept three different types of input.
23
+
24
+ * A full 12 tone row:
25
+ $ webern 9 1 4 7 8 2 0 10 5 6 11 3
26
+
27
+ * An incomplete row, in which case the missing numbers will be added sequentially following what you have provided. See Webern::Webern.finish_partial_row:
28
+ $ webern 0 6 10 9 4 7 (1 2 3 5 8 11 will be added by Webern)
29
+
30
+ * A string, which will be converted to a 12-tone row. See Webern::Webern.make_row_from_string:
31
+ $ webern michael berkowitz
32
+
33
+ == REQUIREMENTS:
34
+
35
+ * No other gems, but you do need lilypond (http://lilypond.org/web/) to generate the .pdf file.
36
+
37
+ == INSTALL:
38
+
39
+ * Not packaged as a gem yet. Run rake install_gem from project root to install as a gem on your computer.
40
+
41
+ == LICENSE:
42
+
43
+ (The MIT License)
44
+
45
+ Copyright (c) 2008 FIX
46
+
47
+ Permission is hereby granted, free of charge, to any person obtaining
48
+ a copy of this software and associated documentation files (the
49
+ 'Software'), to deal in the Software without restriction, including
50
+ without limitation the rights to use, copy, modify, merge, publish,
51
+ distribute, sublicense, and/or sell copies of the Software, and to
52
+ permit persons to whom the Software is furnished to do so, subject to
53
+ the following conditions:
54
+
55
+ The above copyright notice and this permission notice shall be
56
+ included in all copies or substantial portions of the Software.
57
+
58
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
59
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
60
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
61
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
62
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
63
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
64
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+ require 'fileutils'
4
+ require File.dirname(__FILE__) + '/lib/webern.rb'
5
+
6
+ PKG_NAME = 'webern'
7
+ PKG_VER = Webern::Version::STRING
8
+
9
+ Hoe.new('webern', Webern::Version::STRING) do |p|
10
+ p.name = PKG_NAME
11
+ p.version = PKG_VER
12
+ p.developer('Michael Berkowitz', 'michael.berkowitz@gmail.com')
13
+ p.email = 'michael.berkowitz@gmail.com'
14
+ p.author = 'Michael Berkowitz'
15
+ p.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 out to a .pdf file using the LilyPond notational language. }
16
+ end
17
+
18
+ desc "Updates Manifest.txt"
19
+ task :update_manifest do
20
+ files = Dir.glob('**/*') - ["bin", "lib", "lib/webern", "test"]
21
+ puts "Cleaning gem. Removing extraneous pkg and doc files that should not be included in your Manifest.txt file."
22
+ `rake clean`
23
+ File.open('Manifest.txt', 'w') do |f|
24
+ puts "Updating Manifest.txt. Re-run this task as you add files to your gem."
25
+ files.sort.each do |file|
26
+ puts "Adding #{file} to Manifest.txt"
27
+ f << file << "\n"
28
+ end
29
+ end
30
+ end
31
+
32
+ desc "Updates lib/webern.rb to include all files contained in lib/webern/"
33
+ task :update_lib do
34
+ files = Dir.glob('lib/webern/*.rb')
35
+ File.open('lib/webern.rb', 'w') do |f|
36
+ files.each do |file|
37
+ f << "require File.dirname(__FILE__) + '#{file[3..-1]}'\n"
38
+ end
39
+ end
40
+ end
41
+
42
+ desc "Removes rows.ly, rows.pdf, rows.ps"
43
+ task :clear_ly_files do
44
+ Dir.glob('rows.*').each do |file|
45
+ rm file
46
+ end
47
+ end
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # webern
3
+ # created by Michael Berkowitz
4
+
5
+ require File.dirname(__FILE__) + '/../lib/webern'
6
+
7
+ Webern::Webern.new(*ARGV)
8
+ puts "rows.ly generated" unless !File.exists?('rows.ly')
9
+ print "Path to lilypond binary: "
10
+ lilypond_path = STDIN.gets.chomp
11
+ `#{lilypond_path} rows.ly`
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + '/webern/lilypond_builder.rb'
2
+ require File.dirname(__FILE__) + '/webern/matrix.rb'
3
+ require File.dirname(__FILE__) + '/webern/version.rb'
4
+ require File.dirname(__FILE__) + '/webern/webern.rb'
@@ -0,0 +1,74 @@
1
+ require 'fileutils'
2
+
3
+ module Webern
4
+ class LilypondBuilder
5
+ include FileUtils
6
+
7
+ NOTES = {
8
+ 0 => "c",
9
+ 1 => "cs",
10
+ 2 => "d",
11
+ 3 => "ef",
12
+ 4 => "e",
13
+ 5 => "f",
14
+ 6 => "fs",
15
+ 7 => "g",
16
+ 8 => "af",
17
+ 9 => "a",
18
+ 10 => "bf",
19
+ 11 => "b"
20
+ }
21
+
22
+ LILYPOND_PREAMBLE = <<-LILYPOND
23
+ \\version "2.11.57"
24
+ \\include "english.ly"
25
+ #(set-global-staff-size 13)
26
+
27
+ rows = {
28
+ \\override Score.TimeSignature #'stencil = ##f
29
+ \\time 12/4
30
+ LILYPOND
31
+
32
+ LILYPOND_POSTAMBLE = <<-LILYPOND
33
+ }
34
+
35
+ \\book {
36
+ \\score {
37
+ <<
38
+ \\new Staff \\rows
39
+ >>
40
+ }
41
+ }
42
+ LILYPOND
43
+
44
+ attr_reader :matrix # An instance of Webern::Matrix
45
+
46
+ def initialize(matrix)
47
+ @matrix = matrix
48
+ build_lilypond_file
49
+ end
50
+
51
+ # Converts an array of rows into vaild LilyPond code.
52
+ def build_rows(row_type)
53
+ str = ''
54
+ abbrev = row_type.scan(/^[a-z]|_[a-z]/).join("")
55
+ @matrix.send(row_type).sort { |a, b| a[0] <=> b[0] }.each do |row|
56
+ str += "#{NOTES[row[0]]}'^\\markup{#{abbrev}#{row[0]}} "
57
+ str += row[1..-1].map { |n| NOTES[n] }.join("' ") + "'\n"
58
+ end
59
+ str += "\\break\n"
60
+ str
61
+ end
62
+
63
+ # Generates a valid LilyPond file from the Webern::Matrix object passed into the LilypondBuilder
64
+ def build_lilypond_file
65
+ File.open('rows.ly', 'w') do |f|
66
+ f << LILYPOND_PREAMBLE
67
+ ['primes', 'retrogrades', 'inversions', 'retrograde_inversions'].each do |row_type|
68
+ f << build_rows(row_type)
69
+ end
70
+ f << LILYPOND_POSTAMBLE
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,37 @@
1
+ module Webern
2
+ class Matrix
3
+ attr_reader :primes, :retrogrades, :inversions, :retrograde_inversions
4
+ def initialize p0
5
+ create_primes(p0)
6
+ create_retrogrades
7
+ create_inversions
8
+ create_retrograde_inversions
9
+ end
10
+
11
+ def create_primes(p0)
12
+ @primes = []
13
+ p0.each do |offset|
14
+ @primes << p0.map { |c| (12 - offset + c) % 12 }
15
+ end
16
+ end
17
+
18
+ def create_retrogrades
19
+ @retrogrades = @primes.map { |row| row.reverse }
20
+ end
21
+
22
+ def create_inversions
23
+ @inversions = []
24
+ (0...12).each do |i|
25
+ i_row = []
26
+ @primes.each do |row|
27
+ i_row << row[i]
28
+ end
29
+ @inversions << i_row
30
+ end
31
+ end
32
+
33
+ def create_retrograde_inversions
34
+ @retrograde_inversions = @inversions.map { |row| row.reverse }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ module Webern
2
+ module Version #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,41 @@
1
+ module Webern
2
+ class Webern
3
+ attr_reader :row
4
+
5
+ # Takes either a full or partial row of integers 0-11 or a string that can be
6
+ # converted into a row of integers
7
+ def initialize(*args)
8
+ begin
9
+ if args.map { |c| c.to_i }.sort == (0...12).to_a
10
+ row = args.map { |c| c.to_i }
11
+ elsif args.map { |c| c.to_i }.uniq == [0]
12
+ row = make_row_from_string args.join("")
13
+ else
14
+ row = finish_partial_row args
15
+ end
16
+ offset = row.first
17
+ @row = row.map { |c| (c + 12 - offset) % 12 }
18
+ m = Matrix.new(@row)
19
+ LilypondBuilder.new(m)
20
+ end
21
+ end
22
+
23
+ # Creates a 12-tone row from a string provided as an original argument.
24
+ def make_row_from_string(str)
25
+ working_row, row = str.downcase.gsub(/[^a-z]/, '').split('') + ('a'..'z').to_a, []
26
+ while row.size < 12
27
+ (row << working_row.shift).uniq!
28
+ end
29
+ alph_row = row.dup.sort
30
+ row.map { |c| alph_row.index(c) }
31
+ end
32
+
33
+ # Completes a 12-tone row if only a partial row was provided
34
+ # as the original argument.
35
+ def finish_partial_row(row)
36
+ working_row = row.map { |c| c.to_i }
37
+ missing = (0...12).to_a - working_row
38
+ working_row + missing
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + '/../lib/webern.rb'
2
+ require 'test/unit'
3
+
4
+ class WebernTest < Test::Unit::TestCase
5
+ def test_create_row
6
+ # Test full row beginning with 0
7
+ w = Webern::Webern.new("0", "2", "8", "1", "3", "11", "10", "7", "4", "6", "9", "5")
8
+ assert_equal [0,2,8,1,3,11,10,7,4,6,9,5], w.row
9
+
10
+ # Test full row not starting with 0
11
+ w = Webern::Webern.new("1", "2", "4", "5", "8", "10", "11", "6", "0", "3", "7", "9")
12
+ assert_equal [0,1,3,4,7,9,10,5,11,2,6,8], w.row
13
+
14
+ # Test starting string that provides 12 unique characters
15
+ w = Webern::Webern.new("Michael", "Berkowitz")
16
+ assert_equal [0,9,6,8,4,7,11,5,2,10,1,3], w.row
17
+
18
+ # Test starting string that does not provide 12 unique characters
19
+ w = Webern::Webern.new('Erica', 'Smith')
20
+ assert_equal [0,5,3,10,8,6,4,7,2,9,11,1], w.row
21
+
22
+ # Test incomplete row beginning with 0
23
+ w = Webern::Webern.new("0", "2", "4", "6", "8", "10")
24
+ assert_equal [0,2,4,6,8,10,1,3,5,7,9,11], w.row
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "webern"
3
+ s.version = "0.1.0"
4
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
5
+ s.authors = ['Michael Berkowitz']
6
+ s.date = "2008-11-16"
7
+ s.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 out to a .pdf file using the LilyPond notational language. }
8
+ s.email = 'michael.berkowitz@gmail.com'
9
+ s.executables = ['webern']
10
+ s.extra_rdoc_files = ['History.txt', 'Manifest.txt', 'README.txt']
11
+ s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "bin/webern", "lib/webern.rb", "lib/webern/lilypond_builder.rb", "lib/webern/matrix.rb", "lib/webern/version.rb", "lib/webern/webern.rb", "test/test_webern.rb", "webern.gemspec"]
12
+ s.has_rdoc = true
13
+ s.require_paths = ['lib']
14
+ s.summary = s.description
15
+ s.test_files = ["test/test_webern.rb"]
16
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mikowitz-webern
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Berkowitz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-11-16 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ 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 out to a .pdf file using the LilyPond notational language.
17
+ email: michael.berkowitz@gmail.com
18
+ executables:
19
+ - webern
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - History.txt
24
+ - Manifest.txt
25
+ - README.txt
26
+ files:
27
+ - History.txt
28
+ - Manifest.txt
29
+ - README.txt
30
+ - Rakefile
31
+ - bin/webern
32
+ - lib/webern.rb
33
+ - lib/webern/lilypond_builder.rb
34
+ - lib/webern/matrix.rb
35
+ - lib/webern/version.rb
36
+ - lib/webern/webern.rb
37
+ - test/test_webern.rb
38
+ - webern.gemspec
39
+ has_rdoc: true
40
+ homepage:
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.2.0
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: 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 out to a .pdf file using the LilyPond notational language.
65
+ test_files:
66
+ - test/test_webern.rb