I am losing my hair trying to figure out how to analyze the music (text) tab using preg_match_all and PREG_OFFSET_CAPTURE.
An example :
[D#] [G#] [Fm]
[C#] [Fm] [C#] [Fm] [C#] [Fm]
[C]La la la la la la [Fm]la la la la [D#]
[Fm]I made this song Cause I [Bbm]love you
[C]I made this song just for [Fm]you [D#]
[Fm]I made this song deep in [Bbm]my heart
The result that I am trying to get is:
D
C
C Fm D
La la la la la la la la la la
Fm Bbm
I made this song Cause I love you
C Fm D
I made this song just for you
Fm Bbm
I made this song deep in my heart
And finally, I want to wrap the chords with html tags.
Note that the spaces between chords must exactly match the position of these chords in the original input.
I started parsing line-by-line input, finding chords, getting my position, but my code doesn’t work ... There is something wrong with my line_extract_chords function , it doesn’t work as it should.
Any ideas?
<style>
body{
font-family: monospace;
white-space: pre;
</style>
<?php
function parse_song($content){
$lines = explode(PHP_EOL, $content);
foreach($lines as $key=>$line){
$chords_line = line_extract_chords($line);
$lines[$key] = implode("\n\r",(array)$chords_line);
}
return implode("\n\r",$lines);
}
function line_extract_chords($line){
$line_chords = null;
$line_chords_html = null;
$found_chords = array();
$line = html_entity_decode($line);
preg_match_all("/\[([^\]]*)\]/", $line, $matches, PREG_OFFSET_CAPTURE);
$chord_matches = array();
if ( $matches[1] ){
foreach($matches[1] as $key=>$chord_match){
$chord = $chord_match[0];
$position = $chord_match[1];
$offset= $position;
$offset-= 1;
$offset-=strlen($line_chords);
if ($found_chords){
$offset -= strlen(implode('',$found_chords));
$offset -= 2*(count($found_chords));
}
$chord_html = '<a href="#">'.$chord.'</a>';
if ($offset>0){
$line_chords.= str_repeat(" ", $offset);
$line_chords_html.= str_repeat(" ", $offset);
}
$line_chords.=$chord;
$line_chords_html.=$chord_html;
$found_chords[] = $chord;
}
}
$line = htmlentities($line);
if ($line_chords){
$line = preg_replace('/\[([^\]]*)\]/', '', $line);
return array($line_chords_html,$line);
}else{
return $line;
}
}
?>
source
share