我必须制作一个接收int
的转换器,表示当前音调的色度间隔(即root = 1,次要秒= 2,次要第7 = 11,主要第9 = 15,主要是13 = 22等),并将其转换为全音阶间隔,反之亦然。
所以考虑上面的例子,这里有一些映射:
Diat. | Chrom.
---------------------
1 (C) | 1
b2 (Db) | 2
2 (D) | 3
4 (F) | 6
b7 (Bb) | 11
9 (D) | 15
#11 (F#) | 19
b13 (Ab) | 21
显然我可以使用简单的1对1 switch
语句执行两个函数,或者as suggested使用双向字典,但在此之前我想知道我是否能找到更多有效的方法。
全音阶输出不一定是精确的音调,和谐音调也很好,因此D#
和Eb
是相同的。
然而,解析方法必须知道如何解析锐利和平面,但这可以通过将所有锐利设置为更高的音调来实现。
对于铬。要diat。函数,我正在考虑更多计算它的算法。我现在想弄明白,仍然没有成功。它必须根据钢琴键盘的视觉顺序划分彩色步骤,意味着将数量除以一半,不包括E-F和B-C之间被认为是整个全音阶的半步。
我更喜欢它是计算而不是静态映射,所以我以后可以使用转置标度等。
答案 0 :(得分:1)
为此,您需要一个特殊的双向词典。 这是一个: Getting key of value of a generic Dictionary?
通过模运算和计算音符之间的相对距离,可以轻松处理换位。
如果您正在寻找速度,您还可以定义包含所需元素对的类,并将它们放在循环链表或二叉搜索树中。但是,当你只处理12个简单元素时,我认为这并不重要。
答案 1 :(得分:0)
正如我所承诺的那样,只是为了这件事和参考,这里是(在使用GetNote
值之前应该除以12的模数,以排除整个八度音阶):
/// <summary>
/// The values are organized so that the note value + 10 is sharp, -10 is flat, for readability.
/// For instance, Note.C - 10 = Note.CFlat, Note.C + 10 = Note.CSharp.
/// </summary>
public enum Note
{
Silent = 0,
CFlat = -9,
DFlat = -8,
EFlat = -7,
FFlat = -6,
GFlat = -5,
AFlat = -4,
BFlat = -3,
C = 1,
D = 2,
E = 3,
F = 4,
G = 5,
A = 6,
B = 7,
CSharp = 10,
DSharp = 12,
ESharp = 13,
FSharp = 14,
GSharp = 15,
ASharp = 16,
BSharp = 17,
}
/// <summary>
/// Returns the note from a chromatic level.
/// For instance: 1 = C, 2 = Db, 6 = F, etc.
/// </summary>
/// <param name="chromaticStep"></param>
public static Note GetNote(int chromaticStep)
{
if (chromaticStep < 0 || chromaticStep > 12)
throw new ArgumentOutOfRangeException("chromaticStep",
"The value must be within the octave range.");
var diatonicStep = (chromaticStep / 2) + 1;
//determines whether it's in the upper half of the keyboard layout (> E)
var isUpperHalf = chromaticStep > 5;
var isOdd = chromaticStep % 2 != 0;
var isChromatic = isUpperHalf ? isOdd : !isOdd;
if (isChromatic)
diatonicStep += isUpperHalf ? 10 : -10;
return (Note)diatonicStep;
}
测试:
static void Main(string[] args)
{
for (int i = 1; i < 13; i++)
Console.WriteLine("{0}: {1}", i, GetNote(i));
}
结果:
1: C
2: DFlat
3: D
4: EFlat
5: E
6: F
7: FSharp
8: G
9: GSharp
10: A
11: ASharp
12: B