Qu'est-ce que je viens de jouer? Traduire les doigtés de guitare en accords

22

Connexes: Musique: qu'est-ce que cet accord? , Notes to Tablature , Générer des tablatures de guitare? , Traduire des paires de numéros en notes de guitare

Étant donné un doigté de guitare, sortez l'accord qu'il représente. Vous pouvez utiliser une entrée et une sortie standard ou écrire une fonction qui renvoie une chaîne.

Les doigtés d'entrée seront classables comme l'un des accords suivants, à exprimer comme suit (si la note fondamentale était C):

  • triade majeure: C
  • triade mineure: Cm
  • (dominant) septième: C7
  • septième mineure: Cm7

L'accord peut être inversé, vous ne pouvez donc pas vous fier à la note la plus grave comme étant la racine. Vous ne pouvez pas non plus compter sur le fait qu'il s'agit d'un doigté facile ou courant dans le monde réel. Plus généralement, la sortie de votre programme doit ignorer les octaves des hauteurs et traiter tous les hauteurs correspondant à la même note de musique (c'est-à-dire A) comme égales.

Il s'agit de , donc le code le plus court en octets l'emporte.

Format d'entrée

L'entrée est une série de 6 valeurs qui indiquent, pour chaque corde d'une guitare à 6 cordes en accordage standard (EADGBE), à quelle frette cette corde sera jouée. Cela pourrait également indiquer que la chaîne n'est pas jouée du tout. La frette "zeroth" est également connue comme la position ouverte, et le nombre de frettes compte à partir de là. Supposons que la guitare a 21 positions de frettes, de sorte que la position de frette la plus élevée soit le numéro 20.

Par exemple, l'entrée X 3 2 0 1 0signifie placer ses doigts aux positions suivantes en haut du manche de la guitare:

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

et gratter les 2e à 6e cordes. Il correspond à cet onglet ASCII :

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

Vous avez une certaine flexibilité dans le choix du type d'entrée que vous souhaitez: chaque position de frette peut être exprimée sous la forme d'une chaîne ou d'un nombre. Les cordes de guitare qui ne sont pas jouées sont généralement indiquées par un X, mais vous pouvez choisir une valeur sentinelle différente si cela vous facilite la tâche (comme -1si vous utilisez des chiffres). La série de 6 positions de frettes peut être entrée comme n'importe quel type de liste, de tableau ou de séquence, une seule chaîne séparée par des espaces ou comme entrée standard — encore une fois, votre choix.

Vous pouvez compter sur l'entrée correspondant à l'un des 4 types d'accords mentionnés ci-dessus.

Veuillez expliquer dans votre message quelle forme de saisie prend votre solution.

Format de sortie

Vous devez soit retourner soit imprimer sur la sortie standard une chaîne décrivant l'accord auquel le doigté est destiné. Cette chaîne est composée de deux parties concaténées ensemble. La capitalisation est importante. Les espaces de fin sont autorisés.

La première partie indique la note fondamentale , l' un des A, A#/ Bb, B, C, C#/ Db, D, D#/ Eb, E, F, F#/ Gb, Gou G#/ Ab. (J'utilise au #lieu de , et au blieu de , pour éviter d' exiger Unicode.) Notes fondamentales qui peuvent être exprimées sans dièse ou bémol doit être exprimé sans eux (jamais sortie B#, Fbou Dbb); ceux qui ne peuvent pas être exprimés avec un seul symbole pointu ou plat (c'est-à-dire soit C#ou Db, mais jamais B##). En d'autres termes, vous devez minimiser le nombre d'accidents (objets tranchants ou plats) dans le nom de la note.

La deuxième partie indique le type d'accord, soit vide pour une triade majeure, mpour une triade mineure, 7pour la septième dominante, soit m7pour la septième mineure. Ainsi, un sol majeur est Gsorti simplement comme , tandis qu'un septième mineur en D♯ peut être sorti comme D#m7ou Ebm7. Plus d'exemples peuvent être trouvés dans les cas de test à la fin.

Théorie et astuces

Notes de musique

La gamme chromatique a 12 hauteurs par octave. Lorsqu'il est réglé sur un tempérament égal, chacun de ces emplacements est également éloigné de ses voisins 1 . Les hauteurs distantes de 12 demi-tons (une octave) sont considérées comme la même note de musique. Cela signifie que nous pouvons traiter les notes comme des entiers modulo 12, de 0 à 11. Sept d'entre eux ont des noms de lettre 2 de A à G.Ce n'est pas suffisant pour nommer les 12 hauteurs, mais l'ajout de corrections accidentelles: ajout d'un ♯ ( forte) à une note la rend un demi-ton plus haut, et l'ajout d'un ♭ (plat) la rend un demi-ton plus basse.

Accords

Un accord est composé de 2 notes ou plus jouées ensemble. Le type d'accord dépend des relations entre les notes, qui peuvent être déterminées par les distances entre elles. Un accord a une note fondamentale, comme mentionné précédemment. Nous traiterons la note fondamentale comme 0 dans ces exemples, mais c'est arbitraire, et tout ce qui compte dans ce défi est la distance entre les notes en arithmétique modulo. Il y aura toujours un type d'accord unique pour la réponse, soit une triade ou un septième accord . La note fondamentale ne sera pas toujours la hauteur de fréquence la plus basse; choisissez la note fondamentale de telle sorte que vous puissiez décrire l'accord comme l'un des quatre types d'accord suivants:

  • Une triade majeure est un accord avec les notes 0 4 7.
  • Une triade mineure est un accord avec les notes 0 3 7.
  • Un accord de septième dominant (ou majeur / mineur) a les notes 0 4 7 10.
  • Un accord de septième mineur (ou mineur / mineur) a les notes 0 3 7 10. 3

Accordage de guitare

L'accord standard sur une guitare à 6 cordes commence par E sur la corde la plus basse, puis frappe des notes à des intervalles de 5, 5, 5, 4, puis 5 demi-tons en remontant les cordes. En prenant le plus bas E comme 0, cela signifie que gratter toutes les cordes de la guitare vous donne des hauteurs numérotées 0 5 10 15 19 24, auxquelles le modulo 12 est équivalent 0 5 10 3 7 0, ou les notes E A D G B E.

Exemples travaillés

Si votre entrée est 0 2 2 0 0 0, cela correspond aux notes E B E G B E, donc juste E, B et G. Ceux-ci forment l'accord Em, qui peut être vu en les numérotant avec la racine comme E, nous donnant 0 3 7. (Le résultat serait le même pour X 2 X 0 X 0, ou 12 14 14 12 12 12.)

Si votre entrée est 4 4 6 4 6 4, leur numérotation avec une racine de C♯ donne 7 0 7 10 4 7, ou 0 4 7 10alors la réponse est C#7(ou Db7). Si c'était le cas 4 4 6 4 5 4, la numérotation donnerait 7 0 7 10 3 7, ou 0 3 7 10, qui est C#m7(ou Dbm7).

Cas de test

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 par les logarithmes de leurs fréquences

2 ou, au solfège , des noms comme do, re, mi . Dans ce défi, utilisez les noms de lettres.

3 Cela pourrait aussi être appelé un accord majeur de sixième, avec un choix différent de note fondamentale. Dans ce défi, appelez-le par son septième nom mineur.

Dan Getz
la source
3
Grand défi!
Luis Mendo
1
Tenté de clôturer en tant que dupe de mon futur défi: D (j'avais un défi très similaire en tête, mais vous étiez visiblement plus rapide.)
flawr
Les espaces de fin sont-ils autorisés dans la chaîne de sortie?
Luis Mendo
@LuisMendo bien sûr; C'est très bien.
Dan Getz
1
@officialaimm non, vous n'avez pas besoin de gérer d'autres situations. Vous pouvez supposer que ce sera toujours l'un de ces 4 types d'accords. En d'autres termes, votre code peut faire ce que vous voulez (y compris l'erreur ou donner une mauvaise réponse) s'il obtient un accord différent.
Dan Getz

Réponses:

9

MATL , 115 114 bytes

[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

Le format d'entrée est [N 3 2 0 1 0], où Nindique une chaîne inutilisée.

La chaîne de sortie utilise toujours #, non b.

Essayez-le en ligne! Ou vérifiez tous les cas de test, en deux parties pour éviter l'expiration du compilateur en ligne:

Explication

[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
la source
4

Fichier .COM MS-DOS (179 octets)

Le fichier (ici affiché en 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

L'entrée est donnée via la ligne de commande. Une entrée non valide entraînera un comportement de programme non valide!

Le code assembleur ressemble à ceci:

.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

Cas de test:

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

J'ai déjà vu deux pianistes jouer ensemble "à quatre mains" sur un piano.

Ce cas de test est la première fois que je lis sur des guitaristes faisant ça!

Même en tapant à droite, vous ne pouvez pas jouer un cordon comme celui-ci!

Martin Rosenau
la source
Hmm, peut-être qu'un calmar pourrait jouer cet accord? Je pense que c'est l'un de ceux que j'ai trouvé par une recherche aléatoire afin qu'il puisse y avoir des cas de test "durs".
Dan Getz
3

Rubis, 129 octets

Comme la version précédente mais utilise une seule boucle, avec opérateur ternaire pour séquencer entre l'étape d'analyse et l'étape de sortie. Quelques autres modifications mineures ont été nécessaires pour faire ce travail.

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

Rubis, 136 octets

La fonction Llamda accepte un tableau de 6 nombres comme argument et sort vers stdout. La chaîne inutilisée est représentée par une valeur falsifiée (les seules valeurs falsifiées dans ruby ​​sont nilet 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}}

Explication

J'utilise une représentation des 12 hauteurs basée sur le cercle des quintes . Cela signifie que chaque hauteur est suivie par la hauteur 7 demi-tons plus haut (ou 5 demi-tons plus bas) donnant la séquence F C G D A E B F# C# G# D# A#. Il y a 2 avantages à cela. La première est que tous les objets tranchants apparaissent ensemble. L'autre est que les notes à cordes ouvertes de la basse à 5 cordes apparaissent ensemble: GDAEB (la guitare est liée mais légèrement plus complexe, voir ci-dessous).

La première boucle s'exécute 6 fois. L'expression 6--~j%5(équivalente 6-(j+1)%5) donne les valeurs de notes pour les chaînes ouvertes: E=5 A=4 D=3 G=2 B=6 E=5. À cela, nous ajoutons le nombre de frettes multiplié par 7 (comme on peut le voir ci-dessus, l'ajout d'un demi-ton nous fait avancer de 7 places dans la séquence.) Ensuite, nous prenons le tout modulo 12 et faisons un bitmap des notes qui sont présentes (nous utiliser 4097<<note valuepour donner 2 octaves consécutives.)

Après avoir composé le bitmap, nous sommes prêts à rechercher l'accord et à le sortir.

Nous sommes intéressés par les notes suivantes:

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

En commençant par vérifier l'accord F, nous testons pour voir si la racine et le cinquième sont présents: bits 0 et 1 (en comptant du moins significatif: les bits 1 et 2). Afin de rejeter les accords sixième, nous devons également vérifier que le sixième est absent: bit 3 (bit de 8). Donc nous vérifions cela r&&11==3et si c'est le cas, nous imprimons l'accord.

Nous ignorons le tiers majeur et comptons entièrement sur le bit 9 (tiers mineur) et le bit 10 (septième mineur) pour déterminer le type d'accord. L'expression r>>9&3est utilisée pour choisir le type d'accord correct dans un tableau.

A la fin de la boucle, on décale l'image bitmap bit à droite de l' un r/=2de tester les racines d'accords possibles dans l' ordre: F C G D A E B F# C# G# D# A#.

Non testé dans le programme de test

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
la source
2

Javascript (ES6), 335 333 octets

J'adore ce défi et PPCG SE! C'est mon premier golf - les suggestions sont les bienvenues car je suis sûr que cela pourrait être beaucoup amélioré. (éliminé 2 octets car j'avais inclus f = dans le décompte)

La fonction fprend un tableau de chaînes, représentant des nombres et «X», comme f(['X','3','2','0','1','0'])et retourne un accord (naturel ou aigu) comme E#m7. Ajout de nouvelles lignes pour plus de clarté (non inclus dans le nombre d'octets)

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]

Exemple d'utilisation:

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

Pour exécuter des cas de test:

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

Version non golfée avec explication:

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
la source
1
Bienvenue sur le site! Je suis content de vous entendre en profiter. :) Malheureusement, je ne connais aucun JS donc je n'ai pas de conseils, mais vous pourriez en trouver ici
DJMcMayhem