我正在编写一个PHP应用程序,它将吉他的六个弦表示为一系列范围。通过这种方式,我可以对一组数字进行加法或减法,以系统地更改我定义的原型结构。
范围为:
//E: 1-15, A: 26-40, D: 51-65, G: 76-90, b: 101-115, e: 126-140
我对下面的代码有问题。
//the key of the key value pair represents its position on the guitar, and the value
//represents a theoretical function. If the inversion is "0", do nothing. If the
//inversion is "1", all notes that have the value of "r" should have their key
//incremented by 4 and their value changed to '3'.
//example: 1=>"r",28=>"5",52=>"7",77=>"3"
function invChange($pattern, $inversion) {
if ($inversion == 1) {
foreach ($pattern as $position => $function) {
if ($function == 'r' ) { $position += 4; $junction = '3'; }
if ($function == '3' ) { $position += 3; $junction = '5'; }
if ($function == '5' ) { $position += 4; $junction = '7'; }
if ($function == '7' ) { $position += 1; $junction = 'r'; }
$modScale[$position] = $junction;
}
}
if ($inversion == 2) {
foreach ($pattern as $position => $function) {
if ($function == 'r' ) { $position += 7; $junction = '5';}
if ($function == '3' ) { $position += 7; $junction = '7';}
if ($function == '5' ) { $position += 5; $junction = 'r';}
if ($function == '7' ) { $position += 5; $junction = '3';}
$modScale[$position] = $junction;
}
}
if ($inversion == 3) {
foreach ($pattern as $position => $function) {
if ($function == 'r' ) { $position += 11; $junction = '7';}
if ($function == '3' ) { $position += 8; $junction = 'r';}
if ($function == '5' ) { $position += 9; $junction = '3';}
if ($function == '7' ) { $position += 8; $junction = '5';}
$modScale[$position] = $junction;
}
}
return $modScale;
}
如您所见,这是相当重复的。看着这段代码让我觉得一定有更好的方法。我想我需要的是以无限线性方式使用数组:
array("root" => 4, "third" => 3, "fifth" => 4, "seventh" => 1);
现在我需要取预定义的$note => $offset对中的任意一个,并将它们在这个数组中跳跃1、2或3次。例如,如果它从一个根开始,它进行了一次跳跃,我需要添加4将其变成"第三",并将其值更改为"第三"。但如果它从根开始并进行两次跳跃,我需要添加4,添加3,然后将其值更改为"fifth"
TL;
好. .你可以用数学来做。甚至,在您提供的限制条件下,它实际上可以用一个函数来完成。二次函数。
怎么做
你所需要做的就是以某种方式创建一个数学函数,它将把你的反转作为一个参数,并通过给定的"函数"返回一个特定的位置(它是如何在你的PHP函数中调用的)。因为你有三个"反转"的值,你可以用二次函数来完成:
f(x) = ax2 + bx + c
在这里,您需要通过给定的x
值(您的情况为$inversion
)和函数值(每个"反转"if
块中的"位置"值)找到系数a
, b
和c
。
然而,对于每个"函数"(在foreach
块内),您有四个不同的位置开关-这就是为什么,实际上,您必须处理四个二次函数。
['r', '3', '5', '7']
,那么,如果反转是1
,电流是3
,那么结果将是5
。如果反演是2
,那么结果将是7
e t.c。
和代码
function invChangeN($pattern, $inversion)
{
$junc = ['r', '3', '5', '7'];
$pos = [
'r' => [ 1, 7, 14],
'3' => [-3, 5, 14],
'5' => [ 3, 5, 10],
'7' => [-1, 7, 10]
];
$inversion -= 2;
$modScale = [];
foreach ($pattern as $p => $f)
{
$p += ($pos[$f][0]*pow($inversion,2) + $pos[$f][1]*$inversion + $pos[$f][2])/2;
$j = $junc[(array_search($f, $junc)+$inversion+2)%count($junc)];
$modScale[$p] = $j;
}
return $modScale;
}
我们为什么要做$inversion -= 2
?将1
, 2
和3
(原始反演值)中的三个点调换为-1
, 0
和1
,这样计算a
, b
和c
就容易得多了。
$pos
包含每个"函数"(即$f
内循环)的二次函数系数数组。由于求解线性方程组,它们都是"半整数"(所以,有一个视图W/2
,所以分数的分母是2
)。这就是为什么我刚刚把它们都乘以2
,并在位置计算中加上除2。
我已经对你的函数和这个新的"数学"模拟进行了测试-取得了成功的结果,当然是1
, 2
和3
的反演,如:
//derived from old function:
array(4) {
[8]=>
string(1) "5"
[33]=>
string(1) "r"
[57]=>
string(1) "3"
[84]=>
string(1) "7"
}
//derived from new function:
array(4) {
[8]=>
string(1) "5"
[33]=>
string(1) "r"
[57]=>
string(1) "3"
[84]=>
string(1) "7"
}
以上结果适用于模式[1=>"r",28=>"5",52=>"7",77=>"3"]
和反转2