2013-05-05 65 views
0

我必须制作一个转换器,它接受表示当前音色(即根= 1,次秒= 2,次小七= 11,主要第九= 1)的色间隔的int。 15,主要十三= 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

为什么你关心Dictionar效率在这里?你会在循环中使用它一百万次吗?它是否为实时声音? – SimpleVar 2013-05-05 04:05:20

+0

@YoryeNathan它应该执行得非常快。我不知道在循环中是否有数百万次,但必须非常快速地工作。 – Shimmy 2013-05-05 04:10:36

+0

字典是非常好的表现,你知道。你有没有尝试过,看到它不够好?更快的方法是通过静态只读数组(非常大)直接索引 - 只有可能感谢音乐理论非常扎实。 – SimpleVar 2013-05-05 04:13:00

回答

1

你需要一个特殊的双向字典这项工作。 这里有一个: Getting key of value of a generic Dictionary?

转置可以很容易地通过模算术和通过计算音符之间的相对距离来处理。

如果您正在寻找速度,您还可以定义具有所需元素对的类,并将它们放入循环链表或二进制搜索树中。但我认为,当你只处理12个简单元素时,它并不重要。

+0

我其实已经想过了,但我更喜欢用算法来计算它。我试图找出现在,仍然没有成功。根据钢琴键盘的视觉顺序,它必须加倍色阶,这意味着除了E-F和B-C之间的半步之外,它应该将阶跃量减半。 – Shimmy 2013-05-05 03:46:47

+0

我不明白为什么“算法”方法会比这更好。你的问题听起来像你只想要如何按价值获得关键,反之亦然。 – 2013-05-05 03:50:50

+0

我需要它来计算,因为我希望它是动态和灵活的。 – Shimmy 2013-05-05 03:51:53

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 
相关问题