2012-09-29 4 views
0

Je suis en train de faire la transposition d'accords en PHP le tableau de valeurs d'accords sont comme suit ...php - chaîne de remplacement

$chords1 = array('C','C#','D','D#','E','F','F#','G','G#','A','A#','B','C','Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B','C'); 

Un exemple serait D6/F #. Je veux faire correspondre la valeur du tableau, puis le transposer par une position numérique donnée dans le tableau. Voici ce que j'ai jusqu'à présent ...

function splitChord($chord){ // The chord comes into the function 
    preg_match_all("/C#|D#|F#|G#|A#|Db|Eb|Gb|Ab|Bb|C|D|E|F|G|A|B/", $chord, $notes); // match the item 
    $notes = $notes[0]; 
    $newArray = array(); 
    foreach($notes as $note){ // for each found item as a note 
     $note = switchNotes($note); // switch the not out 
     array_push($newArray, $note); // and push it into the new array 
    } 
    $chord = str_replace($notes, $newArray, $chord); // then string replace the chord with the new notes available 
    return($chord); 
} 
function switchNotes($note){ 
    $chords1 = array('C','C#','D','D#','E','F','F#','G','G#','A','A#','B','C','Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B','C'); 

    $search = array_search($note, $chords1);////////////////Search the array position D=2 & F#=6 
    $note = $chords1[$search + 4];///////////////////////then make the new position add 4 = F# and A# 
    return($note); 
} 

Cela fonctionne, sauf le problème est que si j'utilise un accord de séparation comme (D6/F #) L'accord est transposable à A # 6/A #. Il remplace la première note (D) par un (F #) puis, les deux (F # 's) avec un (A #).

La question est ... Comment puis-je empêcher cette redondance? La sortie désirée serait F # 6/A #. Merci de votre aide. Si la solution est affichée, je la marquerai comme ayant été répondue.

Répondre

1

Vous pouvez utiliser la fonction preg_replace_callback

function transposeNoteCallback($match) { 
    $chords = array('C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B', 'C'); 
    $pos = array_search($match[0], $chords) + 4; 
    if ($pos >= count($chords)) { 
     $pos = $pos - count($chords); 
    } 
    return $chords[$pos]; 
} 

function transposeNote($noteStr) { 
    return preg_replace_callback("/C#|D#|F#|G#|A#|Db|Eb|Gb|Ab|Bb|C|D|E|F|G|A|B/", 'transposeNoteCallback', $noteStr); 
} 

test

écho transposeNote ("EB6 Bb B Ab D6/F #");

retours

G6 C# C Eb F # 6/A #

+0

comment puis-je ajouter une variable à la fonction de rappel pour le numéro 4 ... –

+0

Je ne comprends pas la question. Vous voulez également détecter G # 4, G # 6, G # 7? Essayez avec ce pseudo regex "/...|(G#)([0-9]+)?|.../" ou si vous ne voulez pas d'accords inexistants, vous pouvez mettre toutes les variations manuellement "/ .. . | (G #) (4 | 6 | 7 ... | 11 | ...)? | .../" Dans transposeNoteCallback, vous aurez $ match [1] G, et vous devez ensuite vérifier si count ($ match) == 2 et si la condition est vraie, vous pouvez choisir le numéro de $ match [2] – Igor

+0

J'ai finalement obtenu ce dont j'avais besoin. Merci! Je voulais détecter si c'était une touche # ou une touche b par opposition à la détection de note. –

1

Bon marché: déplacez-vous dans le domaine des nombres naturels [[0-11]] et associez-les aux notes correspondantes uniquement pendant l'affichage, cela vous fera gagner beaucoup de temps.

Le seul problème sera les sons homophones [par ex. C-sharp/D-flat], mais j'espère que vous pouvez déduire de la tonalité.