mm-lilypond 1.1.0 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd930b1d2e25368ab27876e5c0a80e7551eec8f599353892322ed8514f5dfdab
4
- data.tar.gz: 02d6e331e9768b36cbbdd38aed6b72ea94fe73c6b7d5c85f0c9b0bbbcb0ae101
3
+ metadata.gz: fdbfb6d2f24f1d1080cd6ea6559ade00260f830a2c092680bcea1b095b189c8e
4
+ data.tar.gz: a240526e7b535154b73af7d698ac39e2456acb531c61d31e82a5e4a1fef81c82
5
5
  SHA512:
6
- metadata.gz: 48e39b98a3f8896df5dd14da6d366b4c07e7f4ebf5e8298bf332db59bf152caa8ee59bae2f803750d5ab83891a15093d678a653cca85f19816d1c1817dc2d3be
7
- data.tar.gz: cab4a1af508f392e4bb1e073198eeaf69bdfd7861badaf070d4fe948297d38d4069253a15115f007d2b6737efa3ee1e48d86557b75cfc57d033cf2c622867f4a
6
+ metadata.gz: 1fc161114967aceae870bfbe23d5daed473cbb0afefb92020935df1474026c2313717a579445c9483dbe74c7d19639d8f0e1433bc56bc8ec165b318deb9fae42
7
+ data.tar.gz: aa56e773fe514b8c126e7ecbf1d5dc68e95f40482aef1c71b5978231a922c27f8a0306ba9b96ae54af2947ae1bb93fe6654b8e2a1080c28217cf08922d1c6403
data/lib/mm/lilypond.rb CHANGED
@@ -1,119 +1,134 @@
1
- require 'mm'
2
- require 'pry'
3
- require 'erb'
4
-
5
- class MM::Lilypond
6
- VERSION = "1.1.0"
7
-
8
- attr_accessor :offset, :basenames, :prime_limit, :prime_steps
9
- attr_writer :template
10
-
11
- def initialize prime_limit: nil
12
- # offset is around the circle of fifths
13
- @offset = 2
14
- @basenames = ["c", "g", "d", "a", "e", "b",
15
- "fsharp", "csharp", "gsharp", "dsharp", "asharp", "esharp", "bsharp",
16
- "fdoublesharp", "cdoublesharp", "gdoublesharp", "ddoublesharp", "adoublesharp", "edoublesharp", "bdoublesharp",
17
- "fdoubleflat", "cdoubleflat", "gdoubleflat", "ddoubleflat", "adoubleflat", "edoubleflat", "bdoubleflat",
18
- "fflat", "cflat", "gflat", "dflat", "aflat", "eflat", "bflat", "f"]
19
- @prime_limit = prime_limit
20
- @prime_steps = [1, 4, -2, -1, 3]
21
- end
22
-
23
- def get_pitch ratio
24
- basename = get_basename ratio
25
- alteration = get_alteration ratio
26
- octave = get_octave ratio
27
- basename + alteration + octave
28
- end
29
-
30
- def get_basename ratio
31
- @basenames[@offset + get_steps(ratio)].dup
32
- end
33
-
34
- def get_alteration ratio
35
- ratio.factors.reject {|f| @prime_limit && f[0] > @prime_limit}.map {|f|
36
- case f[0]
37
- when 5
38
- collect_string f[1], "f"
39
- when 7
40
- collect_string f[1], "s"
41
- when 11
42
- collect_string f[1] * -1, "e"
43
- when 13
44
- collect_string f[1], "t"
45
- end
46
- }.join("")
47
- end
48
-
49
- def get_octave ratio
50
- offset = (@offset * 4) % 7
51
- degrees = ratio.factors.inject(0) {|d, f|
52
- d + case f[0]
53
- when 2
54
- f[1] * 7
55
- when 3
56
- f[1] * 11
57
- when 5
58
- f[1] * 16
59
- when 7
60
- f[1] * 20
61
- when 11
62
- f[1] * 24
63
- when 13
64
- f[1] * 26
65
- else
66
- 0
67
- end
68
- } + offset
69
- if degrees > 0
70
- (degrees / 7.0).floor.times.map {"'"}.join("")
71
- else
72
- (degrees / -7.0).ceil.times.map {","}.join("")
73
- end
74
- end
75
-
76
- def get_duration ratio
77
- "1*#{ratio.reciprocal.to_s}"
78
- end
79
-
80
- def full_note ratio
81
- get_pitch(ratio) + get_duration(ratio)
82
- end
83
-
84
- def render ratios
85
- my_music = ratios.map {|r| self.full_note r}.join(" ")
86
- output = ERB.new @template
87
- output.result(binding)
88
- end
89
-
90
- private
91
-
92
- def collect_string times, string
93
- if times > 0
94
- times.times.collect {"D#{string}"}
95
- else
96
- (times * -1).times.collect {"U#{string}"}
97
- end
98
- end
99
-
100
- def get_steps ratio
101
- ratio.factors.inject(0) {|memo, f|
102
- memo + case f[0]
103
- when 3
104
- f[1] * @prime_steps[0]
105
- when 5
106
- f[1] * @prime_steps[1]
107
- when 7
108
- f[1] * @prime_steps[2]
109
- when 11
110
- f[1] * @prime_steps[3]
111
- when 13
112
- f[1] * @prime_steps[4]
113
- else
114
- 0
115
- end
116
- }
117
- end
118
- end
119
-
1
+ require 'mm'
2
+ require 'erb'
3
+
4
+ class MM::Lilypond
5
+ VERSION = "1.2.0"
6
+
7
+ attr_accessor :offset, :basenames, :prime_limit, :prime_steps
8
+ attr_writer :template
9
+
10
+ def initialize prime_limit: nil
11
+ # offset is around the circle of fifths
12
+ @offset = 2
13
+ @basenames = ["c", "g", "d", "a", "e", "b",
14
+ "fsharp", "csharp", "gsharp", "dsharp", "asharp", "esharp", "bsharp",
15
+ "fdoublesharp", "cdoublesharp", "gdoublesharp", "ddoublesharp", "adoublesharp", "edoublesharp", "bdoublesharp",
16
+ "fdoubleflat", "cdoubleflat", "gdoubleflat", "ddoubleflat", "adoubleflat", "edoubleflat", "bdoubleflat",
17
+ "fflat", "cflat", "gflat", "dflat", "aflat", "eflat", "bflat", "f"]
18
+ @prime_limit = prime_limit
19
+ @prime_steps = [1, 4, -2, -1, 3]
20
+ end
21
+
22
+ def get_pitch ratio
23
+ basename = get_basename ratio
24
+ alteration = get_alteration ratio
25
+ octave = get_octave ratio
26
+ basename + alteration + octave
27
+ end
28
+
29
+ def get_basename ratio
30
+ @basenames[@offset + get_steps(ratio)].dup
31
+ end
32
+
33
+ def get_alteration ratio
34
+ ratio.factors.reject {|f| @prime_limit && f[0] > @prime_limit}.map {|f|
35
+ case f[0]
36
+ when 5
37
+ collect_string f[1], "f"
38
+ when 7
39
+ collect_string f[1], "s"
40
+ when 11
41
+ collect_string f[1] * -1, "e"
42
+ when 13
43
+ collect_string f[1], "t"
44
+ end
45
+ }.join("")
46
+ end
47
+
48
+ def get_octave ratio
49
+ offset = (@offset * 4) % 7
50
+ degrees = ratio.factors.inject(0) {|d, f|
51
+ d + case f[0]
52
+ when 2
53
+ f[1] * 7
54
+ when 3
55
+ f[1] * 11
56
+ when 5
57
+ f[1] * 16
58
+ when 7
59
+ f[1] * 20
60
+ when 11
61
+ f[1] * 24
62
+ when 13
63
+ f[1] * 26
64
+ else
65
+ 0
66
+ end
67
+ } + offset
68
+ if degrees > 0
69
+ (degrees / 7.0).floor.times.map {"'"}.join("")
70
+ else
71
+ (degrees / -7.0).ceil.times.map {","}.join("")
72
+ end
73
+ end
74
+
75
+ def get_duration ratio
76
+ "1*#{ratio.reciprocal.to_s}"
77
+ end
78
+
79
+ # Gets the cents deviation from the unaltered pitch (i.e., from the equal
80
+ # tempered pitch of sharps, flats, naturals).
81
+ def cents_deviation ratio
82
+ unaltered = cents_of_unaltered ratio
83
+ deviation = (ratio.cents % 1200) - unaltered
84
+ if deviation < 0
85
+ "#{deviation.round}"
86
+ else
87
+ "+#{deviation.round}"
88
+ end
89
+ end
90
+
91
+ def cents_of_unaltered ratio
92
+ (get_steps(ratio) * 7) % 12 * 100.0
93
+ end
94
+
95
+ def full_note ratio
96
+ get_pitch(ratio) + get_duration(ratio)
97
+ end
98
+
99
+ def render ratios
100
+ my_music = ratios.map {|r| self.full_note r}.join(" ")
101
+ output = ERB.new @template
102
+ output.result(binding)
103
+ end
104
+
105
+ private
106
+
107
+ def collect_string times, string
108
+ if times > 0
109
+ times.times.collect {"D#{string}"}
110
+ else
111
+ (times * -1).times.collect {"U#{string}"}
112
+ end
113
+ end
114
+
115
+ def get_steps ratio
116
+ ratio.factors.inject(0) {|memo, f|
117
+ memo + case f[0]
118
+ when 3
119
+ f[1] * @prime_steps[0]
120
+ when 5
121
+ f[1] * @prime_steps[1]
122
+ when 7
123
+ f[1] * @prime_steps[2]
124
+ when 11
125
+ f[1] * @prime_steps[3]
126
+ when 13
127
+ f[1] * @prime_steps[4]
128
+ else
129
+ 0
130
+ end
131
+ }
132
+ end
133
+ end
134
+
@@ -1,70 +1,80 @@
1
- require "minitest/autorun"
2
- require "mm/lilypond"
3
-
4
- module TestMM; end
5
-
6
- class TestMM::TestLilypond < Minitest::Test
7
- def setup
8
- @lily_parser = MM::Lilypond.new
9
- end
10
-
11
- def test_get_duration
12
- assert_equal "1*2/3", @lily_parser.get_duration(MM::Ratio.new(3,2))
13
- end
14
-
15
- def test_get_basename
16
- assert_equal "e", @lily_parser.get_basename(MM::Ratio.new(9,8))
17
- assert_equal "fsharp", @lily_parser.get_basename(MM::Ratio.new(5,4))
18
- assert_equal "c", @lily_parser.get_basename(MM::Ratio.new(7,4))
19
- assert_equal "g", @lily_parser.get_basename(MM::Ratio.new(11,8))
20
- end
21
-
22
- def test_get_alteration
23
- assert_equal "Df", @lily_parser.get_alteration(MM::Ratio.new(5,4))
24
- assert_equal "Ds", @lily_parser.get_alteration(MM::Ratio.new(7,4))
25
- end
26
-
27
- def test_get_octave
28
- assert_equal ",,", @lily_parser.get_octave(MM::Ratio.new(1,4))
29
- assert_equal "'", @lily_parser.get_octave(MM::Ratio.new(9,4))
30
- assert_equal "'", @lily_parser.get_octave(MM::Ratio.new(7,4))
31
- end
32
-
33
- def test_get_pitch
34
- assert_equal "d", @lily_parser.get_pitch(MM::Ratio.new(1,1))
35
- assert_equal "a", @lily_parser.get_pitch(MM::Ratio.new(3,2))
36
- assert_equal "fsharpDf", @lily_parser.get_pitch(MM::Ratio.new(5,4))
37
- assert_equal "cDs'", @lily_parser.get_pitch(MM::Ratio.new(7,4))
38
- assert_equal "cDs", @lily_parser.get_pitch(MM::Ratio.new(7,8))
39
- assert_equal "d'", @lily_parser.get_pitch(MM::Ratio.new(2,1))
40
- assert_equal "d,", @lily_parser.get_pitch(MM::Ratio.new(1,2))
41
- end
42
-
43
- def test_get_full_note
44
- assert_equal "d'1*1/2", @lily_parser.full_note(MM::Ratio.new(2,1))
45
- assert_equal "aflatUfDs1*5/7", @lily_parser.full_note(MM::Ratio.new(7,5))
46
- end
47
-
48
- def test_render
49
- @lily_parser.template = File.read("test/test_template.ly.erb")
50
- exp = "music = { a1*2/3 cDs'1*4/7 }\n"
51
- result = @lily_parser.render([MM::Ratio.new(3,2), MM::Ratio.new(7,4)])
52
- assert_equal exp, result
53
- end
54
-
55
- def test_offset
56
- @lily_parser.offset = 0
57
- assert_equal "c", @lily_parser.get_pitch(MM::Ratio.new(1,1))
58
- assert_equal "eDf", @lily_parser.get_pitch(MM::Ratio.new(5,4))
59
- assert_equal "bDf", @lily_parser.get_pitch(MM::Ratio.new(15,8))
60
- end
61
-
62
- def test_prime_limit
63
- @lily_parser.prime_limit = 3
64
- @lily_parser.prime_steps[3] = 6
65
- assert_equal "bflat", @lily_parser.get_pitch(MM::Ratio.new(14, 9))
66
- assert_equal "fsharp", @lily_parser.get_pitch(MM::Ratio.new(5, 4))
67
- assert_equal "gsharp", @lily_parser.get_pitch(MM::Ratio.new(11, 8))
68
- end
69
- end
70
-
1
+ require "minitest/autorun"
2
+ require "mm/lilypond"
3
+
4
+ module TestMM; end
5
+
6
+ class TestMM::TestLilypond < Minitest::Test
7
+ def setup
8
+ @lily_parser = MM::Lilypond.new
9
+ end
10
+
11
+ def test_get_duration
12
+ assert_equal "1*2/3", @lily_parser.get_duration(MM::Ratio.new(3,2))
13
+ end
14
+
15
+ def test_get_basename
16
+ assert_equal "e", @lily_parser.get_basename(MM::Ratio.new(9,8))
17
+ assert_equal "fsharp", @lily_parser.get_basename(MM::Ratio.new(5,4))
18
+ assert_equal "c", @lily_parser.get_basename(MM::Ratio.new(7,4))
19
+ assert_equal "g", @lily_parser.get_basename(MM::Ratio.new(11,8))
20
+ end
21
+
22
+ def test_get_alteration
23
+ assert_equal "Df", @lily_parser.get_alteration(MM::Ratio.new(5,4))
24
+ assert_equal "Ds", @lily_parser.get_alteration(MM::Ratio.new(7,4))
25
+ end
26
+
27
+ def test_get_octave
28
+ assert_equal ",,", @lily_parser.get_octave(MM::Ratio.new(1,4))
29
+ assert_equal "'", @lily_parser.get_octave(MM::Ratio.new(9,4))
30
+ assert_equal "'", @lily_parser.get_octave(MM::Ratio.new(7,4))
31
+ end
32
+
33
+ def test_get_pitch
34
+ assert_equal "d", @lily_parser.get_pitch(MM::Ratio.new(1,1))
35
+ assert_equal "a", @lily_parser.get_pitch(MM::Ratio.new(3,2))
36
+ assert_equal "fsharpDf", @lily_parser.get_pitch(MM::Ratio.new(5,4))
37
+ assert_equal "cDs'", @lily_parser.get_pitch(MM::Ratio.new(7,4))
38
+ assert_equal "cDs", @lily_parser.get_pitch(MM::Ratio.new(7,8))
39
+ assert_equal "d'", @lily_parser.get_pitch(MM::Ratio.new(2,1))
40
+ assert_equal "d,", @lily_parser.get_pitch(MM::Ratio.new(1,2))
41
+ end
42
+
43
+ def test_get_full_note
44
+ assert_equal "d'1*1/2", @lily_parser.full_note(MM::Ratio.new(2,1))
45
+ assert_equal "aflatUfDs1*5/7", @lily_parser.full_note(MM::Ratio.new(7,5))
46
+ end
47
+
48
+ def test_cents_deviation
49
+ assert_equal "+2", @lily_parser.cents_deviation(MM::Ratio.new(3, 2))
50
+ assert_equal "-14", @lily_parser.cents_deviation(MM::Ratio.new(5, 4))
51
+ end
52
+
53
+ def test_cents_of_unaltered
54
+ assert_equal 700.0, @lily_parser.cents_of_unaltered(MM::Ratio.new(3, 2))
55
+ assert_equal 400.0, @lily_parser.cents_of_unaltered(MM::Ratio.new(5, 4))
56
+ end
57
+
58
+ def test_render
59
+ @lily_parser.template = File.read("test/test_template.ly.erb")
60
+ exp = "music = { a1*2/3 cDs'1*4/7 }\n"
61
+ result = @lily_parser.render([MM::Ratio.new(3,2), MM::Ratio.new(7,4)])
62
+ assert_equal exp, result
63
+ end
64
+
65
+ def test_offset
66
+ @lily_parser.offset = 0
67
+ assert_equal "c", @lily_parser.get_pitch(MM::Ratio.new(1,1))
68
+ assert_equal "eDf", @lily_parser.get_pitch(MM::Ratio.new(5,4))
69
+ assert_equal "bDf", @lily_parser.get_pitch(MM::Ratio.new(15,8))
70
+ end
71
+
72
+ def test_prime_limit
73
+ @lily_parser.prime_limit = 3
74
+ @lily_parser.prime_steps[3] = 6
75
+ assert_equal "bflat", @lily_parser.get_pitch(MM::Ratio.new(14, 9))
76
+ assert_equal "fsharp", @lily_parser.get_pitch(MM::Ratio.new(5, 4))
77
+ assert_equal "gsharp", @lily_parser.get_pitch(MM::Ratio.new(11, 8))
78
+ end
79
+ end
80
+
@@ -1 +1 @@
1
- music = { <%= my_music %> }
1
+ music = { <%= my_music %> }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mm-lilypond
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Smith
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '5.10'
19
+ version: '5.11'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '5.10'
26
+ version: '5.11'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rdoc
29
29
  requirement: !ruby/object:Gem::Requirement