正如我说过的,只是事情的缘故,并为参考,这(使用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
为什么你关心Dictionar效率在这里?你会在循环中使用它一百万次吗?它是否为实时声音? – SimpleVar 2013-05-05 04:05:20
@YoryeNathan它应该执行得非常快。我不知道在循环中是否有数百万次,但必须非常快速地工作。 – Shimmy 2013-05-05 04:10:36
字典是非常好的表现,你知道。你有没有尝试过,看到它不够好?更快的方法是通过静态只读数组(非常大)直接索引 - 只有可能感谢音乐理论非常扎实。 – SimpleVar 2013-05-05 04:13:00