Apa yang baru saja saya mainkan? Terjemahkan jari gitar ke akord

22

Terkait: Musik: ada apa di chord ini? , Catatan untuk Tablature , Membuat tab gitar? , Terjemahkan pasangan nomor ke catatan gitar

Diberi fingering gitar, mengeluarkan akor yang diwakilinya. Anda dapat menggunakan input dan output standar, atau menulis fungsi yang mengembalikan string.

Masukan jari akan dapat diklasifikasikan sebagai salah satu akord berikut, untuk dinyatakan sebagai berikut (jika catatan root adalah C):

  • triad utama: C
  • triad kecil: Cm
  • (dominan) ketujuh: C7
  • ketujuh minor: Cm7

Chord mungkin terbalik, jadi Anda tidak bisa mengandalkan nada terendah sebagai root. Anda juga tidak dapat mengandalkan ini sebagai penjarian yang mudah atau umum di dunia nyata. Secara umum, output program Anda harus mengabaikan oktaf nada, dan memperlakukan semua nada yang sesuai dengan not musik yang sama (yaitu, A) sama.

Ini adalah , jadi kode terpendek dalam byte menang.

Masukkan format

Input adalah serangkaian 6 nilai yang menunjukkan, untuk setiap string gitar 6-string dalam penyetelan standar (EADGBE), yang membuat fret string itu dimainkan. Bisa juga menunjukkan bahwa string tidak dimainkan sama sekali. Fret "nol" juga dikenal sebagai posisi terbuka, dan nomor fret dihitung dari sana. Asumsikan gitar memiliki 21 posisi fret, sehingga posisi fret tertinggi adalah angka 20.

Misalnya, input X 3 2 0 1 0berarti menempatkan jari pada posisi berikut di bagian atas leher gitar:

(6th) |---|---|---|---|---
      |-X-|---|---|---|---
      |---|---|---|---|---
      |---|-X-|---|---|---
      |---|---|-X-|---|---
(1st) |---|---|---|---|---

dan memetik senar ke-2 sampai ke-6. Itu sesuai dengan tab ASCII ini :

e |-0-|
B |-1-|
G |-0-|
D |-2-|
A |-3-|
E |---|

Anda memiliki fleksibilitas dalam memilih jenis input yang Anda inginkan: setiap posisi fret dapat dinyatakan sebagai string, atau angka. Senar gitar yang tidak dimainkan biasanya ditandai dengan huruf X, tetapi Anda dapat memilih nilai sentinel yang berbeda jika itu memudahkan Anda (seperti -1jika Anda menggunakan angka). Rangkaian 6 posisi fret dapat dimasukkan sebagai daftar, larik, atau jenis urutan apa pun, string berpisah satu ruang, atau sebagai input standar — sekali lagi, pilihan Anda.

Anda dapat mengandalkan input yang sesuai dengan salah satu dari 4 jenis akor yang disebutkan di atas.

Tolong jelaskan dalam posting Anda bentuk input apa yang diambil oleh solusi Anda.

Format output

Anda harus kembali atau mencetak ke output standar string yang menggambarkan akord untuk fingering. Tali ini terdiri dari dua bagian yang disatukan. Huruf besar penting. Trailing whitespace diizinkan.

Bagian pertama menunjukkan catatan akar , salah A, A#/ Bb, B, C, C#/ Db, D, D#/ Eb, E, F, F#/ Gb, Gatau G#/ Ab. (Saya menggunakan #bukan , dan bbukan , untuk menghindari membutuhkan Unicode.) Catatan akar yang dapat dinyatakan tanpa tajam atau datar harus dinyatakan tanpa mereka (tidak pernah keluaran B#, Fbatau Dbb); mereka yang tidak dapat harus diekspresikan dengan simbol tunggal tajam atau datar (yaitu salah satu C#atau Db, tetapi tidak pernah B##). Dengan kata lain, Anda harus meminimalkan jumlah kecelakaan (benda tajam atau flat) dalam nama catatan itu.

Bagian kedua menunjukkan jenis akord, baik kosong untuk triad utama, muntuk triad kecil, 7untuk ketujuh yang dominan, atau m7untuk ketujuh kecil. Jadi G mayor adalah keluaran hanya sebagai G, sedangkan D♯ minor ketujuh bisa keluaran sebagai salah satu D#m7atau Ebm7. Lebih banyak contoh dapat ditemukan dalam kasus uji di akhir.

Teori & petunjuk

Not balok

Skala berwarna memiliki 12 nada per oktaf. Ketika disetel ke temperamen yang sama, masing-masing nada ini sama-sama jauh dari tetangganya 1 . Pitch dengan jarak 12 semitone (satu oktaf) dianggap not musik yang sama. Ini berarti kita dapat memperlakukan catatan seperti bilangan bulat modulo 12, dari 0 hingga 11. Tujuh di antaranya diberi nama huruf 2 dari A hingga G. Ini tidak cukup untuk memberi nama semua 12 nada, tetapi menambahkan perbaikan tidak disengaja itu: menambahkan ♯ ( tajam) ke not membuatnya semitone lebih tinggi, dan menambahkan ♭ (flat) menjadikannya semitone lebih rendah.

Akord

Chord adalah 2 atau lebih not yang dimainkan bersama. Jenis akor tergantung pada hubungan antar not, yang dapat ditentukan oleh jarak antara not. Akor memiliki catatan root, seperti yang disebutkan sebelumnya. Kami akan memperlakukan catatan root sebagai 0 dalam contoh-contoh ini, tetapi ini arbitrer, dan yang terpenting dalam tantangan ini adalah jarak antara catatan dalam modulo aritmatika. Akan selalu ada satu jenis akor unik untuk jawabannya, baik akor triad atau ketujuh . Catatan root tidak akan selalu menjadi nada dengan frekuensi terendah; pilih catatan root sedemikian rupa sehingga Anda dapat menggambarkan akor sebagai salah satu dari empat jenis akor berikut:

  • Sebuah triad utama adalah akord dengan catatan 0 4 7.
  • Sebuah triad minor adalah akord dengan catatan 0 3 7.
  • Sebuah ketujuh dominan (atau besar / kecil) chord memiliki catatan 0 4 7 10.
  • Sebuah minor (atau minor / minor) ketujuh chord memiliki catatan 0 3 7 10. 3

Tuning gitar

Penyeteman standar pada gitar 6 senar dimulai dengan E pada senar terendah, dan kemudian mengenai nada pada interval 5, 5, 5, 4, kemudian 5 semitone menaiki senar. Mengambil E terendah sebagai 0, ini berarti memetik semua senar gitar memberi Anda nada bernomor 0 5 10 15 19 24, yang modulo 12 setara dengan 0 5 10 3 7 0, atau not E A D G B E.

Contoh yang berhasil

Jika input Anda 0 2 2 0 0 0, ini sesuai dengan catatan E B E G B E, jadi hanya E, B, dan G. Ini membentuk akord Em, yang dapat dilihat dengan memberi nomor dengan root sebagai E, memberi kami 0 3 7. (Hasilnya akan sama untuk X 2 X 0 X 0, atau 12 14 14 12 12 12.)

Jika input Anda 4 4 6 4 6 4, beri nomor dengan akar C♯ berikan 7 0 7 10 4 7, atau 0 4 7 10, jadi jawabannya adalah C#7(atau Db7). Jika sebaliknya 4 4 6 4 5 4, penomoran akan memberi 7 0 7 10 3 7, atau 0 3 7 10, yang C#m7(atau Dbm7).

Uji kasus

X 3 2 0 1 0  --->  C
0 2 2 0 0 0  --->  Em
X 2 X 0 X 0  --->  Em
4 4 6 4 6 4  --->  C#7  (or Db7)
4 4 6 4 5 4  --->  C#m7 (or Dbm7)
0 2 2 1 0 0  --->  E
0 0 2 2 2 0  --->  A
X X 4 3 2 2  --->  F#   (or Gb)
3 2 0 0 0 1  --->  G7
X X 0 2 1 1  --->  Dm7
3 3 5 5 5 3  --->  C
4 6 6 5 4 4  --->  G#   (or Ab)
2 2 4 4 4 5  --->  B7
0 7 5 5 5 5  --->  Am7
7 6 4 4 X X  --->  B
8 6 1 X 1 3  --->  Cm
8 8 10 10 9 8 -->  Fm
0 19 5 16 8 7 -->  Em
6 20 0 3 11 6 -->  A#   (or Bb)
X 14 9 1 16 X -->  G#m  (or Abm)
12 14 14 12 12 12 --> Em
15 14 12 12 12 15 --> G
20 X 20 20 20 20  --> Cm7
X 13 18 10 11 10  --> A#7 (or Bb7)

1 oleh logaritma frekuensi mereka

2 atau, dalam solfège , nama seperti do, re, mi . Dalam tantangan ini, gunakan nama surat.

3 Ini juga bisa disebut akor keenam utama, dengan pilihan catatan root yang berbeda. Dalam tantangan ini, sebut saja dengan nama ketujuh minor.

Dan Getz
sumber
3
Tantangan besar!
Luis Mendo
1
Tergoda untuk menutup sebagai penipu dari tantangan masa depan saya: D (saya memiliki tantangan yang sangat mirip dalam pikiran, tetapi Anda dengan cepat lebih cepat.)
flawr
Apakah trailing whitespace diizinkan dalam string output?
Luis Mendo
@LuisMendo yakin; tidak apa-apa.
Dan Getz
1
@ tidak resmi, tidak, Anda tidak perlu menangani situasi lain. Anda dapat menganggap itu akan selalu menjadi salah satu dari 4 tipe akor tersebut. Dengan kata lain, kode Anda dapat melakukan apa pun yang Anda inginkan (termasuk kesalahan atau memberikan jawaban yang salah) jika mendapat kunci yang berbeda.
Dan Getz

Jawaban:

9

MATL , 115 114 byte

[OAXICO]+tZN~)Y@!"@t1)XH- 12\XzXJK7hm?O.]JI7hm?'m'.]J[KCX]m?'7'.]J[ICX]m?'m7'.]]'FF#GG#AA#BCC#DD#E'l2741B~QY{HX)wh

Format input adalah [N 3 2 0 1 0], di mana Nmenunjukkan string yang tidak digunakan.

String output selalu digunakan #, bukan b.

Cobalah online! Atau verifikasi semua kasus uji, dalam dua bagian untuk menghindari penghentian waktu kompilator online:

Penjelasan

[OAXICO]            % Push [0 5 10 3 7 0]. This represents the pitch of each open
                    % string relative to the lowest string, modulo 12
+                   % Add to implicit input. May contain NaN's, for unused strings
tZN~)               % Remove NaN's
Y@!                 % Matrix of all permutations, each in a column
"                   % For each column
  @                 %   Push current column
  t1)               %   Duplicate and get first entry
  XH                %   Copy into clipboard H
  - 12\             %   Subtract. This amounts to considering that the first note
                    %   of the current permutation is the root, and computing
                    %   all intervals with respect to that
  12\               %   Modulo 12
  Xz                %   Remove zeros
  XJ                %   Copy into clipboard J
  K7hm?             %   Are all intervals 4 or 7? If so: it's a major chord
    O               %     Push 0 (will become space when converted to char)
    .               %     Break for loop
  ]                 %   End if
  J                 %   Push array of nonzero intervals again
  I7hm?             %   Are all intervals 3 or 7? If so: it's a minor chord
    'm'             %     Push this string
    .               %     Break for loop
  ]                 %   End if
  J                 %   Push array of nonzero intervals again
  [KCX]m?           %   Are all intervals 4, 7 or 10? If so: it's a dominant-7th
                    %   chord
    '7'             %     Push this string
    .               %     Break for loop
  ]                 %   End if
  J                 %   Push array of nonzero intervals again
  [ICX]m?           %   Are all intervals 3, 7 or 10? If so: it's a minor 7th chord
    'm7'            %     Push this string
    .               %     Break for loop
  ]                 %   End if
]                   % End for. The loop is always exited via one of the 'break'
                    % statements. When that happens, the stack contains 0, 'm',
                    % '7' or 'm7', indicating the type of chord; and clipboard H
                    % contains a number that tells the root note using the lowest 
                    % string as base (1 is F, 2 is F# etc)
'FF#GG#AA#BCC#DD#E' % Push this string. Will be split into strings of length 1 or 2
l                   % Push 1
2741B~Q             % Push [1 2 1 2 1 2 1 1 2 1 2 1] (obtained as 2741 in binary,
                    % negated, plus 1)
Y{                  % Split string using those lengths. Gives a cell array of
                    % strings: {'F', 'F#', ..., 'E'}
H                   % Push the identified root note
X)                  % Index into cell array of strings
wh                  % Swap and concatenate. Implicitly display
Luis Mendo
sumber
4

File MS-DOS .COM (179 byte)

File (di sini ditampilkan sebagai HEX):

fc be 81 00 bf 72 01 31 db b9 06 00 51 e8 73 00
59 e2 f9 b9 0c 00 be 48 01 ad 39 c3 74 0d 40 75
f8 d1 fb 73 03 80 c7 08 e2 ec c3 31 db 88 cb 8a
87 59 01 e8 42 00 8a 87 65 01 e8 3b 00 81 c6 08
00 ac e8 33 00 ac eb 30 91 00 89 00 91 04 89 04
ff ff 00 00 6d 00 37 00 6d 37 42 41 41 47 47 46
46 45 44 44 43 43 00 23 00 23 00 23 00 00 23 00
23 00 04 09 02 07 0b 04 84 c0 74 06 b4 02 88 c2
cd 21 c3 8a 0d 47 ac 3c 20 76 fb 30 ed 3c 41 73
22 2c 30 72 0b 86 c5 b4 0a f6 e4 00 c5 ac eb ed
88 e8 00 c8 30 e4 b1 0c f6 f1 88 e1 b8 01 00 d3
e0 09 c3

Input diberikan melalui baris perintah. Masukan yang tidak valid akan menyebabkan perilaku program tidak valid!

Kode assembler terlihat seperti ini:

.text
.code16
ComFileStart:
    cld
    mov $0x81, %si
    mov $(TuneTable-ComFileStart+0x100), %di
    xor %bx, %bx
    # 6 strings: Build the mask of played tones
    mov $6, %cx
NextStringRead:
    push %cx
    call InsertIntoMask
    pop %cx
    loop NextStringRead

    # Check all base tones...
    mov $12, %cx
TestNextTone:
    mov $0x100+ChordTable-ComFileStart, %si
TestNextChord:
    lodsw
    # Is it the chord we are searching for?
    cmp %ax, %bx
    je FoundChord 
    # Is it the end of the table?
    inc %ax
    jnz TestNextChord
    # Transpose the chord we really play
    # and go to the next tone
    # This code rotates the low 12 bits of
    # BX one bit right
    sar $1, %bx
    jnc NoToneRotated
    add $8, %bh
NoToneRotated:
    loop TestNextTone
EndOfProgram:
    ret

FoundChord:
    # Get and print the tone name
    xor %bx, %bx
    mov %cl, %bl
    mov (ToneNamesTable+0x100-1-ComFileStart)(%bx),%al
    call printChar
    mov (ToneNamesTable+0x100+12-1-ComFileStart)(%bx),%al
    call printChar
    # Get the chord name suffix and print it
    add $(ChordNamesTable-ChordTable-2),%si
    lodsb
    call printChar
    lodsb
    # Note: Under MS-DOS 0x0000 is the first word on
    # the stack so the "RET" of printChar will jump
    # to address 0x0000 which contains an "INT $0x21"
    # (end of program) instruction
    jmp printChar

ChordTable:
    # Major, Minor, Major-7, Minor-7
    .word 0x91, 0x89, 0x491, 0x489, 0xFFFF
ChordNamesTable:
    .byte 0,0,'m',0,'7',0,'m','7'
ToneNamesTable:
    .ascii "BAAGGFFEDDCC"
    .byte 0,'#',0,'#',0,'#',0,0,'#',0,'#',0
TuneTable:
    .byte 4,9,2,7,11,4

#
# Subfunction: Print character AL;
#              Do nothing if AL=0
#
printChar:
    test %al, %al
    jz noPrint
    mov $2, %ah
    mov %al, %dl
    int $0x21
noPrint:
    ret

#
# Subfunction: Get one finger position
#              and insert it into a bit mask
#              of tones being played
#
# Input:
#
#   [DS:DI] = 
#        Tuning of current string (0=C, 1=C#, ..., 11=B)
#        Actually only 2=D, 4=E, 7=G, 9=A and 11=B are used
#
#   DS:SI = Next character to read
#
#   DF = Clear
#
# Input and Output:
#
#    BX = Bit mask
#    DI = Will be incremented
#
# Destroys nearly all registers but SI and BX
#
InsertIntoMask:
    mov (%di), %cl
    inc %di
SkipSpaces:
    lodsb
    cmp $' ', %al
    jbe SkipSpaces
# Now evaluate each digit
    xor %ch, %ch
GetNextDigit:
    # Number = 10*Number+Digit
    cmp $'A', %al
    jae DigitIsX
    sub $'0', %al
    jb DigitsDone
    xchg %al, %ch
    mov $10, %ah
    mul %ah
    add %al, %ch
    lodsb
    jmp GetNextDigit
DigitsDone:
    # Add the tune of the string
    # and perform modulus 12
    mov %ch, %al
    add %cl, %al
    xor %ah, %ah
    mov $12, %cl
    div %cl
    mov %ah, %cl
    mov $1, %ax
    shl %cl, %ax
    or %ax, %bx
DigitIsX:
    ret

Kasus uji:

6 20 0 3 11 6 -->  A#   (or Bb)

Saya sudah melihat dua pemain piano bermain bersama "empat tangan" di atas piano.

Test case ini adalah pertama kali saya membaca tentang pemain gitar melakukan ini!

Bahkan dengan mengetuk tangan kanan Anda tidak dapat memainkan tali seperti ini!

Martin Rosenau
sumber
Hmm, mungkin cumi-cumi bisa memainkan akord itu? Saya pikir itu salah satu yang saya temukan dengan pencarian acak sehingga mungkin ada beberapa kasus uji "keras".
Dan Getz
3

Ruby, 129 byte

Sebagai versi sebelumnya tetapi menggunakan loop tunggal, dengan operator ternary untuk mengurutkan antara langkah parsing dan langkah output. Beberapa modifikasi kecil lainnya diperlukan untuk membuat pekerjaan ini.

->a{r=0
18.times{|j|j<6?a[j]&&r|=8194<<(6--~j%5+a[j]*7)%12:(r/=2)&11==3&&puts("CGDAEBF"[j%7]+?#*(j/13)+['',?m,?7,'m7'][r>>9&3])}}

Ruby, 136 byte

Fungsi Llamda menerima array 6 angka sebagai argumen dan output ke stdout. String yang tidak digunakan diwakili oleh nilai falsy (satu-satunya nilai falsy di ruby ​​adalah nildan false.)

->a{r=0
6.times{|j|a[j]&&r|=4097<<(6--~j%5+a[j]*7)%12}
12.times{|j|r&11==3&&puts("FCGDAEB"[j%7]+?#*(j/7)+['',?m,?7,'m7'][r>>9&3]);r/=2}}

Penjelasan

Saya menggunakan representasi dari 12 nada berdasarkan lingkaran perlima . Ini berarti setiap nada diikuti oleh nada 7 semitone lebih tinggi (atau 5 semitone lebih rendah) memberikan urutan F C G D A E B F# C# G# D# A#. Ada 2 keuntungan untuk ini. Salah satunya adalah bahwa semua benda tajam muncul bersama. Yang lainnya adalah not senar terbuka dari senar bass 5 muncul bersamaan: GDAEB (gitarnya terkait tetapi sedikit lebih rumit, lihat di bawah).

Loop pertama berjalan 6 kali. Ekspresi 6--~j%5(ekuivalen 6-(j+1)%5) memberikan nilai-nilai catatan untuk senar terbuka: E=5 A=4 D=3 G=2 B=6 E=5. Untuk ini kita menambahkan nomor fret dikalikan dengan 7 (seperti dapat dilihat di atas, menambahkan satu semitone menggerakkan kita 7 tempat ke depan dalam urutan.) Kemudian kita mengambil semuanya modulo 12 dan membuat bitmap dari catatan yang hadir (kita gunakan 4097<<note valueuntuk memberi 2 oktaf berturut-turut.)

Setelah menyusun bitmap, kami siap mencari chord dan mengeluarkannya.

Kami tertarik pada catatan berikut:

Note       position in      position in             Note      position in 
           semitone domain  circle of fifths                  circle of fifths 
Root       0                0                       Root      0
Minor 3rd  3                9                       Fifth     1
Major 3rd  4                4                       Sixth     3
Fifth      7                1                       Major 3rd 4
Sixth      9                3                       Minor 3rd 9
Minor 7th  10               10                      Minor 7th 10

Dimulai dengan memeriksa chord F, kami menguji untuk melihat apakah root dan kelima ada: bits 0 dan 1 (menghitung dari paling tidak signifikan: bit 1 dan 2). Untuk menolak chord keenam kita juga perlu memeriksa bahwa keenam tidak ada: bit 3 (bit 8.) jadi kami memeriksa itu r&&11==3dan jika demikian kami mencetak chord.

Kami mengabaikan sepertiga utama, dan bergantung sepenuhnya pada bit 9 (minor ketiga) dan bit 10 (minor 7) untuk menentukan tipe chord. Ekspresi r>>9&3digunakan untuk memilih tipe akor yang benar dari array.

Pada akhir loop, kita menggeser bitmap yang tepat bit r/=2untuk menguji akar akord mungkin dalam urutan: F C G D A E B F# C# G# D# A#.

Tidak terkurung dalam program uji

f=->a{                            #Accept array of 6 numbers as argument.
  r=0                             #Setup an empty bitmap.

  6.times{|j|                     #For each string
    a[j]&&                        #if the fret value is truthy (not nil or false)
    r|=4097<<(6--~j%5+a[j]*7)%12  #calculate the note value in the circle of fifths and add to the bitmap.
  }

  12.times{|j|                    #For each possible root note
    r&11==3&&                     #if root and fifth are present (bits 0 and 1) and sixth is absent (bit 3) 
    puts("FCGDAEB"[j%7]+?#*(j/7)+ #output the note name and a sharp symbol if necessary, followed by
    ['',?m,?7,'m7'][r>>9&3])      #m and/or 7 as indicate by bits 9 and 10.
    r/=2
  }
}

print 1;f[[nil,3,2,0,1,0]]       #  C
print 2;f[[0,2,2,0,0,0]]         #  Em
print 3;f[[nil,2,nil,0,nil,0]]   #  Em
print 4;f[[4,4,6,4,6,4]]         #  C#7 
print 5;f[[4,4,6,4,5,4]]         #  C#m7 
print 6;f[[0,2,2,1,0,0]]         #  E
print 7;f[[0,0,2,2,2,0]]         #  A
print 8;f[[nil,nil,4,3,2,2]]     #  F#  
print 9;f[[3,2,0,0,0,1]]         #  G7
print 10;f[[nil,nil,0,2,1,1]]    #  Dm7
print 11;f[[3,3,5,5,5,3]]        #  C
print 12;f[[4,6,6,5,4,4]]        #  G#  
print 13;f[[2,2,4,4,4,5]]        #  B7
print 14;f[[0,7,5,5,5,5]]        #  Am7
print 15;f[[7,6,4,4,nil,nil]]    #  B
print 16;f[[8,6,1,nil,1,3]]      #  Cm
print 17;f[[8,8,10,10,9,8]]      #  Fm
print 18;f[[0,19,5,16,8,7]]      #  Em
print 19;f[[6,20,0,3,11,6]]      #  A#  
print 20;f[[nil,14,9,1,16,nil]]  #  G#m 
print 21;f[[12,14,14,12,12,12]]  #  Em
print 22;f[[15,14,12,12,12,15]]  #  G
print 23;f[[20,nil,20,20,20,20]] #  Cm7
print 24;f[[nil,13,18,10,11,10]] #  A#7
Level River St
sumber
2

Javascript (ES6), 335 333 byte

Suka tantangan ini dan PPCG SE! Ini adalah golf pertama saya - saran diterima karena saya yakin itu bisa ditingkatkan banyak. (menjatuhkan 2 byte seperti yang saya sertakan f = dalam hitungan)

Function fmengambil array string, mewakili angka dan 'X', seperti f(['X','3','2','0','1','0'])dan mengembalikan chord (alami atau tajam) seperti E#m7. Baris baru ditambahkan untuk kejelasan (tidak termasuk dalam jumlah byte)

f=c=>[s=new Map([[435,''],[345,'m'],[4332,7],[3432,'m7']]),
n=[...new Set(c.map((e,i)=>e?(+e+[0,5,10,3,7,0][i])%12:-1)
.filter(e=>++e).sort((a,b)=>a>b))],d=[...n,n[0]+12].reduce(
(a,c,i)=>i?[...a,(c-n[i-1]+12)%12]:[],0).join``.repeat(2),
m=+d.match(/(34|43)(5|32)/g)[0],'E0F0F#0G0G#0A0A#0B0C0C#0D0D#'
.split(0)[n[d.indexOf(m)]]+s.get(m)][4]

Contoh penggunaan:

console.log(f(['0','2','2','0','0','0'])); // Em

Untuk menjalankan test case:

tests=`X 3 2 0 1 0 ---> C
0 2 2 0 0 0 ---> Em
X 2 X 0 X 0 ---> Em
4 4 6 4 6 4 ---> C#7 (or Db7)
4 4 6 4 5 4 ---> C#m7 (or Dbm7)`; // and so on...

tests.split`\n`.forEach(e=>{
    console.log(`Test: ${e}
      Result: ${f(e.split(' ').slice(0,6))}`)
})

Versi tidak dikoleksi dengan penjelasan:

f = (c) => {
    s = new Map([
        [435,''], [345,'m'], [4332,7], [3432,'m7'] 
    ]) /* Each key in s describes the intervals (semitones)
          between consecutive notes in a chord, when it is
          reduced to a single octave, including the interval
          from highest back to lowest. The values describe
          the corresponding chord suffix. E.g. C-E-G has
          intervals C-4-E-3-G-5-C. 435=major=no suffix. */

    n = [ ...new Set(
        c.map( 
         (e,i) => e ? ( +e + [0,5,10,3,7,0][i] )%12 : -1 
         ).filter( (e) => ++e ).sort( (a,b) => a>b )
        ) ] /* take the input array, c, and transform each fret
               position into a note. remove non-notes (-1), sort
               in tone order, remove duplicates. An input of
               positions X 13 18 10 11 10 becomes notes
               (-1) 6 4 1 6 10 then 1 4 6 10. */

    d = [ ...n, n[0] + 12 ].reduce(
        (a,c,i) => i ? [ ...a, (c - n[i-1] + 12)%12 ] : [], 0
    ).join``.repeat(2)
    /* convert the note array, n, into an interval string, d,
       including the lowest note repeated above it to capture
       all intervals. Repeat it twice so that, regardless of the
       inversion played, the intervals will appear in root order
       somewhere. E.g. notes 1-4-6-10 and 13 (1+12)
       become intervals 3 2 4 3, and string for searching
       32433243 */

    m = +d.match( /(34|43)(5|32)/g )[0];
      /* m is the matched chord pattern. In this case, 4332. */

    return 'E0F0F#0G0G#0A0A#0B0C0C#0D0D#'.split(0)[
    n[ d.indexOf(m) ]
    /* get the position in the interval string where the root
       interval first occurs. this corresponds to the position
       of the chord root note in the note array, n. convert this
       number 0-12 to a note name E - D# */
    ] + s.get(m)
       /* add the suffix corresponding to the matched
       chord interval pattern */
}
Chris M
sumber
1
Selamat datang di situs ini! Saya senang mendengar Anda menikmatinya. :) Sayangnya, saya tidak tahu JS jadi saya tidak punya tips, tetapi Anda mungkin dapat menemukan beberapa di sini
DJMcMayhem