Модуль:Музыка

Материал из свободной русской энциклопедии «Традиция»
Перейти к: навигация, поиск
\relative c' {
\override Staff.TimeSignature #'stencil = ##f
\key c \major s1 |
\key g \major s1 |
\key d \major s1 |
\key a \major s1 |
\key e \major s1 |
\key b \major s1 |
\key fis \major s1
}
Code Output
{{#invoke:Музыка|keys|cis major}}
\relative c' {
\override Staff.TimeSignature #'stencil = ##f
\key cis \major s1}

-- Well tempered:
local semitones_from_c = {
	C	= 0,
	Cis	= 1,
	Ces	= 11,
	D	= 2,
	Dis	= 3,
	Des	= 1,
	E	= 4,
	Eis	= 5,
	Es	= 3,
	F	= 5,
	Fis	= 6,
	Fes	= 4,
	G	= 7,
	Gis	= 8,
	Ges	= 6,
	A	= 9,
	Ais	= 10,
	As	= 8,
	H	= 11,
	His	= 12,
	B	= 10
}	-- local semitones_from_c

-- Intervals in semitones:
local intervals = {
	-- English:
	['unison']			= 0,
	['minor second']	= 1,
	['major second']	= 2,
	['minor third']		= 3,
	['major third']		= 4,
	['perfect fourth']	= 5,
	['perfect fifth']	= 7,
	['minor sixth']		= 8,
	['major sixth']		= 9,
	['minor seventh']	= 10,
	['major seventh']	= 11,
	['perfect octave']	= 12,
	
	-- Russian:
	['унисон']			= 0,
	['малая секунда']	= 1,
	['большая секунда']	= 2,
	['малая терция']	= 3,
	['большая терция']	= 4,
	['чистая кварта']	= 5,
	['чистая квинта']	= 7,
	['малая секста']	= 8,
	['большая секста']	= 9,
	['малая септима']	= 10,
	['большая септима']	= 11,
	['чистая октава']	= 12
}	-- 	local intervals

local degrees = {
	russian = {'тоника', 'верхний вводный тон', 'медианта', 'субдоминанта', 'доминанта', 'субмедианта', 'нижний вводный тон'},
	english = {'tonic', 'supertonic', 'mediant', 'subdominant', 'dominant', 'submediant', 'leading/subtonic'}	
}	-- local degrees

local scales = {
	major = {0, 2, 4, 5, 7, 9, 11, 12},
	minor = {0, 2, 3, 5, 7, 8, 10, 12}
}	-- local modes
local bases = {
	major = 0,
	minor = 9
}	-- local bases

local function degree (tonic, mode, degree)
	local alteration = alteration_type (tonic, mode)
	return offset (tonic, scales [mode] [degree], alteration)
end		-- local function degree (tonic, mode, degree)

local function gamma_absolute (tonic, mode)
	local gamma = {}
	for i=1, 7 do
		gamma [i] = degree (tonic, mode, i)
	end
	return gamma
end		-- local function gamma_absolute (tonic, mode)

local bezout = require 'Module:Math'.bezout
local function diophantine (a, b, c)
	local gcd, x, y = bezout (a, b)
	return x * gcd, y * gcd
end		-- local function diophantine (a, b, c)

local function get_quintas (tonic, mode)
	local quintas, octaves = diophantine (7,  12, tonic - bases [mode])
	if quintas > 6 then
		quintas = quintas - 12
	end
	return quintas
end		-- local function get_quintas (tonic, mode)

local function alteration_type (tonic, mode)
	local quintas = get_quintas (tonic, mode)
	if quintas >= 0 then
		return 'is'
	else
		return 'es'
	end
end		-- local function alteration_type (tonic, mode)

local function get_alteration (key)
	if mw.ustring.sub (key, -2) == 'is' then
		return 'is'
	elseif mw.ustring.sub (key, -1) == 's' then
		return 'es'
	elseif key == 'B' then
		return 'es'
	else
		return ''
	end
end		-- local function get_alteration (key)

local function offset (base, semitones, alteration)
	local base_semitones = semitones_from_c [base]
	for key, height in pairs (semitones_from_c) do
		if height == base_semitones + semitones and get_alteration (key) == alteration then
			return key
		end
	end
end		-- local function offset (base, semitones, alteration)

local alterations = {'F', 'C', 'G', 'D', 'A', 'E', 'B'}

local function keys (tonic, scale)
	local keys = {}
	local gamma = gamma_absolute (tonic, scale)
	for degree, key in ipairs (gamma) do
		if get_alteration (key) ~= '' then
			keys [#keys + 1] = key
		end
	end
	return keys
end		-- local function keys (tonic, scale)

local sub = mw.ustring.gsub

local function show_keys_with_score (key)
	local escaped = sub (key, '%s(.+)$', ' \\%1')
	return [=[
\relative c' {
\override Staff.TimeSignature #'stencil = ##f
\key ]=] .. escaped .. ' s1}'
end		-- local function show_keys_with_score (key)

-- Interface:
local interface = {
	functions = {
		keys	= show_keys_with_score
	},
	wrappers = {
		keys = function (frame, text)
			return frame:callParserFunction ('#tag', 'score', text)
		end
	}
}	-- local interface

local p = {}

for name, func in pairs (interface.functions) do
	if interface.wrappers [name] then
		p [name] = function (frame)
			local cloned_args = mw.clone (frame.args)
			return interface.wrappers [name] (frame, func (unpack (cloned_args)))
		end
	else
		p [name] = function (frame)
			local cloned_args = mw.clone (frame.args)
			return func (unpack (cloned_args))
		end
	end	-- if interface.wrappers (name)
end	-- for name, func in pairs (interface.functions)

return p