Tần số của ghi chú này là gì?


21

Làm mới âm nhạc nhanh chóng:

Bàn phím piano bao gồm 88 nốt nhạc. Trên mỗi quãng tám, có 12 nốt, C, C♯/D♭, D, D♯/E♭, E, F, F♯/G♭, G, G♯/A♭, A, A♯/B♭B. Mỗi lần bạn nhấn 'C', mẫu sẽ lặp lại quãng tám cao hơn.

nhập mô tả hình ảnh ở đây

Một ghi chú được xác định duy nhất bởi 1) chữ cái, bao gồm bất kỳ vật sắc nhọn hoặc căn hộ nào và 2) quãng tám, là một số từ 0 đến 8. Ba nốt đầu tiên của bàn phím, là A0, A♯/B♭B0. Sau đó, thang màu đầy đủ trên quãng tám 1. C1, C♯1/D♭1, D1, D♯1/E♭1, E1, F1, F♯1/G♭1, G1, G♯1/A♭1, A1, A♯1/B♭1B1. Sau đó, thang màu đầy đủ trên các quãng tám 2, 3, 4, 5, 6 và 7. Sau đó, ghi chú cuối cùng là a C8.

Mỗi nốt tương ứng với một tần số trong dải 20-4100 Hz. Với việc A0bắt đầu ở chính xác 27.500 hertz, mỗi ghi chú tương ứng là ghi chú trước nhân với gốc thứ mười hai của hai, hoặc khoảng 1.059463. Một công thức tổng quát hơn là:

nhập mô tả hình ảnh ở đây

Trong đó n là số ghi chú, với A0 là 1. (Thông tin thêm ở đây )

Các thách thức

Viết chương trình hoặc hàm lấy một chuỗi biểu thị một ghi chú và in hoặc trả về tần số của ghi chú đó. Chúng tôi sẽ sử dụng dấu #thăng cho biểu tượng sắc nét (hoặc hashtag cho bạn trẻ) và chữ thường bcho biểu tượng phẳng. Tất cả các đầu vào sẽ trông như (uppercase letter) + (optional sharp or flat) + (number)không có khoảng trắng. Nếu đầu vào nằm ngoài phạm vi của bàn phím (thấp hơn A0 hoặc cao hơn C8) hoặc có ký tự không hợp lệ, thiếu hoặc thừa, đây là đầu vào không hợp lệ và bạn không phải xử lý nó. Bạn cũng có thể giả định một cách an toàn rằng bạn sẽ không nhận được bất kỳ đầu vào kỳ lạ nào như E # hoặc Cb.

Độ chính xác

Vì độ chính xác vô hạn không thực sự có thể, chúng tôi sẽ nói rằng bất cứ điều gì trong một phần trăm giá trị thực đều có thể chấp nhận được. Không đi sâu vào chi tiết, một xu là gốc thứ 1200 của hai, hoặc 1.0005777895. Hãy sử dụng một ví dụ cụ thể để làm cho nó rõ ràng hơn. Giả sử đầu vào của bạn là A4. Các chính xác giá trị của ghi chú này là 440 Hz. Một khi cent phẳng là 440 / 1.0005777895 = 439.7459. 440 * 1.0005777895 = 440.2542Do đó, một khi sắc nét là Do đó, bất kỳ số nào lớn hơn 439.7459 nhưng nhỏ hơn 440.2542 là đủ chính xác để đếm.

Các trường hợp thử nghiệm

A0  --> 27.500
C4  --> 261.626
F#3 --> 184.997
Bb6 --> 1864.66
A#6 --> 1864.66
A4  --> 440
D9  --> Too high, invalid input.
G0  --> Too low, invalid input.
Fb5 --> Invalid input.
E   --> Missing octave, invalid input
b2  --> Lowercase, invalid input
H#4 --> H is not a real note, invalid input.

Hãy nhớ rằng bạn không phải xử lý các đầu vào không hợp lệ. Nếu chương trình của bạn giả vờ rằng chúng là đầu vào thực và in ra một giá trị, điều đó có thể chấp nhận được. Nếu chương trình của bạn gặp sự cố, điều đó cũng được chấp nhận. Bất cứ điều gì có thể xảy ra khi bạn nhận được một. Để biết danh sách đầy đủ các đầu vào và đầu ra, xem trang này

Như thường lệ, đây là môn đánh gôn, vì vậy các sơ hở tiêu chuẩn được áp dụng và câu trả lời ngắn nhất tính theo byte sẽ thắng.


9
"H # 4 -> H không phải là ghi chú thực, đầu vào không hợp lệ." Ngoại trừ ở châu Âu.
Lui

6
@Lui điều gì về châu Âu như thể toàn bộ châu Âu sử dụng H? Hcó nghĩa là B là AFAIK chỉ được sử dụng ở các nước nói tiếng Đức. ( Bcó nghĩa là Bb bằng cách này.) Những gì người Anh và Ailen gọi B được gọi là Si hoặc Ti ở Tây Ban Nha và Ý, như trong Do Re Mi Fa Sol La Si.
Cấp sông St

3
Tôi đã chơi B♯2 trên viola trước đây, đó là một ghi chú hoàn toàn hợp lý và không có gì lạ cả.
Neil

3
@steveverrill Hđược sử dụng ở Đức, Cộng hòa Séc, Slovakia, Ba Lan, Hungary, Serbia, Đan Mạch, Na Uy, Phần Lan, Estonia và Áo, theo Wikipedia . (Tôi cũng có thể tự xác nhận nó cho Phần Lan.)
PurkkaKoodari

6
@Neil Có lẽ chỉ là tình cờ. ;)
cốc

Câu trả lời:


21

Japt, 41 37 35 34 byte

Cuối cùng tôi cũng có cơ hội để ¾sử dụng tốt! :-)

55*2pU¬®-1¾ª"C#D EF G A B"bZ /C} x

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

          // Implicit: U = input string, C = 12
U¨    }  // Take U, split into chars, and map each item Z by this function:
-1¾       //  Subtract 1.75 from Z. This produces NaN for non-digits.
ª"..."bZ  //  If the result is falsy (NaN), instead return the index of Z in this string.
          //  C produces 0, D -> 2, E -> 4, F -> 5, G -> 7, A -> 9, B -> 11.
          //  # -> 1, and b -> -1, so we don't need to calculate them separately.
/C        //  Divide the index by 12.
x         // Sum.
2p        // Take 2 to the power of the result.
55*       // Multiply by 55.

Các trường hợp thử nghiệm

Tất cả các trường hợp kiểm tra hợp lệ đi qua tốt. Đó là những thứ không hợp lệ, nơi nó trở nên kỳ lạ ...

input --> output       (program's reasoning)
A0  --> 27.5           (Yep, I can do that for you!)
C4  --> 261.625565...  (Yep, I can do that for you!)
F#3 --> 184.997211...  (Yep, I can do that for you!)
Bb6 --> 1864.6550...   (Yep, I can do that for you!)
A#6 --> 1864.6550...   (Yep, I can do that for you!)
A4  --> 440            (Yep, I can do that for you!)
D9  --> 9397.27257...  (Who says that's too high?)
G0  --> 24.49971...    (I've heard that note before.)
Fb5 --> 659.25511...   (Wait, Fb isn't supposed to be a note?)
E   --> 69.295657...   (I'm gonna guess that the missing octave is 1¾.)
b2  --> 61.735412...   (I assume that b means Cb...)
H#4 --> 261.625565...  (H# is C!)

13
+ Để sử dụng ¾ :)
anatolyg

1
Đây thực sự không phải là 38 byte ?
Patrick Roberts

@PatrickRoberts Đây là 38 byte trong UTF-8, nhưng Japt sử dụng mã hóa ISO-8859-1 , trong đó mỗi ký tự chính xác là một byte.
Sản phẩm ETH

8

Pyth, 46 44 43 42 39 35 byte

*55^2tsm.xsdc-x"C D EF GbA#B"d9 12z

Hãy thử trực tuyến. Bộ thử nghiệm.

Mã hiện sử dụng một thuật toán tương tự như câu trả lời Japt của ETHproductions , vì vậy hãy tin tưởng vào điều đó.

Giải trình

                                            implicit: z = input
       m                          z         for each character in input:
          sd                                  try parsing as number
        .x                                    if that fails:
               "C D EF GbA#B"                   string "C D EF GbA#B"
              x              d                  find index of character in that
             -                9                 subtract 9
            c                   12              divide by 12
      s                                     sum results
     t                                      decrement
   ^2                                       get the correct power of 2
*55                                         multiply by 55 (frequency of A1)

Phiên bản cũ (42 byte, 39 w / chuỗi đóng gói)

*55^2+tsezc+-x"C D EF G A B"hz9-}\#z}\bz12

Giải trình


Hay đấy. Làm thế nào để gói Pyth?
Luis Mendo

@LuisMendo Bạn có thể tìm thấy thông tin về điều đó trong các tài liệu . Về cơ bản, nó tìm thấy cơ sở nhỏ nhất để chuyển đổi dữ liệu và sau đó mã hóa kết quả trong cơ sở 256.
PurkkaKoodari

7

Toán học, 77 byte

2^((Import[".mid"~Export~Sound@SoundNote@#,"RawData"][[1,3,3,1]]-69)/12)440.&

Giải thích :

Ý tưởng chính của chức năng này là chuyển đổi chuỗi ghi chú sang cao độ tương đối của nó, sau đó tính tần số của nó.

Phương pháp tôi sử dụng là xuất âm thanh sang midi và nhập dữ liệu thô, nhưng tôi nghi ngờ rằng có một cách thanh lịch hơn.


Các trường hợp thử nghiệm :

f=%; (* assign the function above to f *)
f["A4"]    (* 440.    *)
f["A5"]    (* 880.    *)
f["C#-1"]  (* 8.66196 *)
f["Fb4"]   (* 329.628 *)
f["E4"]    (* 329.628 *)
f["E"]     (* 329.628 *)

2
Thông thường tôi rất buồn khi thấy các bản dựng Mathicala giải quyết vấn đề một cách tầm thường, nhưng đây thực sự là một cách khá truyền cảm để làm điều đó.
Robert Fraser

4

MATL , 56 53 50 49 48 byte

Hj1)'C D EF G A B'=f22-'#b'"G@m]-s+ 12/G0)U+^55*

Sử dụng bản phát hành hiện tại (10.1.0) , sớm hơn thử thách này.

Hãy thử trực tuyến !

Giải trình

H                   % push 2
j1)                 % get input string. Take first character (note)
'C D EF G A B'=f    % find index of note: 1 for C, 3 for D...
22-                 % subtract 22. This number comes from three parts:
                    % 9; 1 for 0-based indexing; 12 to subtract 1 octave
'#b'"G@m]-s         % For loop. Gives 1 if input contains '#', -1 if 'b', 0 otherwise
+                   % add to previous number. Space needed to separate from next literal
12/                 % divide by 12
G0)                 % push input and get last character (octave)
U+                  % convert to number and add to previous number
^                   % raise 2 (that was initially pushed) to accumulated number 
55*                 % multiply by 55 (=27.5*2). Implicitly display


3

Ruby, 69 65

->n{2**((n.ord*13/8%12-n.size+(n=~/#/?7:5))/12.0+n[-1].to_i)*55/4}

Ungolfed trong chương trình thử nghiệm

f=->n{
  2**(                    #raise 2 to the power of the following expression:
   (
     n.ord*13/8%12-       #note name C..B maps to number 0..11 calculated from the ascii code of n[0] 
     n.size+(n=~/#/?7:5)  #Correction for flat: length of n is 1 more for flat (or sharp) than for natural. Then apply correction for sharp
                          #now we have a number 3..14 for C..B (so 12 for A, will be a whole number when divided)
   )/12.0+                #divide by 12 to convert into a fraction of an octave

  n[-1].to_i              #add the octave number, last character in n
  )*                      #end of power expression, now we have A0=2,A1=4,A2=4 etc

  55/4                    #multiply to get correct frequency, this is shorter than 13.75 or 440/32                      
}

#complete octave test case
puts %w{A0 A#0 Bb0 B0 C1 C#1 Db1 D1 D#1 Eb1 E1 F1 F#1 Gb1 G1 G#1 Ab1 A1 A#1}.map{|e|[e,f[e]]}

#test case per OP
puts %w{A0 C4 F#3 Bb6 A#6}.map{|e|[e,f[e]]}

Đầu ra

A0
27.5
A#0
29.13523509488062
Bb0
29.13523509488062
B0
30.867706328507758
C1
32.70319566257483
C#1
34.64782887210901
Db1
34.64782887210901
D1
36.70809598967595
D#1
38.890872965260115
Eb1
38.890872965260115
E1
41.20344461410875
F1
43.653528929125486
F#1
46.2493028389543
Gb1
46.2493028389543
G1
48.999429497718666
G#1
51.91308719749314
Ab1
51.91308719749314
A1
55.0
A#1
58.27047018976123
A0
27.5
C4
261.6255653005986
F#3
184.9972113558172
Bb6
1864.6550460723593
A#6
1864.6550460723593

2

ES7, 82 byte

s=>55*2**(+s.slice(-1)+("C D EF G A B".search(s[0])+(s[1]<'0')-(s[1]>'9')-21)/12)

Trả về 130.8127826502993 cho đầu vào của "B # 2" như mong đợi.

Chỉnh sửa: Đã lưu 3 byte nhờ @ user81655.


@ user81655 2*3**3*2là 108 trong bảng điều khiển trình duyệt của Firefox, đồng ý với 2*(3**3)*2. Cũng lưu ý rằng trang đó cũng nói rằng ?:có quyền ưu tiên cao hơn =nhưng họ thực sự có quyền ưu tiên như nhau (xem xét a=b?c=d:e=f).
Neil

À, được rồi Firefox của tôi không có **nên tôi chưa bao giờ có thể kiểm tra nó. Tôi nghĩ rằng ?:có một quyền ưu tiên cao hơn =mặc dù bởi vì trong ví dụ của bạn ađược đặt thành kết quả của ternary, chứ không phải b, sau đó thực hiện ternary. Hai nhiệm vụ khác được đính kèm trong ternary vì vậy chúng là một trường hợp đặc biệt.
dùng81655

@ user81655 Làm thế nào là e=fbên trong chim nhạn ?
Neil

Hãy xem xét a=b?c=d:e=f?g:h. Nếu chúng có cùng mức ưu tiên và lần thứ ba kết thúc vào lúc =sau e, nó sẽ gây ra lỗi gán tay trái không hợp lệ.
dùng81655

@ user81655 Nhưng đó cũng sẽ là một vấn đề nếu ?:có quyền ưu tiên cao hơn =dù sao đi nữa. Các biểu thức cần phải nhóm như thể nó là a=(b?c=d:(e=(f?g:h))). Bạn không thể làm điều đó nếu họ không có quyền ưu tiên.
Neil

2

C, 123 byte

float d(char*s){int n=*s++,m=(n*12+(n<67?90:6))/7,o=*s++,a=o^35?o^98?0:-1:1;return exp((m+(a?*s++:o)*12+a)/17.3123-37.12);}

Sử dụng:

#include <stdio.h>
#include <math.h>

float d(char*s){int n=*s++,m=(n*12+(n<67?90:6))/7,o=*s++,a=o^35?o^98?0:-1:1;return exp((m+(a?*s++:o)*12+a)/17.3123-37.12);}

int main()
{
    printf("%f\n", d("A4"));
}

Giá trị tính toán luôn nhỏ hơn khoảng 0,8 cent so với giá trị chính xác, vì tôi đã cắt càng nhiều chữ số càng tốt từ các số dấu phẩy động.

Tổng quan về mã:

float d(char*s){
    int n=*s++,        // read the letter
        m=(n*12+       // multiply by 12/7 to convert from A...G to 0...11
        (n<67?90:6)    // if A or B, add 1 octave; also add some fix-up rounding value
        )/7,

        o=*s++,        // read next char: the octave digit or accidental

        a=o^35?o^98?0:-1:1; // if accidental, convert it into +1 or -1; else 0

        return exp((m+ // I adjusted the factors to use exp instead of pow
            (a?*s++:o) // if was accidental, now read the octave digit
            *12+a)/
            17.3123-   // a more exact value is 17.3123404447
            37.12);    // a more exact value is 37.1193996632
}

1

R, 157 150 141 136 byte

f=function(x){y=strsplit(x,"")[[1]];55*2^(as.double(y[nchar(x)])-1+(c(10,12,1,3,5,6,8)[LETTERS==y[1]]-switch(y[2],"#"=9,"b"=11,10))/12)}

Với thụt lề và dòng mới:

f=function(x){
     y=strsplit(x,"")[[1]]
     55 * 2^(as.double(y[nchar(x)]) - 1 + 
         (c(10,12,1,3,5,6,8)[LETTERS==y[1]] - 
         switch(y[2],"#"=9,"b"=11,10))/12)
     }

Sử dụng:

> f("A0")
[1] 27.5
> f("C8")
[1] 4186.009
> sapply(c("C4","Bb6","A#6","A4"),f)
       C4       Bb6       A#6        A4 
 261.6256 1864.6550 1864.6550  440.0000 

1

Python, 97 95 byte

def f(n):a,*b,c=n;return 2**(int(c)+('C@D@EF@G@A@B'.find(a)-(21,(22,20)['#'in b])[b>[]])/12)*55

Dựa trên cách tiếp cận cũ của Pietu1998 (và những người khác) trong việc tìm kiếm chỉ mục của ghi chú trong chuỗi 'C@D@EF@G@A@B'cho một số char trống hoặc khác. Tôi sử dụng giải nén lặp để phân tích chuỗi ghi chú mà không có điều kiện. Tôi đã làm một chút đại số ở cuối để đơn giản hóa biểu thức chuyển đổi. Không biết liệu tôi có thể rút ngắn lại mà không thay đổi cách tiếp cận của mình không.


1
Tôi nghĩ rằng b==['#']có thể được rút ngắn xuống còn '#'in b, và not bđể b>[].
Zgarb

Điểm hay! Làm việc cho bộ thử nghiệm của tôi, cảm ơn. Tôi nghĩ rằng tôi có thể cải thiện việc chơi golf xuống các điều kiện trong Python một chút công bằng, cảm ơn.
Ogaday

1

Ngôn ngữ Wolfram (Mathicala), 69 byte

ToExpression@("Music`"<>StringReplace[#,{"b"->"flat","#"->"sharp"}])&

Sử dụng gói nhạc , chỉ cần nhập ghi chú dưới dạng biểu thức sẽ đánh giá tần số của nó, như sau:

 In[1]:= Eflat3
Out[1]:= 155.563

Để lưu byte bằng cách tránh nhập gói với <<Music, tôi đang sử dụng tên đủ điều kiện : Music`Eflat3. Tuy nhiên, tôi vẫn phải thay thế bbằng flat#bằng sharpđể phù hợp với định dạng đầu vào của câu hỏi, điều mà tôi làm với một cách đơn giản StringReplace.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.