使用PHP/HTML计算和显示四部分和弦的反转



我正在编写一个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, bc

然而,对于每个"函数"(在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, 23(原始反演值)中的三个点调换为-1, 01,这样计算a, bc就容易得多了。

$pos包含每个"函数"(即$f内循环)的二次函数系数数组。由于求解线性方程组,它们都是"半整数"(所以,有一个视图W/2,所以分数的分母是2)。这就是为什么我刚刚把它们都乘以2,并在位置计算中加上除2。

测试

我已经对你的函数和这个新的"数学"模拟进行了测试-取得了成功的结果,当然是1, 23的反演,如:

//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

最新更新