1
2
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
120
121
122
123
124
|
--[[
(c) Copyright 2013 Ondrej Fafejta <fafejtao@gmail.com>
https://github.com/fafejtao/pmxChords
]] --
--
-- Chords transposition class
--
ChordsTr = {} -- the table representing the class, which will double as the metatable for the instances
ChordsTr.__index = ChordsTr -- failed table lookups on the instances should fallback to the class table, to get methods
setmetatable(ChordsTr,
{
__call = function(cls, ...)
return cls.new(...)
end,
})
--
-- global constants
--
ChordsTr.CHORDS_BEGIN = "\\ch."
ChordsTr.CHORDS_END = ".\\"
ChordsTr.BASE_CHORDS_ARR = {
-- lua is indexing from 1 I need from 0 ...
[0] = "C",
[1] = "Cs",
[2] = "D",
[3] = "Ef",
[4] = "E",
[5] = "F",
[6] = "Fs",
[7] = "G",
[8] = "Af",
[9] = "A",
[10] = "Bf",
[11] = "B"
}
--
-- Create instance of chords transposition class
-- params iSig input signature e.g. -1 - F major
-- oSig output signature e.g. 2 - D major
--
function ChordsTr.new(iSig, oSig)
local self = setmetatable({}, ChordsTr)
self.trMap = ChordsTr.__createTransposeMap(oSig - iSig)
return self
end
--
-- Core of transposition.
-- Prepare map of transposed chords.
-- Key is input base chord and value is output base chord.
--
function ChordsTr.__createTransposeMap(sigDiff)
local size = 12
local halfTones = (sigDiff * 7) % size
if (halfTones < 0) then
halfTones = halfTones + size
end
-- generate transpose map of base chords ...
local res = {}
local i
for i = 0, size - 1, 1 do
local key = ChordsTr.BASE_CHORDS_ARR[i]
local trIdx = (i + halfTones) % size;
res[key] = ChordsTr.BASE_CHORDS_ARR[trIdx]
end
return res
end
--
-- transpose one line.
-- Find each chords in line and transpose it into output signature.
-- return transposed line.
--
function ChordsTr:lineTranspose(line)
local pos = 0;
local trLine = "" -- transposed line (result)
while true do
local i = line:find(ChordsTr.CHORDS_BEGIN, pos)
if i == nil then
trLine = trLine .. line:sub(pos)
break
end
i = i + 3 -- move after \ch.
trLine = trLine .. line:sub(pos, i) -- append non chord string into result
pos = line:find(ChordsTr.CHORDS_END, i)
if pos == nil then -- TODO check correctly end of chords ... e.g. check wrong line (first chord is not finished correctly): \ch.C. c \ch.G7.\ b
io.stderr:write("End of chords was not found!\n")
os.exit(-1)
end
local chord = line:sub(i + 1, pos - 1)
trLine = trLine .. self:doTranspose(chord)
end
return trLine
end
--
-- do transpose of one chord.
--
function ChordsTr:doTranspose(chord)
local base, alt = ChordsTr.splitChord(chord)
return self.trMap[base] .. alt
end
--
-- Split chord into two part: base chord and chord alteration.
-- e.g. Fsm7 - base chord is Fs, alteration is m7
--
function ChordsTr.splitChord(chord)
if (chord.len == 1) then
return chord, ""
end
local secondChar = chord:sub(2, 2)
if (secondChar == 's' or secondChar == 'f') then
return chord:sub(1, 2), chord:sub(3)
else
return chord:sub(1, 1), chord:sub(2)
end
end
--
-- end of ChordsTr class
--
|