튜닝 문자열


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.

  • 문자열이 튜닝되는 빈도를 나타내는 숫자 (정수일 필요는 없음). 이 숫자의 정밀도는 소수점 이하 최대 4 자리입니다.

이는 주파수 사이에 존재할 것이다 전달된다고 가정 될 수있다 10 Hz40000 Hz.

입력은 원하는 형식으로 전달 될 수 있습니다. 답변에서 프로그램에 입력이 허용되는 방식을 지정하십시오.

산출

프로그램은 12 톤 균등 한 튜닝 시스템에서 가장 가까운 음표 *와 문자열로 표시된 소리가 가장 가까운 음에서 가장 가까운 음의 수를 출력해야합니다 (가장 가까운 센트로 반올림).

+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

마지막 줄에 @flawr [-X--], 문자열은 4 곳 (따라서 5 부분)으로 나뉘어지고 두 번째 부분에서 눌려집니다. 따라서을 눌렀으며 2/5사용 된 길이는 3/5입니다.
es1024

아 알았어 이제 알다시피, 각각 -기본적으로 부서의 위치를 ​​나타냅니다. 설명해 주셔서 감사합니다!
flawr

답변:


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);}

아스키 사진을 한 줄로, 별도의 줄로 주파수를받습니다.

매직 넘버 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
멋진 scanf형식 문자열의 경우 +1 당신이 할 수있을 줄 몰랐어요 나중에 당신에게 출력 코드를 확인합니다 (I는 C와 비슷한 출력을 위해 나에게 발생하지만, 내가 경쟁적으로 모든 일을 할 수있는 방법을 볼 수없는이 일에 대해 생각했다.) 나는 가정 d+9당신이 색인하고 있기 때문에입니다 음표 A는 옥타브 수를 음표 C의 색인으로 조정해야합니다.
Level River St

그렇습니다. +9는 옥타브가 C에서 시작한다는 사실을 보상합니다. 음표 이름 계산과 비슷하거나 비슷합니다. 참고 이름의 경우 순환 시프트는 LUT에 의해 구현 될 수 있지만 더 계산적인 수학적 방법을 선호합니다.
anatolyg

1

자바 스크립트 (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)}

결정된. (유럽에 살고 있으므로 Bb 대신 B를 사용하고 B = 대신 H를 사용했습니다.)


Flawr, 당신은 독일 사람입니까? 나는 항상 B와 H를 유럽식 표기법이 아닌 독일 식 표기법으로 생각했습니다. 영국과 아일랜드는 Bb와 B를 사용합니다. 스페인과 이탈리아는 SIb와 SI를 사용합니다 (DO RE MI FA SOL LA SI와 동일). 어쨌든 그것은 하나의 문자를 절약하는 것입니다.
Level River St

예, 저는 독일어를 사용하는 국가입니다. 다른 유럽 국가에서는 Doremi 시스템을 사용한다는 사실을 알지 못했습니다 (사람들이 어린이 교육에 사용한다고 들었습니다). 어쨌든 그것은 단지 1 문자를 절약하고 실제로 요구 사항을 충족시키지 못한다고 말한 이후로 농담이었습니다. =)
flawr

센트 수가 음수이면 t('[---X--]',11.7103)( 예 : (마지막 예) -10대신에 센트 수를 잘못 반올림합니다.-11
es1024

를 사용 p="C0C#0D0D#0E0F0F#0G0G#0A0B0H".split(0)하면 추가로 2자를 절약 할 수 있습니다.
Sean Latham

@ es1024 아, 알고 있어야합니다 : round(x) = x+.5|0양수에 대해서만 올바른 둥근 함수를 구현했기 때문에 나중에 수정하겠습니다. @ipi 감사합니다!
flawr

1

파이썬 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.")
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.