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 +4 -4
- data/lib/mm/lilypond.rb +134 -119
- data/test/mm/test_lilypond.rb +80 -70
- data/test/test_template.ly.erb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdbfb6d2f24f1d1080cd6ea6559ade00260f830a2c092680bcea1b095b189c8e
|
4
|
+
data.tar.gz: a240526e7b535154b73af7d698ac39e2456acb531c61d31e82a5e4a1fef81c82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1fc161114967aceae870bfbe23d5daed473cbb0afefb92020935df1474026c2313717a579445c9483dbe74c7d19639d8f0e1433bc56bc8ec165b318deb9fae42
|
7
|
+
data.tar.gz: aa56e773fe514b8c126e7ecbf1d5dc68e95f40482aef1c71b5978231a922c27f8a0306ba9b96ae54af2947ae1bb93fe6654b8e2a1080c28217cf08922d1c6403
|
data/lib/mm/lilypond.rb
CHANGED
@@ -1,119 +1,134 @@
|
|
1
|
-
require 'mm'
|
2
|
-
require '
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@
|
14
|
-
|
15
|
-
"
|
16
|
-
"
|
17
|
-
"
|
18
|
-
|
19
|
-
@
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
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
|
+
|
data/test/mm/test_lilypond.rb
CHANGED
@@ -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
|
49
|
-
@lily_parser.
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
assert_equal "
|
68
|
-
|
69
|
-
|
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
|
+
|
data/test/test_template.ly.erb
CHANGED
@@ -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.
|
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.
|
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.
|
26
|
+
version: '5.11'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rdoc
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|