From: Don Wieland on
Hello,

I am building a web Song DB. That will simple song chord charts in the
DB. I would like the ability to do KEY changes for the different
songs. I am looking for some direction on how to do this. This was my
original thought but I am open if there is a better way.

I defined a table called Chords (here is the mySQL Dump):

DROP TABLE IF EXISTS `Chords`;

CREATE TABLE `Chords` (
`id` int(11) NOT NULL auto_increment,
`original_note` varchar(2) default NULL,
`up_note` varchar(2) default NULL,
`down_note` varchar(2) default NULL,
`flatted` varchar(2) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=13 DEFAULT CHARSET=latin1;

LOCK TABLES `Chords` WRITE;
/*!40000 ALTER TABLE `Chords` DISABLE KEYS */;
INSERT INTO `Chords`
(`id`,`original_note`,`up_note`,`down_note`,`flatted`)
VALUES
(1,'A','A#','G#',NULL),
(2,'A#','B','A','Bb'),
(3,'B','C','A#',NULL),
(4,'C','C#','B',NULL),
(5,'C#','D','C','Db'),
(6,'D','D#','C#',NULL),
(7,'D#','E','D','Eb'),
(8,'E','F','D#',NULL),
(9,'F','F#','E',''),
(10,'F#','G','F','Gb'),
(11,'G','G#','F#',NULL),
(12,'G#','A','G','Ab');

/*!40000 ALTER TABLE `Chords` ENABLE KEYS */;
UNLOCK TABLES;

---------------

now this is a sample of my Music Charts:

C Dm7 Em
This is the first line of my song
C/E Em7 Dm7
and I know it can get real long
Gm7 Am7
If you know I will say
G/B C
That it will help to ease the day

What I was hoping for is to check patterns in the CHORD LINES. I
realize I need to mark which lines do PHP will now which line to
parse. I was thinking that the user would add a asterisk "*" at the
beginning of the chord line like so:

* C Dm7 Em
This is the first line of my song
* C/E Em7 Dm7
and I know it can get real long
* Gm7 Am7
If you know I will say
* G/B C
That it will help to ease the day

Then have PHP look for occurrences in the lines that begin with an "*".

So if I want to transpose up 1/2 step, it would look like this:

* C# D#m7 Fm
This is the first line of my song
* C#/F Fm7 D#m7
and I know it can get real long
* G#m7 A#m7
If you know I will say
* G#/C C#
That it will help to ease the day


So if I want to transpose up 1/2 step, it would look like this:

* B C#m7 D#m
This is the first line of my song
* B/D# D#m7 C#m7
and I know it can get real long
* F#m7 G#m7
If you know I will say
* F#/A# B
That it will help to ease the day

I guess the challenge would that once the value was changed, it would
not get changed again it same process. Also, I need to make sure that
EXACT Case is only changed. For example, there might be a chord like
"Asus add 9" where I would not want the "a" of add9 to change.

Any suggestions would be appreciated.

Don Wieland
From: Richard Quadling on
On 1 October 2010 14:35, Don Wieland <donw(a)pointmade.net> wrote:
> Hello,
>
> I am building a web Song DB. That will simple song chord charts in the DB..
>  I would like the ability to do KEY changes for the different songs. I am
> looking for some direction on how to do this. This was my original thought
> but I  am open if there is a better way.
>
> I defined a table called Chords (here is the mySQL Dump):
>
> DROP TABLE IF EXISTS `Chords`;
>
> CREATE TABLE `Chords` (
>  `id` int(11) NOT NULL auto_increment,
>  `original_note` varchar(2) default NULL,
>  `up_note` varchar(2) default NULL,
>  `down_note` varchar(2) default NULL,
>  `flatted` varchar(2) default NULL,
>  PRIMARY KEY  (`id`)
> ) ENGINE=MyISAM AUTO_INCREMENT=13 DEFAULT CHARSET=latin1;
>
> LOCK TABLES `Chords` WRITE;
> /*!40000 ALTER TABLE `Chords` DISABLE KEYS */;
> INSERT INTO `Chords` (`id`,`original_note`,`up_note`,`down_note`,`flatted`)
> VALUES
>        (1,'A','A#','G#',NULL),
>        (2,'A#','B','A','Bb'),
>        (3,'B','C','A#',NULL),
>        (4,'C','C#','B',NULL),
>        (5,'C#','D','C','Db'),
>        (6,'D','D#','C#',NULL),
>        (7,'D#','E','D','Eb'),
>        (8,'E','F','D#',NULL),
>        (9,'F','F#','E',''),
>        (10,'F#','G','F','Gb'),
>        (11,'G','G#','F#',NULL),
>        (12,'G#','A','G','Ab');
>
> /*!40000 ALTER TABLE `Chords` ENABLE KEYS */;
> UNLOCK TABLES;
>
> ---------------
>
> now this is a sample of my Music Charts:
>
>                 C     Dm7        Em
> This is the first line of my song
>         C/E      Em7            Dm7
> and I know it can get real long
>         Gm7          Am7
> If you know I will say
>                 G/B                    C
> That it will help to ease the day
>
> What I was hoping for is to check patterns in the CHORD LINES. I realize I
> need to mark which lines do PHP will now which line to parse. I was thinking
> that the user would add a asterisk "*" at the beginning of the chord line
> like so:
>
> *                C     Dm7        Em
> This is the first line of my song
> *         C/E      Em7            Dm7
> and I know it can get real long
> *         Gm7          Am7
> If you know I will say
> *                 G/B                    C
> That it will help to ease the day
>
> Then have PHP look for occurrences in the lines that begin with an "*".
>
> So if I want to transpose up 1/2 step, it would look like this:
>
> *                C#     D#m7        Fm
> This is the first line of my song
> *         C#/F      Fm7            D#m7
> and I know it can get real long
> *         G#m7          A#m7
> If you know I will say
> *                 G#/C                    C#
> That it will help to ease the day
>
>
> So if I want to transpose up 1/2 step, it would look like this:
>
> *                B     C#m7        D#m
> This is the first line of my song
> *         B/D#      D#m7            C#m7
> and I know it can get real long
> *         F#m7          G#m7
> If you know I will say
> *                 F#/A#                    B
> That it will help to ease the day
>
> I guess the challenge would that once the value was changed, it would not
> get changed again it same process. Also, I need to make sure that EXACT Case
> is only changed. For example, there might be a chord like "Asus add 9" where
> I would not want the "a" of add9 to change.
>
> Any suggestions would be appreciated.
>
> Don Wieland
>
> --
> PHP General Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>

For each key I would guess you'd need the chord order, so if you
change key, you change chords accordingly.

I don't know if that is accurate.

If it is, then a song is recorded in a particular key.

The song will then play the chords/notes of that key. Key1, Note1,
Note2, Note2, Note3, Note4, Note1.

Change key, the same notes are played. For that key ... Key2, Note1,
Note2, Note2, Note3, Note4, Note1.

Or

Key4, Note1, Note2, Note2, Note3, Note4, Note1.

If this is the same for chords, then I'd go with :

A Key table (ID, Keyname) - all the names of the keys
A Notes table (ID, KeyID, Note, Sequence) - the notes in order per key
with a unique composite key of KeyID+Sequence
A Song table (ID, NormalKeyID, Title) - the key that the song is
normally sung in.
A Song Notes table (ID, SongID, NoteSequenceNumber) - Which notes are played.

Changing the NormalKeyID and using that ID with NoteSequenceNumber
should give you the new note to play.

I think.

--
Richard Quadling
Twitter : EE : Zend
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY
From: Don Wieland on
The logic I need is pretty straight forward, but I am having a hard
time replicating it using PHP functions. I will try to break it down
to it's simplest form:

I have a field that has several lines of text. Chords and Song Lyrics.

The "Chord" lines begin with an asterisk "*" and end with the line
break. This is the string I want to parse. Lines with no asterisk at
the beginning are ignored.

Based on 3 arrays of NOTES, I want SUBSTITUTE the text (based on exact
text character patterns - just NOTES not the chord type) of the lines
in my field that start with an asterisk "*".

original_chord_array = A, A#, B, C, C#, D, D#, E, F, F#, G, G#
transpose_up_array = A#, B, C, C#, D, D#, E, F, F#, G, G#, A
transpose_down_array = G#, A, A#, B, C, C#, D, D#, E, F, F#, G

It is important that it only effects EXACT strings. Notes will always
be capitalized and chord types will be lower case. Maybe we can use
that characteristic to better identify what to change. Here are some
examples of chords:

A
Asus7
Csus add9
Dmaj7
F#m7
G#
C#dim no3

When I transpose UP these chords, just the NOTE should change:

A#
A#sus7
C#sus add9
D#maj7
Gm7
A
Ddim no3

When I transpose DOWN these chords, just the NOTE should change:

G#
G#sus7
Bsus add9
C#maj7
Fm7
G
Cdim no3

I am working on a function, but still not producing the proper
results. Hopefully this break down is more clear and someone will bail
me out ;-)

Thanks again for the feedback.

Don

On Oct 1, 2010, at 7:02 AM, Richard Quadling wrote:

> Changing the NormalKeyID and using that ID with NoteSequenceNumber
> should give you the new note to play.
>
> I think.

From: chris h on
Don,

How far along are you? To get started something like this may work for
you...

preg_match_all('/[A-G]{1}#?/', $line, $matches);

That SHOULD return each note of the line (you can retrieve them via the
$matches array), given that there are no other upper-case characters that
are not notes. Also this assumes that $line has exactly one line in it. :)

If you get that working, perhaps you can setup something using the
preg_replace method?
http://php.net/manual/en/function.preg-replace.php


Another option is to use the str_replace function.
http://us3.php.net/manual/en/function.str-replace.php


I gotta run (else I would type some more) but let me know if you want any
advice on using those!

Chris.


On Fri, Oct 1, 2010 at 11:20 AM, Don Wieland <donw(a)pointmade.net> wrote:

> The logic I need is pretty straight forward, but I am having a hard time
> replicating it using PHP functions. I will try to break it down to it's
> simplest form:
>
> I have a field that has several lines of text. Chords and Song Lyrics.
>
> The "Chord" lines begin with an asterisk "*" and end with the line break.
> This is the string I want to parse. Lines with no asterisk at the beginning
> are ignored.
>
> Based on 3 arrays of NOTES, I want SUBSTITUTE the text (based on exact text
> character patterns - just NOTES not the chord type) of the lines in my field
> that start with an asterisk "*".
>
> original_chord_array = A, A#, B, C, C#, D, D#, E, F, F#, G, G#
> transpose_up_array = A#, B, C, C#, D, D#, E, F, F#, G, G#, A
> transpose_down_array = G#, A, A#, B, C, C#, D, D#, E, F, F#, G
>
> It is important that it only effects EXACT strings. Notes will always be
> capitalized and chord types will be lower case. Maybe we can use that
> characteristic to better identify what to change. Here are some examples of
> chords:
>
> A
> Asus7
> Csus add9
> Dmaj7
> F#m7
> G#
> C#dim no3
>
> When I transpose UP these chords, just the NOTE should change:
>
> A#
> A#sus7
> C#sus add9
> D#maj7
> Gm7
> A
> Ddim no3
>
> When I transpose DOWN these chords, just the NOTE should change:
>
> G#
> G#sus7
> Bsus add9
> C#maj7
> Fm7
> G
> Cdim no3
>
> I am working on a function, but still not producing the proper results.
> Hopefully this break down is more clear and someone will bail me out ;-)
>
> Thanks again for the feedback.
>
> Don
>
>
> On Oct 1, 2010, at 7:02 AM, Richard Quadling wrote:
>
> Changing the NormalKeyID and using that ID with NoteSequenceNumber
>> should give you the new note to play.
>>
>> I think.
>>
>
>
> --
> PHP General Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>
From: Richard Quadling on
On 1 October 2010 16:20, Don Wieland <donw(a)pointmade.net> wrote:
> The logic I need is pretty straight forward, but I am having a hard time
> replicating it using PHP functions. I will try to break it down to it's
> simplest form:
>
> I have a field that has several lines of text. Chords and Song Lyrics.
>
> The "Chord" lines begin with an asterisk "*" and end with the line break.
> This is the string I want to parse. Lines with no asterisk at the beginning
> are ignored.
>
> Based on 3 arrays of NOTES, I want SUBSTITUTE the text (based on exact text
> character patterns - just NOTES not the chord type) of the lines in my field
> that start with an asterisk "*".
>
> original_chord_array = A, A#, B, C, C#, D, D#, E, F, F#, G, G#
> transpose_up_array = A#, B, C, C#, D, D#, E, F, F#, G, G#, A
> transpose_down_array = G#, A, A#, B, C, C#, D, D#, E, F, F#, G
>
> It is important that it only effects EXACT strings.  Notes will always be
> capitalized and chord types will be lower case. Maybe we can use that
> characteristic to better identify what to change. Here are some examples of
> chords:
>
> A
> Asus7
> Csus add9
> Dmaj7
> F#m7
> G#
> C#dim no3
>
> When I transpose UP these chords, just the NOTE should change:
>
> A#
> A#sus7
> C#sus add9
> D#maj7
> Gm7
> A
> Ddim no3
>
> When I transpose DOWN these chords, just the NOTE should change:
>
> G#
> G#sus7
> Bsus add9
> C#maj7
> Fm7
> G
> Cdim no3
>
> I am working on a function, but still not producing the proper results.
> Hopefully this break down is more clear and someone will bail me out ;-)
>
> Thanks again for the feedback.
>
> Don
>
> On Oct 1, 2010, at 7:02 AM, Richard Quadling wrote:
>
>> Changing the NormalKeyID and using that ID with NoteSequenceNumber
>> should give you the new note to play.
>>
>> I think.
>
>

/**
* Transpose a chord sequence.
*
* @param $s_Sequence The chord sequence to transpose.
* @param $b_TransposeUp Transpose up or down.
*
* @return The transposed sequence.
*/
function transposeChord($s_Sequence, $b_TransposeUp = True) {
$a_Chords = array('A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F',
'F#', 'G', 'G#');
return preg_replace_callback (
'`([A-G]#?)`',
function($a_Matches) use($a_Chords, $b_TransposeUp) {
// Find the position in the chords array of the found chord.
$a_ChordPositions = array_keys($a_Chords, $a_Matches[1], True);

// Get the new chord position.
$i_NewChordPosition = (count($a_Chords) + $a_ChordPositions[0] +
($b_TransposeUp ? 1 : -1)) % count($a_Chords);

// Return the new chord position.
return $a_Chords[$i_NewChordPosition];
},
$s_Sequence
);
}



--
Richard Quadling
Twitter : EE : Zend
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY