Most of the work I do can be rather routine.
To keep my chops up for doing more complex work, I often try to find a problem to solve that is also useful.
Tablature Files
As a musician I have collected thousands of what are commonly known as Tablature or more commonly known as Tab Files.
As of this writing I have 5,678 tab files in my database.
Tabs or Tablature is a way of representing music in text form.
The simplest tabs are just the lyrics and chords of songs.
These types of tabs can be applied to any chordal instrument such as piano, guitar and ukulele.
So. Central Rain By R.E.M.
Verse 1:
C Em Gm F
Did you never call? I waited for your call
C Cm Bb C
These rivers of suggestion are driving me away
C Em Gm F
The trees will bend, the cities wash away
C Cm Bb C
The city on the river has a girl without a dream
Chorus:
C Dm
I'm sorry
Verse 2:
Eastern to Mountain, third party call, the lines are down
The wise man wrote his words upon the rocks
But I'm not bound to follow suit
The trees will bend, the conversation's dimmed
Go build yourself another home, this choice isn't mine
Chorus
Verse 3:
Did you never call? I waited for your call
These rivers of suggestion are driving me away
The ocean sang, the cities wash away
Go build yourself another dream, this choice isn't mine
Chorus
Tablature originally started as a way of learning songs on guitar.
In addition to the simple lyric-chord form, there are tab files that include the fingering of chords and riffs on the guitar fretboard.
This can also be applied to bass guitar, ukulele or any other stringed instrument.
So. Central Rain By R.E.M.
Opening Riff:
E: ---------|-------------------|-----------------|----------0-|---0------0---
B: ---------|----------3--------|-3---------------|------3-----|-3---3------0-
G: ---------|--------2---2------|---2-0-----------|----2---2---|--------2-----
D: -----2-3-|-0-----------------|-------------2-3-|-0----------|--------------
A: -3-3-----|-------------------|--------3-3------|------------|--------------
E: ---------|-------------------|-----------------|------------|--------------
Verse 1:
C Em Gm F
Did you never call? I waited for your call
C Cm Bb C
These rivers of suggestion are driving me away
C Em Gm F
The trees will bend, the cities wash away
C Cm Bb C
The city on the river has a girl without a dream
Chorus: [x4]
C Dm
I'm sorry
Bass Riff:
G: -------------------------------------
D: --------------2----------------------
A: --3--3--5--3-----5--3---3--3--5--3---
E: -------------------------------------
Verse 2:
Eastern to Mountain, third party call, the lines are down
The wise man wrote his words upon the rocks
But I'm not bound to follow suit
The trees will bend, the conversation's dimmed
Go build yourself another home, this choice isn't mine
Chorus
Verse 3:
Did you never call? I waited for your call
These rivers of suggestion are driving me away
The ocean sang, the cities wash away
Go build yourself another dream, this choice isn't mine
Chorus
As the number of tab files increased they became difficult to manage.
So I created a database driven web application to store and manage all of my tab files.
Another purpose for this design was to make it easy for me to create song books for myself to be printed and bound.
Each song book contained hundreds of songs and it would have been very tedious to add them one at a time.
So I created a feature called Set Lists. With Set Lists I could create an ordered list of songs that could be used to create an MS Word file.
It made it much easier to create music books.
Smart Tablature Files
Many of the Tab sites on the web allow you to transpose songs into different keys.
I had long thought about how they structured the files and parsed them to make that work.
The main body of my tablature data structure is simply text.
There is no separation between the lyrics and chords, they are both are treated the same.
The Data Structure
The data for a tablature file is stored in a javascript object. It can be loaded in one of three different ways:
- Manually, by using the application editor
- From a JSON file
- By parsing simple tablature text
{
title: "So. Central Rain",
artist: "R.E.M.",
author: "Michael Stipe",
key: "0",
trans: "0",
capo: "0",
bpm: "4",
bv: "4",
cpl: "77",
songSections: [
{
Id: 0,
Name: "Opening Riff",
Repeat: "0",
Lyrics: [
"E: ---------|-------------------|-----------------|----------0-|---0------0---",
"B: ---------|----------3--------|-3---------------|------3-----|-3---3------0-",
"G: ---------|--------2---2------|---2-0-----------|----2---2---|--------2-----",
"D: -----2-3-|-0 {let ring out!}-|-------------2-3-|-0----------|--------------",
"A: -3-3-----|-------------------|--------3-3------|------------|--------------",
"E: ---------|-------------------|-----------------|------------|--------------"
],
Chords: []
},
{
Id: 1,
Name: "Verse 1",
Repeat: "0",
Lyrics: [
"Did you never call? I waited for your call",
"These rivers of suggestion are driving me away",
"The trees will bend, the cities wash away",
"The city on the river has a girl without a dream"
],
Chords: [
{ line: "0", chordPos: [
{position: "0",rootNote: "0",chordMod: "",bassNote: "0"},
{position: "14",rootNote: "4",chordMod: "m",bassNote: "4"},
{position: "20",rootNote: "7",chordMod: "m",bassNote: "7"},
{position: "30",rootNote: "5",chordMod: "",bassNote: "5"}
]
},
{ line: "1", chordPos: [
{position: "0",rootNote: "0",chordMod: "",bassNote: "0"},
{position: "12",rootNote: "0",chordMod: "m",bassNote: "0"},
{position: "22",rootNote: "10",chordMod: "",bassNote: "10"},
{position: "27",rootNote: "0",chordMod: "",bassNote: "0"}
]
},
{ line: "2", chordPos: [
{position: "0",rootNote: "0",chordMod: "",bassNote: "0"},
{position: "15",rootNote: "4",chordMod: "m",bassNote: "4"},
{position: "20",rootNote: "7",chordMod: "m",bassNote: "7"},
{position: "32",rootNote: "5",chordMod: "",bassNote: "5"}
]
},
{ line: "3", chordPos: [
{position: "0",rootNote: "0",chordMod: "",bassNote: "0"},
{position: "11",rootNote: "0",chordMod: "m",bassNote: "0"},
{position: "18",rootNote: "10",chordMod: "",bassNote: "10"},
{position: "25",rootNote: "0",chordMod: "",bassNote: "0"}
]
}
]
},
{
Id: 2,
Name: "Chorus",
Repeat: "0",
Lyrics: [
"I'm sorry, I'm sorry, I'm sorry, I'm sorry"
],
Chords: [
{ line: "0", chordPos: [
{position: "0",rootNote: "0",chordMod: "",bassNote: "0"},
{position: "3",rootNote: "2",chordMod: "sus2",bassNote: "2"},
{position: "11",rootNote: "0",chordMod: "",bassNote: "0"},
{position: "14",rootNote: "2",chordMod: "sus2",bassNote: "2"},
{position: "22",rootNote: "0",chordMod: "",bassNote: "0"},
{position: "25",rootNote: "2",chordMod: "sus2",bassNote: "2"},
{position: "33",rootNote: "0",chordMod: "",bassNote: "0"},
{position: "36",rootNote: "2",chordMod: "sus2",bassNote: "2"}
]
}
]
},
{
Id: 3,
Name: "Bass Riff",
Repeat: "0",
Lyrics: [
"G: -------------------------------------",
"D: --------------2----------------------",
"A: --3--3--5--3-----5--3---3--3--5--3---",
"E: -------------------------------------"
],
Chords: [
{ line: "0", chordPos: [
{position: "0",rootNote: "0",chordMod: "",bassNote: "0"}
]
}
]
},
{
Id: 4,
Name: "Verse 2",
Repeat: "0",
Lyrics: [
"Eastern to Mountain, third party call, the lines are down",
"The wise man wrote his words upon the rocks",
"But I'm not bound to follow suit",
"The trees will bend, the conversation's dimmed",
"Go build yourself another home, this choice isn't mine"
],
Chords: []
},
{
Id: 5,
Name: "Interlude",
Repeat: "0",
Lyrics: [
""
],
Chords: [
{ line: "0", chordPos: [
{position: "0",rootNote: "9",chordMod: "m",bassNote: "9"},
{position: "4",rootNote: "2",chordMod: "sus2",bassNote: "2"},
{position: "12",rootNote: "9",chordMod: "m",bassNote: "9"},
{position: "16",rootNote: "2",chordMod: "sus2",bassNote: "2"},
{position: "24",rootNote: "9",chordMod: "m",bassNote: "9"},
{position: "28",rootNote: "2",chordMod: "sus2",bassNote: "2"},
{position: "35",rootNote: "7",chordMod: "",bassNote: "7"}
]
}
]
},
{
Id: 6,
Name: "Verse 3",
Repeat: "0",
Lyrics: [
"Did you never call? I waited for your call",
"These rivers of suggestion are driving me away",
"The ocean sang, the conversation's dimmed",
"Go build yourself another home, this choice isn't mine"
],
Chords: []
},
{
Id: 7,
Name: "Outro",
Repeat: "0",
Lyrics: [ "" ],
Chords: [
{ line: "0", chordPos: [
{position: "0",rootNote: "9",chordMod: "m",bassNote: "9"},
{position: "4",rootNote: "2",chordMod: "sus2",bassNote: "2"},
{position: "11",rootNote: "9",chordMod: "m",bassNote: "9"},
{position: "15",rootNote: "2",chordMod: "sus2",bassNote: "2"},
{position: "22",rootNote: "9",chordMod: "m",bassNote: "9"},
{position: "26",rootNote: "2",chordMod: "sus2",bassNote: "2"},
{position: "33",rootNote: "9",chordMod: "m",bassNote: "9"},
{position: "37",rootNote: "2",chordMod: "sus2",bassNote: "2"},
{position: "44",rootNote: "9",chordMod: "m",bassNote: "9"}
]
}
]
}
],
songAssembly: [
"0",
"1",
"2",
"3",
"4",
"2",
"5",
"3",
"6",
"2",
"7"
]
}