当以任何顺序给出三个音符时如何解决和弦。数学

Posted

技术标签:

【中文标题】当以任何顺序给出三个音符时如何解决和弦。数学【英文标题】:How to resolve chord when given three notes in any order. Mathematics 【发布时间】:2013-11-16 15:22:04 【问题描述】:

我有一个连接到 Stradella 系统钢琴手风琴的 arduino。我在左手和弦的 12 个音符中的每一个上都有光学传感器。当我演奏和弦时,它会触发三个传感器。如果我想让合成器演奏和弦也没关系,但有时我希望它只演奏根音;所以如果我演奏 C 大调,我希望它只演奏音符 C。

在下表中,您可以看到和弦 C 大调的触发传感器是传感器 0,4 和 7。但是因为它们都是同时触发的,所以它们可能不会按该顺序到达,即它们可能以4,0,7 或任意组合。

找到C大调的根音很容易,找到相差7的两个音符,根音是两者中较低的一个。 D 大调和 E 大调等也一样。但是像 F 大调这样的高和弦有一个高音,会再次环绕到底部,因此数字差不再是 7。

           0  1  2  3  4  5  6  7  8  9  10 11
C  Major   X           X        X 
C# Major      X           X        X
D  Major         X           X        X
D# Major            X           X        X
E  Major               X           X        X
F  Major   X              X           X      
F# Major      X              X           X     
G  Major         X              X           X  
G# Major   X        X              X             
A  Major      X        X              X             
A# Major         X        X              X           
B  Major            X        X              X 

有没有人知道我如何能够相当便宜地确定这些和弦的根音(它以每秒 600 次的速度循环运行,而 arduino 正在做很多其他事情)。

我完全被难住了,我尝试过逐步循环直到达到 11,然后从 0 重新开始,每个和弦都重复此操作 3 次,但看起来很混乱。

我还希望能够解决手风琴上的其他两排按钮,占主导地位和减少的 7th

这些是 C 的四个形状,其他 11 个音符将是相同的形状,但向右移动,直到它再次回到 0。

          0 1 2 3 4 5 6 7 8 9 10 11
C Major   X       X     X
C Minor   X     X       X
C 7th     X       X           X
C Dim7th  X     X           X

非常感谢任何建议!

【问题讨论】:

七和弦由4个音符组成,仅用于音符 一个简单的和弦表,由您的输入表示。对输入进行排序,然后在表中找到三元组。没有数学 == 更低的功率要求。 【参考方案1】:

差异仍然是 7 - 您必须只进行所有模 12 的计算。因此,对于 F 大调,您只有 5,9,12,模 12 是 5,9,0。或者反过来:你有 5,9,0 和 7 没有区别,所以只需将 12 加到最低的 (0) 上,得到 (12),然后基音就是 5。

更容易做到这一点的是,如果你的差为 7,则使用较低的音符,但如果你的差为 5,则使用较高的音符。

############# 编辑:

另一种方法是使用 Map(Int, Chord) 或 1024 个元素的数组,您只需用所有已知的和弦填充即可。像上面一样,你已经完成了这项工作。这个想法是有 12 位数字,你只需将 1 移位到每个数字的 lft 多次即可获得密钥。

例子:

char * notes[1024];
// earlier, in initialization:
notes[0x221] = "F-Major";
notes[....]  = ....;   // do that for all chords you're interested in
// this are the numbers you get:
int a = 5, b= 9, c=0;    // F Major
int key = (1 << a) | (1 << b) | (1 << c);   // 0b10 0010 0001 = 0x221
char *chord = notes[key];

【讨论】:

啊,清晰的一刻!这看起来适合主要和次要,非常感谢!因此,通过您的系统,我可以通过取 10 间隔中的最低值或 2 间隔中的最高值来识别 7th。最后的问题将是 Dim7th。它可能是最低的 9,但最高的 3 会匹配很多其他和弦,有什么想法吗? @jason 您仍然可以使用其他方法 - 如果没有有意义的和弦,只需将 12 加到最小的数字上,然后看看是否有意义。 酷,我会接受这个作为答案,在我去的时候解决掉小问题!干杯!让你知道我过得怎么样! 我喜欢这个,但我认为这不是最简单的解决方案。【参考方案2】:

我会创建一个集合(如果您使用的语言支持)或只是一个排序列表(对于 3 个值,我认为您可以使用几个 IF 排序),然后将其用作哈希的键表来找到和弦。

【讨论】:

我在使用 arduino,所以我知道我应该能够制作集合,但我在 google 上看不到任何对集合和 arduino 的引用。所以你是说我应该创建一个预编程所有 48 个和弦的哈希表? 我是说我会这样做。不声称这是最好的方法。【参考方案3】:

看着它,我会将处理分为两个步骤。首先,获得最低的音调。如果不是 0、1 或 2,请使用(唯一标识的)和弦。如果是这三个之一,请检查哪个音调是第二低的。

这只需要一个循环(找到最低音),在最坏的情况下最多需要一次查找。

Find out the lowest tone being played.
If it is 4 ⇒ D# major and return.
Else if it is 5 ⇒ E major and return.
Else if it is 0 ⇒ 
   check if 4 is being played ⇒ C major and return
         else ⇒ F major
Else if it is 1 ⇒
   check if 5 is being played ⇒ C# major and return
         else ⇒ F# major
Else if it is 2 ⇒ 
   check if 6 is being played ⇒ D major and return
         else ⇒ G major

知道最有可能的和弦,如果您想确定和弦当前正在播放,您还可以检查第三个音调。

【讨论】:

您好 Jonas,感谢您的快速回复,我已编辑问题以显示完整的 12 个和弦。正如你所看到的,不幸的是 4 也将与 A 专业匹配,但我仍然试图理解你的回应,但不确定我的编辑是否改变了任何东西..J【参考方案4】:

关于:有没有人知道我如何可以相当便宜地确定这些和弦的根音...

看起来给出的答案已经满足了需求,但我只是想提供另一种观点,以防您需要将其扩展到某些一般应用...

FFT(快速傅里叶变换)或 DFT(离散傅里叶变换) 还可以将一组频率(例如和弦)解析为其基本频率,从而允许您可以选择根音符或任何其他组件。

有很多实现,但我发现 this one 特别有用。它是开源的。如何使用 FFT/DFT 的例子有很多,包括 this onethis implementation disscussion

【讨论】:

FFT 可以应用于音频信号。这里我们没有音频信号,只有关于单个音符的信息。 @el.pescado - 我现在明白了。谢谢。那时 FFT 根本不适用。 事实上,可用的输入可以转换为频率,但解析 FFT 所需的工作量(复杂性)将比简单的表格查找浪费更多的热量。

以上是关于当以任何顺序给出三个音符时如何解决和弦。数学的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式检测音符和和弦(在 iPhone SDK 中)?

HihoCoder1532 : 最美和弦(DP优化)

HihoCoder 1532 : 最美和弦

如何使用 guitar pro 制作扫弦的吉他谱

基本乐理知识——和弦

使用 NAudio 演奏和弦的最佳方式