调弦


9

任务

编写一个程序,确定调到给定频率并在给定位置按下的弦的音调,以及失调多少分。

为简单起见,假定产生的声音的频率与按下声音的右侧的弦长成反比。

注意:此任务仅涉及基音,而不涉及泛音/其他谐波。

输入项

您的程序获得了两条数据:

  • 任意长度的字符串,表示所讨论的字符串。该字符串将用X标记,该字符串将被按下。

    [-----] is a string divided in six sections (five divisions).
    [--X--] is a string pressed at the exact center of the string.
    [X----] is a string pressed at 1/6 the length of the string. (Length used is 5/6)
    [-X--] is a string pressed at 2/5 of the length of the string. (Length used is 3/5)
    

    假设音符使用右侧的字符串部分来发声X

  • 一个数字(不一定是整数),表示调弦的频率。该数字的精度最多为十进制小数点后四位。

可以假设通过的频率在10 Hz和之间40000 Hz

输入可以您选择的格式传递。请在答案中指定如何将输入接受到程序中。

输出量

您的程序必须输出在十二音调相同的音调系统中最接近的音符*,以及输出最接近的音符的美分数,以该字符串表示的声音将被(舍入为最接近的美分)。

+n应使用n美分表示钞票上方-n/下方的美分,以及用于在钞票上方/下方表示美分的美分。

注释应以科学的音高符号输出。假设A4已调至440Hz。使用b和#表示平坦/清晰音符。注意:可以使用锋利的或平坦的。对于的注释466.16Hz,可以输出A#Bb

输出格式取决于您,只要输出仅包含两个先前指定的信息即可(即,不允许打印每个可能的输出)。

*最接近的音符是指与输入所表示的声音最接近的音符,以美分为单位(因此,50 cents声音中的音符)。如果声音50 cents远离两个不同的音符(四舍五入后),则可以输出两个音符中的任何一个。

例子

您的程序应适用于所有情况,而不仅仅是以下示例。

Output             Input Frequency   Input String
A4,  +0  cents     220               [-----X-----]
A5,  +0  cents     220               [--------X--]
D5,  -2  cents     440               [--X--------]
B4,  -49 cents     440               [X----------]
A#4, +19 cents*    314.1592          [X-]
Eb9, +8  cents*    400               [-----------------------X]
Eb11,+8  cents*    100               [--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------X]
D#1, +49 cents*    10                [--X]
A0,  -11 cents     11.7103           [---X--]

*可能已经输出了尖锐或平坦。

可能有用的链接

这是 如此短的答案胜出。


我认为您的示例有些不一致:根据第一个[--X--]字符串,将字符串按在x放置的分隔的中间,而[-X--]按照此逻辑,最后一个字符串应为3/8(而不是2/5)。还是我理解不对?
瑕疵的

对于最后一个@flawr [-X--],将字符串分成4个位置(因此分为5个部分),并在这些划分的第二个位置按。因此,将其按2/5,使用的长度为3/5
es1024

好的,现在我明白了,所以每个-基本上代表了部门的位置,谢谢您的解释!
瑕疵的

Answers:


1

BBC基础版161#

  REM get frequency and string. Store length of string in n for later.
  INPUT f,s$
  n=LEN(s$)

  REM store floating-point value of note in semitones above (C0-0.5). Store integer value in n% (offset effectively means it will be rounded not truncated.)
  n=LN(f*(n-1)/(n-INSTR(s$,"X"))/15.8861)/LN(2)*12
  n%=n

  REM format printing to whole numbers only
  @%=2^17

  REM Output note name and octave. Output cents (discrepancy between n and n%, minus the offset of 0.5)
  PRINT MID$("C C#D D#E F F#G G#A A#B ",n%MOD12*2+1,2);INT(n/12)'(n-0.5-n%)*100'

分数不包括评论。还没打高尔夫球。

输出量

在除两个较长的测试用例之外的所有测试用例上都能正确执行。对于Eb9测试用例,似乎缺少一个破折号:有22 -和一个X,将字符串分成24个相等的部分。根据我的手动计算,这是9600Hz,比D9高37美分。这正是我的程序输出的结果。如果再加上一个破折号,我将得到Eb9 + 8美分。不幸的是,BBC Basic无法处理超过255个字符的字符串,因此Eb11大小写会出错。

在此处输入图片说明


3

C,179

main(n,d){float f;scanf("%*[^X]%nX%*[-]%n]%f",&n,&d,&f);f=log(f*d/(d-n))*17.3123-57.376;n=d=f+.5;n=n%12*7+784;printf("%c%d%c,%+2.0f cents\n",n/12,(d+9)/12,n%12/7*3+32,(f-d)*100);}

单独在一行上接收ascii图片,并在单独的一行上接收频率。

可以通过降低幻数17.3123和的准确性来删除一些字符57.376

没有打高尔夫球,该程序如下所示:

main(n,d)
{
    float f; // 'float' and '%f' better than 'double' and '%lf'

    scanf("%*[^X]%nX%*[-]%n]%f", &n, &d, &f);
    // n is the number of chars before 'X'
    // d is the number of chars before ']'
    // f is the frequency

    // Calculate the tuned frequency
    f = f * d / (d - n);

    // Convert the frequency to logarithmic scale, relative to pitch A0
    f=log(f)*17.3123-57.376;
    // alternatively: f = log2(f / (440 / 16)) * 12;

    // Round to nearest integer
    n=d=f+.5;

    // Calculate the note name ('A', 'B', etc), multipled by 12 for convenience
    n=n%12*7+784;

    printf("%c%d%c,%+2.0f cents\n", // output example: B4 ,-49 cents
        n/12,        // note name
        (d+9)/12,    // octave number
        n%12/7*3+32, // if n%12 is large enough, it's '#' else ' ' (natural)
        (f-d)*100);  // number of cents; stdio rounds it to integer
}

2
+1为超赞的scanf格式字符串。我不知道你能做到这一点。稍后,我将检查您的输出代码(我曾考虑过用C进行此操作,尽管我的输出发生了类似的事情,但我看不到有竞争力的方法来完成整件事。)我想d+9是因为您已经索引了注意A,因此您必须将八度数调整为C的索引:我想知道是否有解决方法。
级圣河

是的,+ 9可以补偿八度从C开始的事实。这是对音符名称的计算的一种或类似的解决方法。对于音符名称,可以通过LUT来实现循环移位,但是我喜欢计算它们的更“数学”的方式。
anatolyg 2014年

1

JavaScript(199)

称呼为 t('[X-]',314.1592)

t=(s,f)=>{l=s.length-1;p='C C# D D# E F F# G G# A B H'.split(' ');n=12*Math.log2(f*l/(l-s.indexOf('X'))/16.3515978);m=n+.5|0;return p[m%12]+(n/12|0)+' '+((n-m)*100+.5|0)}

固定。(因为我住在欧洲,所以我用B代替Bb,用H代替B =)


Flawr,你是德国人吗?我一直认为B和H是德语符号,而不是欧洲符号。英国和爱尔兰使用Bb和B。西班牙和意大利使用SIb和SI(与DO RE MI FA SOL LA SI。一样)。无论如何,这只是节省一个字符。
级圣河

是的,我是一个讲德语的国家,我不知道其他欧洲国家在使用Doremi系统(我只是听说有人在儿童教育中使用它)。反正它是primarly一个笑话,因为正如你说,这不仅节省了1个char和并不真正符合要求=)
flawr

如果美t('[---X--]',11.7103)-10-11
分数

使用p="C0C#0D0D#0E0F0F#0G0G#0A0B0H".split(0)可以为您节省另外2个字符。
肖恩·拉瑟姆

@ es1024哦,我应该知道:这是因为我实现了round(x) = x+.5|0仅对正数正确的舍入函数,稍后将对其进行修复。@ipi谢谢!
瑕疵的

1

的Python 3:175

import math
def t(b,s):l=len(s)-1;n=12*math.log2(b*l/(l-s.index("X"))/16.35);m=round(n);return"%s%s%+d"%(("C C# D D# E F F# G G# A A# B".split()*99)[m],m//12,round(100*(n-m)))

取消高尔夫:

import math

c0 = 16.35

def tuning (base_frequency, string):
    return formatted (note_number (frequency (base_frequency, string)))

def formatted (note_number):
    return "{name}{octave:d}{cents:+d}".format (name=note_name (note_number),
                             octave=octave (note_number),
                             cents=cents_out (note_number))

def note_name (note_number):
    return ("C C# D D# E F F# G G# A A# B".split() * 99)[round (note_number)]

def note_number (frequency):
    return 12 * math.log2 (frequency / c0)

def octave (note_number):
    return round (note_number) // 12

def cents_out (note_number):
    return round (100 * (note_number - round (note_number)))

def frequency (base_frequency, string):
    string_length = len (string) - 1
    held_length = string_length - string.index ("X")
    return base_frequency * string_length / held_length

if "__main__" == __name__:

    print ("Testing functions against known values...")
    assert "A4+0"     == tuning (220,      "[-----X-----]")
    assert "A5+0"     == tuning (220,      "[--------X--]")
    assert "D5-2"     == tuning (440,      "[--X--------]")
    assert "B4-49"    == tuning (440,      "[X----------]")
    assert "A#4+19"   == tuning (314.1592, "[X-]")
    assert "D#9+8"    == tuning (400,      "[-----------------------X]")
    assert "D#11+8"   == tuning (100,      "[--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------X]")
    assert "D#1+49"   == tuning (10,       "[--X]")
    assert "A0-11"    == tuning (11.7103,  "[---X--]")
    print ("Tests passed.")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.