first(); $lines = explode( "\n", $song['text'] ); $newText = ''; $transp = $_GET['transp'] ?? 0; foreach( $lines as $line ){ $line = htmlspecialchars( $line ); if ( $this->chordline( $line ) ) { if ( $transp != 0) { $line = $this->z_transpose2( $line, $transp ); } $class = ! isset( $song['key'] ) ? "tabs chord$transp" : "tabs chord" . $this->transpadd( $song['key'], $transp ); $line = str_replace( array('{','}'), array('{', "}" ), $line ); $newText .= "" . $line . "\n"; } else { $newText .= "$line\n"; } } $song['escapedText'] = $newText; return view('song', ['song' => $song, 'transp' => $transp ] ); } /** * @brief Determine whether or not this line contains chords. */ private function chordline($line) { $chords = array( "C","C#","D","D#","E","F","F#","G","G#","A#","B",//"A", "Db", "Eb", "Gb", "Bb",//"Ab", "Cm", "Dm", "Fm", "Gm", "Bm", //"Em", "Am", ); $ambiguous = array( "Ab", "Em", "Am", "A" ); $line = str_replace(array('/','7', "\n", '2', '4'), ' ', $line); $tokens = array_filter(explode(' ', $line)); $badtokens = 0; $ambtokens = 0; $goodtokens = 0; foreach ($tokens as $token) { if( in_array( substr($token, 0,2), $chords ) ) $goodtokens++; else if ( in_array( substr( $token, 0,2), $ambiguous) ) $ambtokens++; else if( $badtokens > 10 ) return FALSE; else $badtokens++; } return ($goodtokens *2)+ $ambtokens >= $badtokens; } private function z_transpose2( $line, $transp ) { $newchords = $this->z_transparray( $transp ); $newline = ''; $space = 0; ///@< Spaces that need to be added or removed. $inCurly = 0; for($i = 0; $i < strlen($line); $i++) { $char = $line[$i]; $nchar = isset($line[$i+1]) ? $line[$i+1] : ''; $upchar = strtoupper($line[$i]); $cval = ord($upchar); if ( $char == '}' && $inCurly ){ $inCurly = 0;} if ( $char == '{' || $inCurly ){ $inCurly = 1; $newline .= $char; continue;} // A-G if( $cval <= 71 && $cval >=65 ) { // Exception for Cmaj7 if( $upchar == 'A' && $nchar == 'j' ) { $newline .= $char; } else if( $nchar == 'b' || $nchar =='#') { $i++; //We have read an extra character now. $newchord = $newchords[$upchar . $nchar]; if( strlen($newchord) == 1 ) { // Need to insert an extra space. $space += 1; } $newline .= $newchord; } else { $newchord = $newchords[$upchar]; if( strlen($newchord) == 2 ) { // Need to remove an extra space. $space -= 1; } $newline .= $newchord; } } else if ( $char == ' ' ) { if( $space >= 0) { for ($j = 0; $j <= $space; $j++) { $newline .= ' '; } $space = 0; } else { // Only balance negative spaces if one will be left remaining if( $nchar == ' ' ) { $i++; $space += 1; } $newline .= ' '; } } else { $newline .= $char; } } return $newline; } private function z_transparray( $transp ) { $chords = array( "C","C#","D","D#","E","F","F#","G","G#","A","Bb","B" ); $newchords = array(); // Create array to map old chords to new ones for ($i=0; $i < 12; $i++) { $newchords[$chords[$i]] = $chords[($i+$transp+12)%12]; } $newchords["Db"] = $newchords["C#"]; $newchords["Eb"] = $newchords["D#"]; $newchords["Gb"] = $newchords["F#"]; $newchords["Ab"] = $newchords["G#"]; $newchords["A#"] = $newchords["Bb"]; return $newchords; } private function transpadd( $fromkey, $integer ) { $chords = array_flip(array( "C","C#","D","D#","E","F","F#","G","G#","A","A#","B" )); $chords["Db"] = $chords["C#"]; $chords["Eb"] = $chords["D#"]; $chords["Gb"] = $chords["F#"]; $chords["Ab"] = $chords["G#"]; $chords["Bb"] = $chords["A#"]; $ochords = array( "C","Db","D","Eb","E","F","Gb","G","Ab","A","Bb","B" ); $fromkey = trim($fromkey, 'm'); return $ochords[($chords[$fromkey] + $integer + 24)%12]; } }