Skip to content

Instantly share code, notes, and snippets.

@fredbogg
Created March 4, 2012 09:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fredbogg/1971776 to your computer and use it in GitHub Desktop.
Save fredbogg/1971776 to your computer and use it in GitHub Desktop.
Play ABC notation tunes in your Codea project.
--# ABCMusic
--ABCMusic class by Fred Bogg
-- v 0.4 beta
-- tuplets work
ABCMusic = class()
function ABCMusic:init(_ABCTune,LOOP,DEBUG,DUMP)
self.time = 0
self.timerSeconds = 0
self.code = "x=1"
-- sound(SOUND_PICKUP, 42117)
self.DEBUG = DEBUG
if self.DEBUG == nil then self.DEBUG = false end
if DUMP == nil then DUMP = false end
if _ABCTune == nil then
print("No tune provided. Use ABCMusic(tunename)")
end
self.LOOP = LOOP
nextT = 0
cachingSpeed = 0 -- in seconds
cachedIdx = 0
noteNo = 1
bufferTable = {}
gnFrequency = 0
gnMasterVolume = 0.5 -- this is the default setting, will be altered for fades
gnFadeCountup = 0
gnFadeSecondsTarget = 0
gnMasterVolumeModifier = 0
y=0
self.remainingTupletNotes =0
self.soundTablePointer=1
self.soundTable = {}
self.timeElapsedSinceLastNote = 0
self.duration = 1
gnDurationSeconds = 0
gnNoteVolume = 1
--tempDuration = 1
self.tempo = 240 -- if no tempo is specified in the file, use this
self.noteLength = (1/8) -- if no default note length is specified in the file, use this
-- This is the cycle of fifths. It helps us figure out which accidentals to use
-- for a given key.
cycleOfFifths = {"Cb","Gb","Db","Ab","Eb","Bb","F",
"C","G","D","A","E","B","F#","C#","G#","D#","A#"}
-- This is the amount you need to multiply a note value by to get the next highest one.
-- Don't ask me why it's not in hertz, it hurts.
multiplier = 1.0296
--1.0296 works for parameter tables, but the loss of precision using the encoded sound means this is out of tune.
pitchTable = {1} -- This table will be filled with the note values
pitch = pitchTable[1]
self.semitoneModifier = 0
gsNoteOrder = "CDEFGABcdefgab"
gsTonalSystem = "22122212212221" -- compared with the noteOrder, this shows the no of
-- semitones between each note, like the black and white keys.
-- There are 88 keys on a piano, so we will start from our highest note and go down.
-- We calculate the notes ourselves and put them in a table.
for i = 88, 1, -1 do
pitch = pitch / multiplier
table.insert(pitchTable,1,pitch)
end
--print(table.concat(pitchTable,"\n"))
-- These are the 'Guitar chords' and the notes making up each one.
-- Further work needed to expand the range of chords known.
chordList = {
["C"]={"C","E","G"},
["C7"]={"C","E","G","^A"},
["D"]={"D","^F","A"},
["D7"]={"D","^F","A","c"},
["Dm"]={"D","F","A"},
["Dm7"]={"D","F","A","c"},
["E"]={"E","^G","B"},
["Em"]={"E","G","B"},
["F"]={"F","A","c"},
["G"]={"G","B","D"},
["G7"]={"G","B","D","F"},
["A"]={"A","^C","E"},
["Am"]={"A","C","E"},
["Am7"]={"A","C","E","G"},
["Bb"]={"_B","D","F"},
["Bm"]={"B","D","^F"}}
-- Print the raw ABC tune for debugging
if DEBUG then print(_ABCtune) end
-- This is a table of patterns that we use to match against the ABC tune.
-- We use these to find the next, biggest meaningful bit of the tune.
-- Lua patterns is like RegEx, in that we can specify parts of the match to be captured with
-- sets of parentheses.
-- Not all tokens have been implemented yet, but at least we understand
-- musically what is going on.
tokenList = {
TOKEN_REFERENCE = "^X:%s?(.-)\n",
TOKEN_TITLE = "^T:%s?(.-)\n",
TOKEN_COMMENT = "%%.-\n",
TOKEN_KEY = "%[?K:%s?(%a[b#]?)%s?(%a*)[%]\n]", -- matches optional inline [K:...]
TOKEN_METRE = "%[?M:%s?(.-)[%]\n]",
TOKEN_DEFAULT_NOTE_LENGTH = "%[?L:%s?(%d-)%/(%d-)[%]\n]",
TOKEN_TEMPO = "%[?Q:%s?(%d*%/?%d*)%s?=?%s?(%d*)[%]\n]", -- matches deprecated, see standard
TOKEN_CHORD_DURATION = '%[([%^_=]?[a-gA-G][,\']?[,\']?[,\']?%d*/?%d?.-)%]',
TOKEN_GUITAR_CHORD = '"(%a+%d?)"',
--[[ TOKEN_START_REPEAT = '|:',
TOKEN_END_REPEAT = ':|',
TOKEN_END_REPEAT_START = ":|?:",
TOKEN_NUMBERED_REPEAT_START = "[|%[]%d",
--]]
TOKEN_NOTE_DURATION = '([%^_=]?[a-gA-GzZ][,\']?[,\']?[,\']?)(%d*%.?%d?/?%d?)',
--[[ TOKEN_PREV_DOTTED_NEXT_HALVED = ">",
TOKEN_PREV_HALVED_NEXT_DOTTED = "<",
TOKEN_SPACE = "%s",
TOKEN_BARLINE = "|",
TOKEN_DOUBLE_BARLINE = "||",
TOKEN_THIN_THICK_BARLINE = "|%]",
TOKEN_NEWLINE = "\n",
--TOKEN_DOUBLE_FLAT = "__",
--TOKEN_DOUBLE_SHARP = "%^^", --]]
TOKEN_ACCIDENTAL = "([_=\^])",
--[[TOKEN_REST_DURATION = "(z)(%d?/?%d?)",
TOKEN_REST_MULTIMEASURE = "(Z)(%d?)",
TOKEN_TRILL = "~",
TOKEN_START_SLUR = "%(",
TOKEN_END_SLUR = "%)",
TOKEN_STACATO = "%.",--]]
-- TOKEN_TUPLET = "%(([1-9])([%^_=]?[a-gA-G][,']?[,\']?[,\']?[%^_=]?[a-gA-G]?[,']?[,\']?[,\']?[%^_=]?[a-gA-G]?[,']?[,\']?[,\']?)",
TOKEN_TUPLET_INDICATOR = "%([1-9]:?([1-9]?):?([1-9]?)",
TOKEN_TIE = "([%^_=]?[a-gA-G][,\']?[,\']?[,\']?)%d?/?%d?%-^[%]]-(%1%d?/?%d?%-?)", -- greedy?
TOKEN_DYNAMIC = "!([pmf]-)!",
TOKEN_MISC_FIELD = "^[(ABCDEFGHIJNOPRSUVWYZmrsw)]:([^|]-)\n"} -- no overlap with
-- already specified fields like METRE or KEY
-- sound(SOUND_BLIT, 10393)
self:parseTune(_ABCTune)
-- sound(SOUND_PICKUP, 45359)
self:createSoundTable()
-- sound(SOUND_JUMP, 25400)
self:preCache()
--sound(SOUND_EXPLODE, 16774)
--self:preCacheSort()
if DUMP then
dump(self.soundTable) -- for debugging
end
end
function ABCMusic:convertStringFraction(s)
if string.sub(s,1,1) == "/" then
s = "1"..s
end
if s == "1/" then
s = "1/2"
end
if string.find(s, "/") ~= nil then
local numerator = tonumber(string.sub(s,1,string.find(s,"/")-1))
local denominator = tonumber(string.sub(s,string.find(s,"/")+1))
s = numerator / denominator
end
return s
end
function ABCMusic:parseTune(destructableABCtune)
self.destructableABCtune = destructableABCtune
if self.DEBUG then print(self.destructableABCtune.."\n") end
-- Go through the tune looking for ties and replace them with a single note of longer duration
local searchStartIndex
-- find the first match beyond the key sig and index it
local startTieIndex
local endTieIndex
local tieCapture1
local tieCapture2
local originalTieDurationLength
local endKeySigIndex
_, endKeySigIndex = string.find(self.destructableABCtune, tokenList["TOKEN_KEY"],searchStartIndex)
searchStartIndex = endKeySigIndex
--
repeat
startTieIndex, endTieIndex, tieCapture1, tieCapture2 = string.find(self.destructableABCtune, tokenList["TOKEN_NOTE_DURATION"].."-",searchStartIndex)
-- determine if the start tie was in a chord or not
local startedInTie
local startChord, _ = string.find(self.destructableABCtune, "[",endTieIndex,true)
local endChord, _ = string.find(self.destructableABCtune, "]",endTieIndex,true)
-- print(endChord)
--print(startChord)
if (endChord == nil and startChord == nil) or endChord == nil then
startedInTie = false
else
if startChord == nil then
startedInTie = true
else
if endChord > startChord then
startedInTie = false
else
startedInTie = true
end
end
end
local originalEndTieIndex = endTieIndex
if tieCapture2 == nil or tieCapture2 == "" then
originalTieDurationLength = 0
tieCapture2 = 1
else
originalTieDurationLength = #tieCapture2
end
if startTieIndex ~= nil then
if self.DEBUG then print("Tie start, end and 1 & 2: "..startTieIndex, endTieIndex, tieCapture1, tieCapture2) end
-- find the next match
local startNextTieIndex
local endNextTieIndex
local tieNextCapture1
local tieNextCapture2
local possHyphen
local totalTieDuration = ABCMusic:convertStringFraction(tieCapture2)
if totalTieDuration == "" then
totalTieDuration = 1
end
while true do
-- the end tie index will expand and contract depending on what the pattern match was.
startNextTieIndex, endNextTieIndex, tieNextCapture1, tieNextCapture2, possHyphen =
string.find(self.destructableABCtune, "("..tieCapture1..")(%d*/?%d?)([^,\'])",endTieIndex)
if startNextTieIndex == nil then
if self.DEBUG then print("Unresolved tie at ".. endTieIndex) end
break
end
if self.DEBUG then print("next start, end, 1 & 2 and ph: "..startNextTieIndex, endNextTieIndex, tieNextCapture1, tieNextCapture2, possHyphen) end
if tieNextCapture2 == "" or tieNextCapture2 == nil then
tieNextDurationLength = 0
tieNextCapture2 = "1"
else
tieNextDurationLength = #tieNextCapture2
end
-- print("capture 2 ".. tieNextCapture2)
totalTieDuration = totalTieDuration + ABCMusic:convertStringFraction(tieNextCapture2)
-- if the next match also has a - (tie) then iterate again. after the duartion
-- delete the all but the orginal tie
-- print(string.sub(self.destructableABCtune,endNextTieIndex+1,endNextTieIndex+1))
--local possHyphen = string.sub(self.destructableABCtune,endNextTieIndex+1,endNextTieIndex+1)
if possHyphen ~= "-" then
local firstPart = string.sub(self.destructableABCtune,1,startNextTieIndex-1)
local secondPart = string.sub(self.destructableABCtune,endNextTieIndex)
self.destructableABCtune = firstPart..secondPart
--print("no more ties combining ".. firstPart.." with ".. secondPart)
break
else
-- we found a hyphen
local firstPart = string.sub(self.destructableABCtune,1,startNextTieIndex-1)
local secondPart = string.sub(self.destructableABCtune,endNextTieIndex+(1))
--print("endnextTieIndex is "
-- ..string.sub(self.destructableABCtune,endNextTieIndex,endNextTieIndex))
self.destructableABCtune = firstPart..secondPart
--print("another attached tie, combining ".. firstPart.." with ".. secondPart)
end
endTieIndex = endNextTieIndex
--print(self.destructableABCtune)
end
if self.DEBUG then print("total tie duration "..totalTieDuration ) end
--print("originalEndTieIndex is "
-- ..string.sub(self.destructableABCtune,originalEndTieIndex,originalEndTieIndex))
-- if the initial tie was in a chord, we need to add a rest with the original duration
-- otherwise we won't move on from the chord in time.
local firstPart = string.sub(self.destructableABCtune,1,originalEndTieIndex-(1+originalTieDurationLength))
local secondPart = string.sub(self.destructableABCtune,originalEndTieIndex+(1))
local searchStartAddition
if startedInTie == true then
local middleBit = totalTieDuration.."z".. tieCapture2
self.destructableABCtune = firstPart.. middleBit .. secondPart
-- print("started in tie, added "..middleBit)
searchStartAddition = #middleBit
else
local createdChord = "["..tieCapture1..totalTieDuration .. "z"..tieCapture2.."]"
self.destructableABCtune = string.sub(self.destructableABCtune,1,startTieIndex-1)
.. createdChord .. secondPart
searchStartAddition = #createdChord + 1
-- string.sub(self.destructableABCtune,1,originalEndTieIndex)
-- .. "["..tieCapture1..totalTieDuration.."]"..secondPart
-- .. "z"..tieCapture2.."]"..secondPart)
-- print("did not start in tie, added "..createdChord .. " and searching from " ..searchStartIndex)
end
-- print("originalTieDurationLength is "..originalTieDurationLength)
-- print("finished ".. firstPart.." with ".. totalTieDuration.. " and "..secondPart)
-- inch forward to start the next search
searchStartIndex = searchStartIndex + searchStartAddition
end
until originalEndTieIndex == nil
--[[ turn all the chords with only note into single notes
searchStartIndex = 1
local middlePart
local rawMatch
-- while true do
repeat
-- find next instance of chord
startChordIndex, endChordIndex, rawMatch = string.find(self.destructableABCtune, tokenList["TOKEN_CHORD_DURATION"],searchStartIndex)
-- bail if none found
if startChordIndex == nil then break end
-- if only one note in chord, delete the brackets
-- if, starting from the third character, we don't find any notes
if string.find(rawMatch, tokenList["TOKEN_NOTE_DURATION"],2) == nil then
--print(startChordIndex, endChordIndex, rawMatch)
firstPart = string.sub(self.destructableABCtune,1,startChordIndex-1)
middlePart = string.sub(self.destructableABCtune,startChordIndex+1,endChordIndex-1)
secondPart = string.sub(self.destructableABCtune,endChordIndex+1)
self.destructableABCtune = firstPart..middlePart..secondPart
end
searchStartIndex = endChordIndex
until rawMatch == nil
--]]
if self.DEBUG then print(self.destructableABCtune) end
------
-- Go through each token and find the first match in the tune. Use the biggest lowest
-- starting index and then discard the characters that matched.
local lastLongest = 0
self.parsedTune = {}
-- We create a copy of the tune to whittle away at.
--destructableABCtune = ABCtune
local lastToken
local lastTokenMatch
local captureFinal1
local captureFinal2
-- Iterate through the tune until none left
while true do
-- Loop through all tokens to see which one matches the start of the whittled tune.
for key, value in pairs(tokenList) do
local token = value
-- Find the start and end index of the token match, plus record what was in the
-- pattern capture parentheses. I pulled out a max two captures for each match, which
-- seemed adequate.
local startIndex
local endIndex
local capture1
local capture2
startIndex, endIndex, capture1, capture2 = string.find(self.destructableABCtune, token)
if startIndex == nil then startIndex = 0 end
if endIndex == nil then endIndex = 0 end
-- Get the actual match from the tune
local tokenMatch = string.sub(self.destructableABCtune,startIndex, endIndex)
-- if self.DEBUG and tokenMatch ~= "" then print(key.." token in first pass: ".. tokenMatch) end
-- Take the one that matches the start of the whittled tune.
if startIndex == 1 then
-- In case there are two possible matches, then take the biggest one.
-- This shouldn't happen if the token patterns are right.
if endIndex > lastLongest then
-- if self.DEBUG then print(lastLongest.." arrooga ".. key.." "..endIndex) end
lastLongest = endIndex
lastToken = key
lastTokenMatch = tokenMatch
captureFinal1 = capture1
captureFinal2 = capture2
end
end
end
if lastTokenMatch == "" then
if self.DEBUG then
print("No match found for character ".. string.sub(self.destructableABCtune,1,1) )
print("Remaining characters: ".. #self.destructableABCtune)
end
-- set the whittler to trim the strange character away
lastLongest = 1
else
-- Build a table containing the parsed tune.
-- Due to iterative delays in the print function needed for debugging, we will use
-- a 4-strided list for quicker printing it later with table.concat().
table.insert(self.parsedTune,lastToken)
table.insert(self.parsedTune,lastTokenMatch)
-- Where no captures occurred, we will just fill the table item with 1,
-- which will be the default duration of a note that has no length modifier.
if captureFinal1 == "" or captureFinal1 == nil then captureFinal1 = 1 end
if captureFinal2 == "" or captureFinal2 == nil then captureFinal2 = 1 end
table.insert(self.parsedTune,captureFinal1)
table.insert(self.parsedTune,captureFinal2)
end
-- Whittle off the match
self.destructableABCtune = string.sub(self.destructableABCtune, lastLongest + 1)
-- Stop the loop once we have no tune left to parse
if string.len(self.destructableABCtune) == 0 then
break
end
-- Clear the variables
lastLongest = 0
lastToken = ""
lastTokenMatch = ""
end
-- For debugging purposes, print the whole parsed tune.
if self.DEBUG then print(table.concat(self.parsedTune,"\n")) end
end
function ABCMusic:createSoundTable()
-- Here we interpret the parsed tune into a table of notes to play and for how long.
-- The upside of an intermediate process is that there will be no parsing delays to lag
-- things if we are playing music in the middle of a game. It is also easier to debug!
-- On the other hand, ABC format allows for inline tempo or metre changes. To comply
-- we would need to either switch duration to seconds rather than beats, or implement another
-- parsing thing during playback...
local duration
local tempChord={}
local parsedTunePointer = 1
while true do
if self.parsedTune[parsedTunePointer] == nil then break end
-- Break out our 4-strided list into the token, what it actually matched, and the
-- two captured values.
token = self.parsedTune[parsedTunePointer]
rawMatch = self.parsedTune[parsedTunePointer + 1]
value1 = self.parsedTune[parsedTunePointer + 2]
value2 = self.parsedTune[parsedTunePointer + 3]
-- Doing anything here seems to take forever.
-- print(token.."\n"..rawMatch.."\n"..value1.."\n"..value2) end
-- this is so cool: setting the key sig
if token == "TOKEN_KEY" then
if value2 == 1 then
self.mode = "major"
else
self.mode = value2
end
-- search cycle for marching tonic.
for i = 1, #cycleOfFifths do
if cycleOfFifths[i] == value1 then
cycleOfFifthsIndex = i
break
end
end
if self.DEBUG then print("index of key of cycle is "..cycleOfFifthsIndex) end
if self.DEBUG then print("mode is "..self.mode) end
self.accidentals = ""
if cycleOfFifthsIndex~= nil then
if self.mode == "minor" then
cycleOfFifthsIndex = cycleOfFifthsIndex - 3
end
if cycleOfFifthsIndex > 8 then -- if on the right hand side of circle
for x = 7, (cycleOfFifthsIndex - 2) do
self.accidentals = self.accidentals .. cycleOfFifths[x]
end
end
-- if the key is C major or A minor, the centre of the cycle,
-- no accidentals are needed.
if cycleOfFifthsIndex < 8 then -- if on the left hand side of circle
for x = 6, (cycleOfFifthsIndex - 1), -1 do
self.accidentals = self.accidentals .. cycleOfFifths[x]
end
end
if self.DEBUG then print("Looking for these sharps: " .. self.accidentals) end
end
end
if token == "TOKEN_TEMPO" then
if string.find(value1,"/") then
self.tempo = tonumber(value2)
else
self.tempo = tonumber(value1)
self.tempoIsSingleFigure = true -- This is deprecated in the ABC standard
end
if self.DEBUG then print("Tempo found at: " .. self.tempo) end
-- iparameter("ptempo", 40, 480, self.tempo)
end
if token == "TOKEN_DEFAULT_NOTE_LENGTH" then
noteLength = value2
-- Set the tempo, eg if you wanted one quarter note or crotchet per second
-- you would set Q:60 and L:1/4
if self.tempoIsSingleFigure == true then
self.tempo = self.tempo * (noteLength/4)
end
if self.DEBUG then print("internal Tempo is " .. self.tempo) end
end
if token == "TOKEN_DYNAMIC" then
local dynamic = value1
-- Changed from ABC standard suggested range from 0 to 127
if dynamic == "pppp" then gnNoteVolume = 5/127 end
if dynamic == "ppp" then gnNoteVolume = 20/127 end
if dynamic == "pp" then gnNoteVolume = 35/127 end
if dynamic == "p" then gnNoteVolume = 50/127 end
if dynamic == "mp" then gnNoteVolume = 65/127 end
if dynamic == "mf" then gnNoteVolume = 80/127 end
if dynamic == "f" then gnNoteVolume = 95/127 end
if dynamic == "ff" then gnNoteVolume = 110/127 end
if dynamic == "fff" then gnNoteVolume = 125/127 end
if dynamic == "ffff" then gnNoteVolume = 127/127 end
if self.DEBUG then print("dynamic is " .. dynamic) end
end
if token == "TOKEN_NOTE_DURATION" then
if self.remainingTupletNotes > 0 then
self.remainingTupletNotes = self.remainingTupletNotes - 1
else
self.tupletMultiplier = 1
end
duration = value2
-- because the ABC standard allows /4 to mean 1/4, we fix that here
if string.sub(duration,1,1) == "/" then
duration = "1"..duration
end
if duration == "1/" then
duration = "1/2"
end
if string.find(duration, "/") ~= nil then
duration = ABCMusic:convertStringFraction(duration)
end
-- hack for key signature
firstChar = string.upper(string.sub(value1,1,1))
if firstChar ~= "^" and firstChar ~= "_" then
if string.find(self.accidentals,firstChar) ~= nil then
if cycleOfFifthsIndex > 8 then
value1 = "^" .. value1
end
if cycleOfFifthsIndex < 8 then
value1 = "_" .. value1
end
end
end
if firstChar == "=" then
value1 = string.sub(value1,2)
end
-- If there are chords to play at the same time, they will be in the tempChord table.
if value1~="z" then
table.insert(tempChord,{ABCMusic:convertNoteToPitch(value1), ABCMusic:convertDurationToSeconds(duration,self.tempo)* self.tupletMultiplier,gnNoteVolume})
else
table.insert(tempChord,{"z", ABCMusic:convertDurationToSeconds(duration* self.tupletMultiplier,self.tempo),0})
end
table.insert(self.soundTable,tempChord)
tempChord = {}
end
if token == "TOKEN_REST_DURATION" then
duration = value2
if string.sub(duration,1,1) == "/" then
duration = "1"..duration
end
if string.find(duration, "/") ~= nil then
duration = ABCMusic:convertStringFraction(duration)
end
duration = tonumber(duration)
table.insert(self.soundTable,{{"z", ABCMusic:convertDurationToSeconds(duration,self.tempo),gnNoteVolume}})
end
if token == "TOKEN_TIE" then
value1, duration1 = string.match(value1,tokenList["TOKEN_NOTE_DURATION"])
value2, duration2 = string.match(value2,tokenList["TOKEN_NOTE_DURATION"])
if self.DEBUG then print("val1 " .. value1.. " value2 ".. value2) end
if string.sub(duration1,1,1) == "/" then
duration1 = "1"..duration1
end
if string.find(duration1, "/") ~= nil then
duration1 = ABCMusic:convertStringFraction(duration1)
end
if string.sub(duration2,1,1) == "/" then
duration2 = "1"..duration2
end
if string.find(duration2, "/") ~= nil then
duration2 = ABCMusic:convertStringFraction(duration2)
end
if duration1 == nil or duration1 == "" then duration1 = 1 end
if duration2 == nil or duration2 == "" then duration2 = 1 end
if self.DEBUG then print("dur1 ".. duration1 .. "dur2 ".. duration2) end
duration = tonumber(duration1) + tonumber(duration2)
table.insert(self.soundTable,{{ABCMusic:convertNoteToPitch(value1), ABCMusic:convertDurationToSeconds(duration,self.tempo),gnNoteVolume}})
end
if token == "TOKEN_METRE" then
self.metre = value1
end
if token == "TOKEN_TUPLET_INDICATOR" then
if self.DEBUG then print("tuplet was "..rawMatch) end
self.p = tonumber(string.sub(rawMatch,2,2))
if value1 == 1 then
if self.p == 3 then self.p = 2 end
if self.p == 2 then self.p = 3 end
if self.p == 4 then self.p = 3 end
if self.p == 5 or self.p == 7 or self.p == 9 then
if string.sub(self.metre,-1,-1) == 8 then
self.p = 3
else
self.p = 2
end
end
if self.p == 6 then self.p = 2 end
if self.p == 8 then self.p = 3 end
else
self.q = value1
end
if value2 == 1 then
self.remainingTupletNotes = self.p
else
self.remainingTupletNotes = tonumber(value2)
end
-- 'put p notes into the time of q for the next r notes'. ABC Standard.
-- If q is not given, it defaults as above. If r is not given, it defaults to p.
self.tupletMultiplier = self.q/self.p
if self.DEBUG then print("p "..self.p .." q ".. self.q .." r ".. self.remainingTupletNotes) end
end
--[[
if token == "TOKEN_TUPLET" then
-- More types of tuplets exist, up to 9, but need more work.
if value1 == "2" then
duration = 1.5 -- the 2 signals two notes in the space of three
-- We reprocess the notes making up the tuplet
for i = 1, string.len(value2) do
note,noteLength = string.match(value2,tokenList["TOKEN_NOTE_DURATION"],i)
table.insert(self.soundTable,{{ABCMusic:convertNoteToPitch(note), ABCMusic:convertDurationToSeconds(duration,self.tempo),gnNoteVolume}})
end
end
if value1 == "3" then
duration = 1/3 -- the 3 signals three notes in the space of two
-- We reprocess the notes making up the tuplet
for i = 1, string.len(value2) do
note,noteLength = string.match(value2,tokenList["TOKEN_NOTE_DURATION"],i)
table.insert(self.soundTable,{{ABCMusic:convertNoteToPitch(note), ABCMusic:convertDurationToSeconds(duration, self.tempo),gnNoteVolume}})
end
end
end
--]]
if token == "TOKEN_GUITAR_CHORD" then
-- The ABC standard leaves it up to the software how to interpret guitar chords,
-- but they should precede notes in the ABC tune. I'm just going with a vamp.
duration = 1
self.tempChord = {}
if chordList[value1] == nil then
print("Chord ".. value1.. " not found in chord table.")
else
for key, value in pairs(chordList[value1]) do
-- This places the notes of the chord into a temporary table which will
-- be appended to by the next non-chord note.
table.insert(self.tempChord,{ABCMusic:convertNoteToPitch(value1), ABCMusic:convertDurationToSeconds(duration, self.tempo),gnNoteVolume})
end
end
end
if token == "TOKEN_CHORD_DURATION" then
-- These are arbitrary notes sounded simultaneously.
if self.remainingTupletNotes > 0 then
self.remainingTupletNotes = self.remainingTupletNotes - 1
else
self.tupletMultiplier = 1
end
while true do
-- Do this loop unless we have already whittled away the chord into notes.
if string.len(rawMatch) <= 1 then
break
end
-- Reprocess the chord into notes and durations.
startIndex, endIndex, note, noteDuration =
string.find(rawMatch,tokenList["TOKEN_NOTE_DURATION"])
if noteDuration == "" or noteDuration == nil then
noteDuration = 1
else
noteDuration = ABCMusic:convertStringFraction(noteDuration)
end
if note == nil then break end
-- hack for key signature
--print("note is ".. note)
firstChar = string.upper(string.sub(note,1,1))
if firstChar ~= "^" and firstChar ~= "_" then
if string.find(self.accidentals,firstChar) ~= nil then
if cycleOfFifthsIndex > 8 then
note = "^" .. note
--print("added sharp to "..note)
end
if cycleOfFifthsIndex < 8 then
note = "_" .. note
-- print("added flat to "..note)
end
end
end
if firstChar == "=" then
note = string.sub(note,2)
end
-- This places the notes of the chord into a temporary table which will
-- be appended to the sound table at the end of the chord.
if note ~= "z" then
table.insert(tempChord,{ABCMusic:convertNoteToPitch(note), ABCMusic:convertDurationToSeconds(noteDuration, self.tempo)*self.tupletMultiplier,gnNoteVolume})
else
table.insert(tempChord,{"z", ABCMusic:convertDurationToSeconds(noteDuration, self.tempo)*self.tupletMultiplier,0})
end
-- Whittle away the chord
rawMatch = string.sub(rawMatch, endIndex + 1)
end
-- Append chord to sound table.
table.insert(self.soundTable,tempChord)
tempChord = {}
end
-- Move to the next token in our strided list of 4.
parsedTunePointer = parsedTunePointer + 4
end
-- print(self.dataName)
--saveProjectData(self.dataName, self.soundTable)
end
function ABCMusic:fromTheTop()
self.soundTablePointer = 1
end
function ABCMusic:fade(targetVolume, seconds)
-- targetVolume is a value from 0 to 1, over duration seconds, giving a linear fade
if gnMasterVolume == nil then gnMasterVolume = 0.5 end
gnFadeSecondsTarget = seconds
gnFadeCountup = 0
gnFadeAmount = targetVolume - gnMasterVolume
-- print("Fading over " .. gnFadeSecondsTarget)
-- print("len music.next is "..#Music.next)
end
function ABCMusic:play()
-- Step through the parsed tune and decide whether to play the next bit yet.
ABCMusic:timer(0,"x=2")
-- This normalises the tempo to smooth out lag between cumlative frames. Meant to be the
-- same idea for smoothing out animation under variable processing loads.
self.timeElapsedSinceLastNote = self.timeElapsedSinceLastNote + DeltaTime
-- If there is still a tune and it's time for the next set of notes
if gnDurationSeconds <= self.timeElapsedSinceLastNote
and self.soundTablePointer <= #self.soundTable then
-- Step through the set of notes nested in the sound table, finding each note and
-- its duration. If we had volume, we would also want to record it in the most nested
-- table.
-- The operator # gives us the number of elements in a table until a blank one - see Lua
-- documentation.
-- Luckily our table will never have holes in it, or the notes would fall through.
-- The sound table looks like:
-- 1: 1: 1: 44 -- 44th key of piano is A 440 hz
-- 2: 0.5 -- seconds duration
-- 2: 1: 46 -- 46th key is B
-- 2: 0.75
-- 2: etc...
oldTempDuration=0
tempDuration = 0
if gnFadeCountup < gnFadeSecondsTarget then
gnFadeCountup = gnFadeCountup + self.timeElapsedSinceLastNote
gnMasterVolumeModifier = ((gnFadeCountup/gnFadeSecondsTarget) * gnFadeAmount)
if (gnMasterVolume + gnMasterVolumeModifier) < 0 or (gnMasterVolume + gnMasterVolumeModifier) > 1
then gnMasterVolumeModifier = gnFadeAmount
end
end
--if gnMasterVolumeModifier == gnFadeAmount then print("fade done") end
for i = 1, #self.soundTable[self.soundTablePointer] do
oldTempDuration = tempDuration
-- This bit plays the note currently being pointed to. If it is part of a set
-- to be played at once, this will loop around without delay.
gnPitchBeingPlayed = self.soundTable[self.soundTablePointer][i][1]
-- gnNoteBeingPlayed = notes[self.soundTable[self.soundTablePointer][i][1]]
--print(self.soundTable[self.soundTablePointer][i][2])
gnDurationSeconds = ( tonumber(self.soundTable[self.soundTablePointer][i][2]))
--print("temp dur was ".. tempDuration)
tempDuration = gnDurationSeconds
-- soundDuration = (tempDuration/2)*(60/self.tempo)
--print(" sound dur is".. soundDuration)
gnNoteVolume = ( tonumber(self.soundTable[self.soundTablePointer][i][3]))
-- we will multiply this by gnMasterVolume in the sound() call
if gnPitchBeingPlayed ~= "z" then
-- look up based on key of noteNo and the length of note
--print("note "..gnPitchBeingPlayed.."/"..gnDurationSeconds)
-- print("buffer "..bufferTable[gnPitchBeingPlayed.."/"..gnDurationSeconds])
-- sound(bufferTable[gnPitchBeingPlayed.."/"..gnDurationSeconds],gnNoteVolume)
local soundTable = {Waveform = 2, StartFrequency = gnPitchBeingPlayed, SustainTime = 0.6*(math.sqrt(gnDurationSeconds))}
sound(DATA, sound( ENCODE, soundTable ),gnNoteVolume*(gnMasterVolume+gnMasterVolumeModifier))
--sound({Waveform = 0, StartFrequency = gnPitchBeingPlayed, SustainTime = 0.6*(math.sqrt(gnDurationSeconds)), Volume = gnNoteVolume})
end
if self.DEBUG then
y = y + 20
if y > HEIGHT then y=0 end
background(0, 0, 0, 255)
text(gnPitchBeingPlayed .." " ..gnDurationSeconds, WIDTH/2, HEIGHT - y)
end
self.semitoneModifier = 0
-- Keep the shortest note duration of the set of notes to be played together,
-- to be used as one of the inputs for the delay until the next note.
if oldTempDuration ~= 0 and oldTempDuration < tempDuration then
-- print("overtook " .. tempDuration)
tempDuration = oldTempDuration
end
end
-- print("shortest was " .. tempDuration)
gnDurationSeconds = tempDuration
-- Looping music... we need a better way to do this...
--print(duration)
if self.LOOP ~= nil and self.soundTablePointer == #self.soundTable then
self.soundTablePointer = 1
else
-- Increment the pointer in our sound table.
self.soundTablePointer = self.soundTablePointer + 1
end
-- Reset counters rather than going to infinity and beyond.
self.timeElapsedSinceLastNote = 0
end
end
function ABCMusic:noteBeingPlayed()
return gsNoteBeingPlayed
end
function ABCMusic:convertNoteToPitch(n)
self.semitoneModifier = 0
gsNoteBeingPlayed = n
for j = 1, #gsNoteBeingPlayed do
local currentChar = string.sub(gsNoteBeingPlayed,j,j)
if currentChar == "_" then
self.semitoneModifier = self.semitoneModifier - 1
end
if currentChar == "\^" then
self.semitoneModifier = self.semitoneModifier + 1
currentChar = "%^"
end
-- NB need to implement naturals =
-- if the current char is a note
if string.find("abcdefg",string.lower(currentChar)) ~= nil then
-- modify octave
-- search through the next characters for , and '
local nextCharIndex = 1
local nextChar = string.sub(gsNoteBeingPlayed,j+nextCharIndex,j+nextCharIndex)
if nextChar == "," then
self.semitoneModifier = self.semitoneModifier - 12
end
if nextChar == "'" then
self.semitoneModifier = self.semitoneModifier + 12
end
pos = string.find(gsNoteOrder,currentChar)
local tonalModifier = string.sub(gsTonalSystem, 1, pos - 1)
for i = 1, #tonalModifier do
self.semitoneModifier = self.semitoneModifier + tonumber(string.sub(tonalModifier,i,i))
end
end
end
-- gnNoteBeingPlayed = notes[self.soundTable[self.soundTablePointer][i][1]]
--print(self.soundTable[self.soundTablePointer][i][2])
pos = self.semitoneModifier + 44
-- gnerate sound buf ffrom here?
pitch = pitchTable[pos]
return pitch -- changed from pitch to pos and back again, use pitch if encodingsound
end
function ABCMusic:convertDurationToSeconds(d,t)
tempDuration = d
--print("temp dur was ".. tempDuration)
soundDuration = (tempDuration/2)*(60/t)
return soundDuration
end
function ABCMusic:adjustSoundBufferSize()
local sb
local used
sb,used = soundBufferSize()
--print(sb,used)
-- extend the cache if getting full
if used > (sb * 0.9) then
soundBufferSize(sb + 20)
end
end
-- A user function to see if an element exists in a table
function table.contains(table, element)
for _, value in pairs(table) do
if value[1] == element[1] and value[2] == element[2] then
return true
end
end
return false
end
function ABCMusic:preCache()
-- this function create the soundbuffer for all the ?unique? sounds.
-- better this delay comes all at once at the beginning than during the performance.
-- cover it with a loading screen.
if gPreCacheSoundTable == nil then
gPreCacheSoundTable = {}
end
-- If the table already exists it means this is another round of loading, so we
-- have already played the sounds in the table. To save us from playing them again,
-- we match any sounds and don't add them. Then we delete the earlier sounds.
local originalTableLength = #gPreCacheSoundTable
-- print("orig tab length ".. originalTableLength)
-- flatten sound table
for i=1,#self.soundTable do
for j=1, #self.soundTable[i] do
local data = {self.soundTable[i][j][1], self.soundTable[i][j][2]}
-- if not already in there
if table.contains(gPreCacheSoundTable, data) == false and data[1] ~="z" then
table.insert(gPreCacheSoundTable, data)
--print("added unique sound "..data[1].." "..data[2])
else
-- print("skipped dupe sound"..data[1].." "..data[2])
end
-- end
end
end
end
function ABCMusic:preCachePlay()
-- play it all! this runs in main:draw() and should trigger whenever new sounds are added
-- if we're done caching then do nothing
if cachedIdx == nil then return true end
if cachedIdx >= #gPreCacheSoundTable then return true end
-- is it time to cache a new sound?
if ElapsedTime > nextT then
cachedIdx = cachedIdx + 1
--print("caching",self.cachedIdx)
ABCMusic:adjustSoundBufferSize()
nextT = nextT + cachingSpeed
gnPitchBeingPlayed = gPreCacheSoundTable[cachedIdx][1]
gnDurationSeconds = ( tonumber(gPreCacheSoundTable[cachedIdx][2]))
gnNoteVolume = 0 -- silent, otherwise: cacophony!
local soundTable = {Waveform = 2, StartFrequency = gnPitchBeingPlayed, SustainTime = 0.6*(math.sqrt(gnDurationSeconds))}
ABCMusic:adjustSoundBufferSize()
sound(DATA, sound( ENCODE, soundTable ),gnNoteVolume)
end
if self.DEBUG then
print(soundBufferSize())
print("that was " .. gnPitchBeingPlayed.." "..gnDurationSeconds)
end
end
function ABCMusic:timer(seconds, code)
if seconds == 0 then
if self.timerSeconds ~= nil then
-- being called as part of draw(), check the time
if self.time > self.timerSeconds and self.timerSeconds > 0 then
-- execute code as timer is up
loadstring(self.code)()
self.time = 0
self.timerSeconds = 0
print("executed :", self.code)
end
end
else
-- got some code, start the timer
self.code = code
self.timerSeconds = seconds
self.time = 0
print("got code: ", self.code)
end
if self.timerSeconds ~= nil then
self.time = self.time + DeltaTime
end
end
-- Handy function from Pixel to only use for debugging and if the ABCtube is a line long,
-- 'cos it is slow.
-- print contents of a table, with keys sorted.
-- second parameter is optional, used for indenting subtables
function dump(t,indent)
local names = {}
if not indent then indent = "" end
for n,g in pairs(t) do
table.insert(names,n)
end
table.sort(names)
for i,n in pairs(names) do
local v = t[n]
if type(v) == "table" then
if(v==t) then -- prevent endless loop if table contains reference to itself
print(indent..tostring(n)..": <-")
else
print(indent..tostring(n)..":")
dump(v,indent.." ")
end
else
if type(v) == "function" then
print(indent..tostring(n).."()")
else
print(indent..tostring(n)..": "..tostring(v))
end
end
end
end
--# ABCMusicData
function sampleMusic()
-- An ABC tune is a string with newline characters to denote new lines.
-- See the many web pages on ABC musical notation to get a tune or an understanding of
-- this allegedly human- and machine-readable format.
-- You could even write your own by hand or use another program to convert a MIDI file.
ABCtune =
'X:1\n'
..'T:Bogg Blues\n'
..'C:Fred Bogg\n'
..'Q:1/8=240\n'
..'M:12/8\n'
..'L:1/8\n'
..'K:G\n'
..'D,|"G7"[G,2D,2][G,D,] [G,2E,2d2=f2][G,E,ce] "G7"[G,2D,2B2d2][G,D,] [G,2E,2c2e2][G,E,]|\n'
.. '"C"[C2G2][CG] [C2A2c2e2]"C"[CAd=f] "C"[C2G2e2g2][CG] [C2A2c2e2]"C"[CA] |\n'
..'"G7"[G,2D,2][G,D,] [G,2E,2d2=f2][G,E,ce] "G7"[G,2D,2B2d2][G,D,] [G,2E,2c2e2][G,E,G]|\n'
..'"G7"[G,2D,2d2=f2][G,D,] [G,2E,2c2e2][G,E,GBd] "G7"[G,2D,2][G,D,] [G,2E,2][G,E,]|\n'
..'"C"[C2G2][CG] [C2A2c2e2]"C"[CAd=f] "C"[C2G2e2g2][CG] [C2A2c2e2]"C"[CAg] |\n'
..'"C"[C2G2c2e2g2][CGc=fa] [C2A2c2e2g2]"C"[CA] "C"[C2G2][CG] [C2A2]"C"[CA] |\n'
..'"G7"[G,2D,2d2=f2][G,D,] [G,2E,2c2e2][G,E,] "G7"[G,2D,2G2B2d2][G,D,] [G,2E,2A2c2][G,E,]|\n'
..'"G7"[G,2D,2G2B2][G,D,] [G,2E,2=F2A2][G,E,D=FG] "G7"[G,2D,2][G,D,] [G,2E,2][G,E,]|\n'
..'"D7"[D2A2g2b2][DAac\'] [D2B2g2][DBd\'] "D7"[D2A2][DA] [D2B2]"D7"[DB]|\n'
..'"C"[C2G2][CGd=f] [C2A2][CAce] "C"[C2G2][CGd=f] [C2A2]"C"[CAce] |\n'
..'"G7"[G,2D,2b2d2][G,D,bdg] [G,2E,2][G,E,bdg] "G7"[G,2D,2C2E2][G,D,bdg] [G,2E,2][G,E,]|\n'
..'"D7"[D,2A,2d2][D,A,] [D,2B,2e2][D,B,] "D7"[D,2A,2f2][D,A,] [D,2B,2d2][D,B,]|\n'
..'"G7"g2[Bg] [Ca][Db][Ec] [=Fd][Ge][A=f]|"G7"Gbd Fbd "C7"Ece Gec|"G7"g3||\n'
BCtune =
'X:1\n'
..'% test\n'
..'T:Pac Man Theme\n'
..'C:Toshio Kai arr. Fred Bogg Copyright NAMCO\n'
..'Q:135\n'
..'M:4/4\n'
..'L:1/16\n'
..'K:C\n'
..'[B,B]b^f[B^d] b/2^f3/2^dB [C,C]c\'g[Ce] c\'/2g3/2[Ce]C|\n'
..'[B,B]b^f[B^d] b/2^f3/2^dB ^d/2e/2[^gf]f/2^f/2[^ag]g/2^g/2ab2'
BCtune =
'X:1\n'
..'T:Eine Kleine Nachtmusik, Violin 1\n'
..'C:Mozart\n'
..'Z:celestial\n'
..'Q:1/4=125\n'
..'M:4/4\n'
..'L:1/8\n'
..'K:G major\n'
..'G2 z D G2 z D |G D G B d2 z2 |c2 z A c2 z A |c A F A D2 z2 |G2 z G3 B A G |\n'
..'G F F3 A c F |A G G3 B A G |G F F3 A c F |G G G/2 F/2 E/2 F/2 G G B/2 A/2 G/2 A/2 |\n'
..'B B d/2 c/2 B/2 c/2 d2 z2 |D4 E4 |D/4 C2 C2 C/4 B,2 B,2 |B,/4 A,2 A,2 G, F, E, F, |\n'
..'G, z A, z B, z3 |D4 E4 |D C C C C B, B, B, |B, A, A, A, G, F, E, F, |\n'
..'G,5 G,/2 F,/4 G,/4 A, F, |B,5 B,/2 A,/4 B,/4 C A, |D4 E2 F2 |G2 A2 B2 ^c2 |\n'
..'d3 A ^c-^c/2 A/2 ^c-^c/2 A/2 |d3 A ^c-^c/2 A/2 ^c-^c/2 A/2 |d d2 d2 d2 d2 |\n'
..'d2 d2 d2 d |^c A d A ^C A d A |^c A, A, A, A,2 z2 |A3 G/3F/3E/3 D z B z |\n'
..'G z E z A z3 |F3 E/3D/3^c/3 B, z G z |F4 E2 z2 |z A A A A A A A |\n'
..'A A A A A A B ^c |^c d z B B A z ^C |D2 z A d ^c B A |B A z A A A A A |\n'
..'B A z A d ^c B A |B A z A A A A A |B A z2 B3 A/3G/3F/3 |G2 z2 A3 G/3F/3E/3 |\n'
..'F2 z2 B ^c/2 d/2 ^c B |B A F A A G F E |D2 z A d ^c B A |B A z A A A A A |\n'
..'B A z A d ^c B A |B A z A A A A A |B A z B3 A/3G/3F/3 |G2 z2 A3 G/3F/3E/3 |\n'
..'F2 z2 B ^c/2 d/2 ^c B |B A G A A G F E |D A, B, ^C D D E D/2 E/2 |\n'
..'F ^C D E F F G F/2 G/2 |A A ^A ^G/2 A/2 B2 z2 |B,3 E D ^C B, A, |D z F z D z3 |\n'
..'D2 z A, D2 z A, |D A, D F A2 z2 |A2 z F A2 z F |A F ^D F B,2 z2 |z3 G c B A G |\n'
..'A G z G G G G G |A G z G c B A G |A G z G G G G G |A G z G c B A G |\n'
..'A ^G z ^G ^G ^G ^G ^G |B A z A c _B A G |G ^F z ^F ^F ^F ^F ^F |A G z _E G F _E D |\n'
..'D ^C z ^C ^C ^C ^C ^C |E D z D, E, ^F, G, A, |C _B z F, G, A, _B, ^C |\n'
..'E D z D E F G A |_B2 B2 c2 ^c2 |d12 |F3 E/2 F/2 |G2 z D G2 z D |G D G B d2 z2 |\n'
..'c2 z A c2 z A |c A F A D2 z2 |G z G3 B A G |G F F3 A c F |A G G3 B A G |\n'
..'G F F3 A c F |G G G/2 F/2 E/2 F/2 G G B/2 A/2 G/2 A/2 |B B d/2 c/2 B/2 c/2 d2 z2 |\n'
..'D4 E4 |D/4 C2 C2 C/4 B,2 B,2 |B,/4 A,2 A,2 G, F, E, F, |G, z A, z B, z3 |D4 E4 |\n'
..'D C C C C B, B, B, |B, A, A, A, G, F, E, F, |G,5 G,/2 F,/4 G,/4 A, F, |\n'
..'B,5 B,/2 A,/4 B,/4 C A, |D4 E2 F2 |G2 A2 B2 ^c2 |d3 A ^c-^c/2 A/2 ^c-^c/2 A/2 |\n'
..'d3 A ^c-^c/2 A/2 ^c-^c/2 A/2 |d A ^c A d A ^c A |d D, D, D, D,2 z2 |\n'
..'D3 C/3B,/3A,/3 G, z E z |C z A, z D z3 |B3 A/3G/3F/3 E z c z |B4 A2 z2 |\n'
..'z d d d d d d d |d d d d d c A F |F G z E E D z F, |G,2 z D G F E D |\n'
..'E D z D D D D D |E D z D G F E D |E D z D D D D D |E D z2 E3 D/3C/3B,/3 |\n'
..'C2 z2 D3 C/3B,/3A,/3 |B,2 z2 E F/2 G/2 F E |E D B, D D C B, A, |G,2 z D G F E D |\n'
..'E D z D D D D D |E D z D G F E D |E D z D D D D D |E D z2 e3 d/3c/3B/3 |\n'
..'c2 z2 d3 c/3B/3A/3 |B2 z2 E F/2 G/2 F E |D G B d d c B A |G D, E, F, G, G, A, G,/2 A,/2 |\n'
..'B, F, G, A, B, B, C B,/2 C/2 |D D ^D ^C/2 ^D/2 E2 z2 |E,3 A, G, F, E, D, |\n'
..'D ^C C B, D ^C C B, |E,3 A, G, F, E, D, |D E F G D E F G |A2 z2 d2 z2 |G2 z D B, G, B, D |\n'
..'G D G B d2 F2 |G2 z D B, G, B, D |G D G B d2 F2 |G2 z2 G2 z2 |G2 G,-G,/2 G,/2 G,2 z2 ||\n'
ABCtune = 'X:1\n'
..'T:Beethoven - Moonlight Sonata (Clarinet)\n'
..'Z:Transcribed by Illyrean of Meneldor\n'
..'L:1/4\n'
..'Q:60\n'
..'K:C\n'
..'[^G,3/8z/8] ^D,/4 [^G,/8^D,/4] B,/8 [^D/8^G,/8] ^G,/4 [B,/8^D,/4] ^D/8\n'
..'[^G/8^G,3/8] B,/4 [^D/8^D,/4] ^G/8 [B/8^G,3/8] B,/4 [^G/8^D,/4] B/8\n'
..'[^d/8^G,3/8] ^G/4 [B/8^D,/4] ^d/8 [^g/4^G,3/8] B/8 [^d/8^D,/4] ^g/8\n'
..'[b/4^G,3/8] ^d/8 [^g/8^D,/4] b/8 [^d3/8b3/8^g3/8^G,3/8]\n'
..'[^d/4b/4^g/4^D,/4] [=G,3/8z/4] ^D,/8 [G,/8^D,/4] ^A,/8 [^D/4G,/4]\n'
..'G,/8 [^A,/8^D,3/8] ^D/4 [=G/8G,/4] ^A,/8 [^D/8^D,3/8] G/4 [^A/8G,/4]\n'
..'^D/8 [G/8^D,3/8] ^A/4 [^d/8G,/4] G/8 [^A/8^D,3/8] ^d/4 [=g/8G,/4]\n'
..'^A/8 [^d/8^D,3/8] g/4 [^a/8G,/4] ^d/8 [g/4^D,3/8] ^a/8\n'
..'[^d/4^a/4g/4G,/4] [^d3/8^a3/8g3/8^D,3/8] [^F,/4z/8] ^G,/8 [C/4^D,3/8]\n'
..'^D/8 [^G/8^F,/4] C/8 [^D/4^D,3/8] ^G/8 [c/8^F,/4] ^D/8 [^G/4^D,3/8]\n'
..'c/8 [^d/8^F,3/8] ^G/4 [c/8^D,/4] ^d/8 [^g/8^F,3/8] c/4 [^d/8^D,/4]\n'
..'^g/8 [c\'/8^F,3/8] ^d/4 [^g/8^D,/4] c\'/8 [^d/8^F,3/8] ^g/4 [c\'/8^D,/4]\n'
..'^d/8 [^g3/8^d3/8c\'3/8^F,3/8] [^g/4^d/4c\'/4^D,/4] [E,3/8z/4] ^G,/8\n'
..'[^C/8E/8] E/8 [^G/4E,3/8] ^G/8 [^c/8E/4] e/8 [^g/4E,3/8] ^g/8\n'
..'[^c/8E/4] e/8 [^g3/8^c3/8E,3/8] [^g/4^c/4E/4] [E,3/8z/4] ^G,/8\n'
..'[B,/8E3/8] =D/4 [^G/8E,/4] ^G/8 [B/8E3/8] =d/4 [^g/8E,/4] ^g/8\n'
..'[b/8E3/8] d/4 [^g/4d/4E,/4] [^g3/4d3/4E3/4] [=g/4^d/4^D,/4]\n'
..'[^d/8=G3/8^D19/4] ^d/4 [^d/8G/4] ^d/8 [f/8^G3/8] ^d/4 [g/8^A/4] ^d/8\n'
..'[^g/8B3/8] ^d/4 [^a/8^c/4] ^d/8 [=g/8^A3/8] ^d/4 [^a/8^c/4] ^d/8\n'
..'[^g/4B3/8] ^d/8 [^c/8e/4] ^d/8 [b/4^d/4] ^d/8 [^a/8^c/4] ^d/8\n'
..'[^g/4B3/8] ^d/8 [=g/8^A/4] ^d/8 [e/4^G3/8] =d/8 [^d/8=G/4^D5] ^d/8\n'
..'[^d/4G3/8] ^d/8 [^d/8G3/8] ^d/4 [f/8^G/4] ^d/8 [g/8^A3/8] ^d/4\n'
..'[^g/8B/4] ^d/8 [^a/8^c3/8] ^d/4 [=g/8^A/4] ^d/8 [^a/8^c3/8] ^d/4\n'
..'[^g/8B/4] ^d/8 [^c/8e3/8] ^d/4 [b/8^d/8] ^d/8 [^a/4^c3/8] ^d/8\n'
..'[^g/8B/4] ^d/8 [=g/4^A3/8] ^d/8 [e/8^G/4] =d/8 [^d/4=G3/8^D3/8] ^d/8\n'
..'[e/8^G/4^D/4] =d/8 [^d/4=G3/8^D3/8] ^d/8 [e/8^G/4^D/4] =d/8\n'
..'[^d/4=G3/8^D3/8] ^d/8 [e/8^G3/8^D3/8] =d/4 [^d/8=G/4^D/4] ^d/8\n'
..'[e/8^G3/8^D3/8] =d/4 [^d5/8=G5/8^D5/8] [^D15/8^D,15/8] [^G,/4z/8]\n'
..'^D,/8 [^G,/4^D,3/8] B,/8 [^D/8^G,/8] ^G,/8 [B,/4^D,3/8] ^D/8\n'
..'[^G/8^G,/4] B,/8 [^D/4^D,3/8] ^G/8 [B/8^G,/4] B,/8 [^G/4^D,3/8] B/8\n'
..'[^d/8^G,3/8] ^G/4 [B/8^D,/4] ^d/8 [^g/8^G,3/8] B/4 [^d/8^D,/4] ^g/8\n'
..'[b/8^G,3/8] b/4 [^d/8^D,/4] ^g/8 [b3/8^G,3/8] [b/4^D,/4] [=F,3/8z/8]\n'
..'B,/4 [=D/8^G,/4] ^G/8 [B/4F,3/8] D/8 [^G/8^G,/4] B/8 [=d/4F,3/8] ^G/8\n'
..'[B/8^G,/4] d/8 [^g/4F,3/8] B/8 [d/8^G,/4] ^g/8 [b/4F,3/8] d/8\n'
..'[^g/8^G,/4] b/8 [d/4F,3/8] ^g/8 [b/8^G,3/8] d/4 [^g/8F,/4] b/8\n'
..'[d/8^G,3/8] ^g/4 [b/4F/4F,/4] [b3/8^G,3/8] [=D,/4z/8] ^A,/8\n'
..'[F/8^A,3/8] ^G/4 [^A/8D,/4] F/8 [^G/8^A,3/8] ^A/4 [f/8D,/4] ^G/8\n'
..'[^A/4^A,3/8] f/8 [^g/8D,/4] ^A/8 [f/4^A,3/8] ^g/8 [^a/8D,/4] f/8\n'
..'[^g/4^A,3/8] ^a/8 [f/8D,/4] ^g/8 [^a/4^A,3/8] f/8 [^g/8D,/4] f/8\n'
..'[^a/4^A,3/8] ^g/8 [f/8D,3/8] ^a/4 [^g/8^A,/4] f/8 [^f5/8^D,/8] ^A,/4\n'
..'^F,/8 ^A,/8 [^a5/4^D,/8] ^A,/4 ^F,/8 ^A,/8 ^D,/8 ^A,/4 ^F,/8 ^A,/8\n'
..'[^f/2^D,/8] ^A,/4 ^F,/8 [^d/8^A,/8] [=d/8=F,/4] ^d/8 [^A,/8=f/8]\n'
..'[^d/4^G,/8] ^A,/8 [=dF,/4] ^A,/8 ^G,/8 ^A,/8 F,/4 ^A,/8 [d/4^G,/8]\n'
..'^A,/8 [^a/2F,/4] ^A,/8 ^G,/8 [d/8^A,/8] [f3/4^F,/4] ^A,/8 ^F,/8 ^A,/4\n'
..'[^d7/8^F,/8] ^A,/8 ^F,/8 ^A,/4 ^F,/8 ^A,/8 [^d3/8^F,/8] ^A,/4\n'
..'[^a3/8^F,/8] ^A,/8 ^F,/8 [^d/4^A,/4] [^f5/8=D,/8] ^A,/8 D,/8 ^A,/4\n'
..'[=f7/8D,/8] ^A,/8 D,/4 ^A,/8 D,/8 ^A,/8 [f3/8D,/4] ^A,/8 [^a/2D,/8]\n'
..'^A,/8 D,/4 [f/8^A,/8] [^f/4^D,/8] ^A,/8 [^a5/8^F,/4] ^A,/8 ^D,/8\n'
..'^A,/8 [^a3/4^F,/4] ^A,/8 ^D,/8 ^A,/4 [^a/4^F,/8] ^A,/8 [^f3/8^D,/8]\n'
..'^A,/4 [^d/4^F,/8] ^A,/8 [^d3/8=F,/8] ^A,/4 [=d5/8^G,/8] ^A,/8 F,/8\n'
..'^A,/4 [d5/8^G,/8] ^A,/8 F,/8 ^A,/4 [d/4^G,/8] ^A,/8 [^a3/8F,/4] ^A,/8\n'
..'[d/4^G,/8] ^A,/8 [=f3/8^F,/4] ^A,/8 [^d5/8^F,/8] ^A,/8 ^F,/4 ^A,/8\n'
..'[^d5/8^F,/8] ^A,/8 ^F,/4 ^A,/8 [^d/4^F,/8] ^A,/8 [^a3/8^F,/4] ^A,/8\n'
..'[^d3/8^F,/8] ^A,/4 [^f/4=D,/8] ^A,/8 [=f5/8D,/8] ^A,/4 D,/8 ^A,/8\n'
..'[f5/8D,/8] ^A,/4 D,/8 ^A,/8 [f3/8D,/8] ^A,/4 [^a/4D,/8] ^A,/8\n'
..'[f3/8D,/8] ^A,/4 [=g5/4^C,/8] ^A,/8 ^D,/4 ^A,/8 ^C,/8 ^A,/8 ^D,/4\n'
..'^A,/8 [^g5/4B,/8] ^A,/8 ^D,/4 ^A,/8 B,/8 ^A,/8 ^D,/4 ^A,/8 [f/4B,/8]\n'
..'[^d/8^A,/8] [f9/4^C,/4] [^d/8^A,/8] [^f15/8^A,/8] ^A,/4 ^C,/8 ^A,/8\n'
..'^A,/8 ^A,/4 ^C,/8 ^A,/8 ^A,/8 ^A,/4 ^C,/8 ^A,/8 [^d5/4=A,/8] ^F,/4\n'
..'B,/8 ^F,/8 A,/8 ^F,/4 B,/8 ^F,/8 [e5/4^G,/4] ^F,/8 B,/8 ^F,/8 ^G,/4\n'
..'^F,/8 B,/8 ^F,/8 [=d3/8^G,/4] [c\'/8=F,/8] [d9/4^A,/8] [c\'/8F,/8]\n'
..'[^d2^F,/4] =F,/8 ^A,/8 F,/8 ^F,/4 =F,/8 ^A,/8 F,/4 ^F,/8 =F,/8 ^A,/8\n'
..'F,/4 [e11/8b11/8^g11/8B,15/8^G,15/8E,15/8] \n'
ABCtune ='X:1\n'
..'T:Still Alive\n'
..'C:Jonathan Coulton\n'
..'N:Arranged by Meldowen\n'
..'Q:1/4=115\n'
..'M:4/4\n'
..'L:1/8\n'
..'K:D\n'
..'z4 GF EE |[AF4] d fd Bd fd |Ad f[Dd] [BG][dF] [fE][Ed]|\n'
..'A[dF] fd [BD]d [Ef][A,-d] |[AA,2] d fd Bd f[dA,] |\n'
..'[EB][Fe] g[Ge] B[Ee] g[Ce] |A[Dc] g[cE] Ac [gA,][A,c] |\n'
..'A [F4d] fd Bd fd |Ad fd [GB][dF] [Ef][dE] |\n'
..'[AF]d fd Bd fd |Ad f[dD] [GB][Fd] [Ef][dE] |\n'
..'A[Fd] fd [BD]d [Ef][A,d] |Ad fd Bd fd |\n'
..'[BE][eF] g[Ge] B[Ee] g[eC] |A[cD] g[cE] A[cA,] [gC][Ec] |\n'
..'K:F\n'
..'[BF][cE] [eD] [C3a3] A,B, |\n'
..'[Ccfa]c [cFfc\']c [Eceg][Dc] [Dcec\'][Cc] |\n'
..'[dBDb][aC] [CdBg][ce] [Cfac]c [A,cf][B,c] |\n'
..'[Cfca]c [Ffcc\']c [Ggec][Fc] [Ecc\'e][Cc] |\n'
..'[BDdb][aE] [FBdg][ce] [Ffac]c [Gfc][Ac] |\n'
..'[dB][gBb] [ABda]g [Gce][gf] [ec2Fg][c\'gG] |\n'
..'[cAf][Aac\'] [Gcf][ac\'] [dFf][ca] [Dd2g2f][Ca] |\n'
..'[BDd][gF] [FBd][gE] [^cA][Eg] [^FcA2] [Fg] |\n'
..'K:D\n'
..'[DA]d f[Dd] [BB,2] d f[dB,] |[AD]d f[dD] [BB,2] d f[B,d]|\n'
..'[AD]d f[Dd] [BB,2] d f[B,d] |\n'
..'[AD]d f[DA,d] [GBB,2] [dF] [fE][B,Ed] |\n'
..'[DAF4] d f[Dd] [BB,2] d f[B,d] |\n'
..'[DA]d f[Dd] [GBB,2] [Fd] [Ef][B,Ed] |\n'
..'[DA][Fd] f[Dd] [DBB,2] d [Ef][A,B,d] |\n'
..'[DA]d f[Dd] [BB,2] d f[B,d] |\n'
..'[EB]e [Fg][EGe] [EB][Fe] [gE2G2] e |\n'
..'[A,CA]c [Dg][A,Ec] [A,A][B,c] [A,gC2] [A,c] |\n'
..'[DA] [dF4] f[Dd] [BB,2] d f[B,d] |\n'
..'[DA]d f[A,Dd] [GBB,2] [FAd] [EGf][B,EGd] |\n'
..'[DFA]d f[Dd] [BB,2] d f[B,d] |\n'
..'[DA]d f[A,Dd] [GBB,2] [FAd] [EGf][B,EGd] |\n'
..'[DA]d [FAf][DFd] [BB,2] d [EGf][A,B,Dd] |\n'
..'[DA]d f[Dd] [BB,2] d f[B,d] |\n'
..'[EB]e [Fg][EGe] [EB][Fe] [gE2G2] e |\n'
..'[A,CA]c [Dg][A,Ec] [A,A][A,B,c] [CDg][A,Ec] |\n'
..'K:F\n'
..'[B,FB][Ec] [B,De][B,Ca] B,B, [A,B,]B, |\n'
..'[CFAcf][CF] [F2c2f2] [G,CEBce][G,CD] [DBce][CA] |\n'
..'[F,B,DBd][F,B,CA] [CABd]e [CFAcf][CF] [A,Fc2f2] [B,G] |\n'
..'[CFAcf][CF] [F2c2f2] [G,CGBce][G,CF] [EBce][DA] |\n'
..'[F,B,DBd][F,B,EA] [FABd]e [CFAcf][CF] [G/A/c/f2] B/[c/A]d/ |\n'
..'[F,B,Bd][F,B,Bg] [F,B,ABcd][F,B,g] [G,CGBce][G,Cg] [G,CFBec2] [G,CGAg] |\n'
..'[CFAcf][CFAa] [=B,EGBcf][B,EFa] [A,DFAdf][A,Da] [G,CDAfd2] [G,CFa] |\n'
..'[B,DFBd][FAg] [FABd][EGg] [A,A^c][EGg] [^FAcE2] [FAg] |\n'
..'K:D\n'
..'[DA]d f[Dd] [BB,2] d f[B,d] |[DA]d f[Dd] [BB,2] d f[B,d]|\n'
..'[DA]d f[Dd] [BB,2] d f[B,d] |\n'
..'[DA]d f[Dd] [GBB,2] [Fd] [Ef][Ed] |\n'
..'A[Fd] fd Bd fd |Ad f[A,d] [GB][Fd] [Ef][Ed] |\n'
..'Ad [Ff][Dd] Bd [Ef][A,d] |Ad fd Bd fd |\n'
..'[EB]e [Fg][Ge] Be [gE2] e |[CA]c [Dg][Ec] Ac [A,g][A,c] |\n'
..'A [dF4] fd Bd fd |Ad fd [GB][FAd] [EGf][EGd] |\n'
..'[DA][FAd] f[Dd] [BB,2] d f[B,d] |\n'
..'[DA]d f[Dd] [GBB,2] [FAd] [EGf][B,EGd] |\n'
..'[DA]d [FAf][DFd] [BB,2] d [EGf][A,B,Dd] |\n'
..'[DA]d f[Dd] [BB,2] d f[B,d] |\n'
..'[EB]e [Fg][EGe] [EB][Fe] [gE2G2] e |\n'
..'[A,CA]c [Dg][A,Ec] [A,A][A,B,c] [CDg][A,Ec] |\n'
..'K:F\n'
..'[B,FB][Ec] [B,De][B,Ca] B,B, [A,B,]B, |\n'
..'[CFAcf][CF] [F2c2f2] [G,CEBce][G,CD] [DBce][CA] |\n'
..'[F,B,DBd][F,B,CA] [CABd]e [CFAcf][CF] [A,Fc2f2] [B,G] |\n'
..'[CFAcf][CF] [F2c2f2] [G,CGBce][G,CF] [EBce][DA] |\n'
..'[F,B,DBd][F,B,EA] [FABd]e [CFAcf][CF] [G/A/c/f2] B/[c/A]d/ |\n'
..'[F,B,Bd][F,B,Bg] [F,B,ABcd][F,B,g] [G,CGBce][G,Cg] [G,CFBec2] [G,CGAg] |\n'
..'[CFAcf][CFAa] [=B,EGBcf][B,EFa] [A,DFAdf][A,Da] [G,CDAfd2] [G,CFa] |\n'
..'[B,DFBd][FAg] [FABd][EGg] [A,A^c][EGg] [^FAcE2] [AgF] |\n'
..'K:D\n'
..'[DAF2] d f[Dd] [BB,2] d [Af][B,Ad] |\n'
..'[DAB][Ad] [Ff][Dd] [BB,2] [Ed] [Ff][B,AdF-] |\n'
..'[DAF2] d f[Dd] [BB,2] [Ad] [Af][B,Ad] |\n'
..'[DAB][Ad] [Ff][Dd] [BB,2] [EGd] [FAf][B,AdF-] |\n'
..'[DAF2] d f[Dd] [BB,2] [Ad] [Af][B,Ad] |\n'
..'[DAB][Ad] [Ff][Dd] [BB,2] [EGd] [FAf][B,AdF-] |\n'
..'[DAF2] d f[Dd] [BB,2] d [Af][B,Ad] |\n'
..'[DAB][Ad] [Ff][Dd] [BB,2] [EGd] [FAf][B,AdF-] |\n'
..'[DAF2] d f[Dd] [BB,2] [Ad] [Af][B,Ad] |\n'
..'[DAB][Ad] [Ff][Dd] [BB,2] [EGd] [FAf][B,AdF-] |\n'
..'[DAF2] d f[Dd] [BB,2] [Gd] [Af][B,Ad] |\n'
..'[DA]d f[Dd] [B,B][Gd] [Ff][dF-] |F4 ||\n'
BCtune = 'X: 1\n'
..'T: Flight Of The Bumblebee, The\n'
..'M: 4/4\n'
..'Q: 280\n'
..'L: 1/8\n'
..'R: reel\n'
..'K: Cmaj\n'
..'f f f f f | e _e d _d c ^c d ^d | e _e d _d c f e ^d |\n'
..'e _e d _d c ^c d ^d |e _e d _d c ^c d ^d |e _e d ^c d ^c c B |\n'
..'c ^c d ^d e f e ^d |e _e d ^c d ^c c B | c ^c d ^d e ^f g ^g|\n'
..'a _a g ^f f _b a ^g | a _a g ^f f ^f g ^g |a _a g ^f f _b a ^g |\n'
..'a _a g ^f f _b a ^g | a _a g ^f f ^f g ^g | a _a g ^f g ^f f e|\n'
..'f ^f g ^g a _b a ^g | a _a g ^f g ^f f e | f ^f g ^g a _b a ^g |\n'
..'e _e D _D C f e ^D |e _e D _D C ^C D ^D | e _e D _D C ^C D ^D |\n'
..'e _e D ^C D ^C C B | C ^C D ^D e f e ^D |e _e D ^C D ^C C B |\n'
..'C ^C D ^D e ^f g ^g | a _a g ^f f _b a ^g | a _a g ^f f ^f g ^g |\n'
..'a _a g ^f f _b a ^g | a _a g ^f f _b a ^g | a _a g ^f f ^f g ^g | a _a g ^f g ^f f e |\n'
..'f ^f g ^g a _b a ^g | a _a g ^f g ^f f e | f ^f g ^g a _b a ^g | a a _b a a _b |\n'
..'a _b a ^G a _b a ^G | a _b a ^G a _b a ^G |a ^a b c _d c b _b | a ^a b c _d c b _b|\n'
..'a d _e a d _e | d _e d ^c d _e d ^c | d _e d ^c d _e d ^c |d ^d e f ^f e _e |\n'
..'d ^d e f ^f e _e | d ^c c b _b _e d ^c | d ^c c b ^a b c ^c |d ^c c b c b _b a |\n'
..'e f e ^d e f e ^d | z e z c z | a z F z a z c z |e e z c z | a z F z a z c z |\n'
BCtune = 'X:1\n'
..'T:Fawlty Towers by Skjald\n'
..'C:Dennis Wilson\n'
..'L:1/4\n'
..'Q:1/4=60\n'
..'K:C\n'
..'[e3/8c3/8] z/8 [f3/8d3/8] [g/2e/2C,/2] [^f/2^d/2G,/2]\n'
..'[g/2e/2E/4C/4] z/4 [^f/2^d/2] [g/2e/2E/4C/4] z/4 c\'/2\n'
..'[a11/8=f11/8F,/2] C/2 [A/4F/4] z/4 [g3/8e3/8] [f/2=d/2A/4F/4] z/4\n'
..'[e/2c/2] [f/2d/2G,/2] [e/2^c/2D/2] [f/2d/2A/4G/4] z/4 [e/2^c/2]\n'
..'[f/2d/2G/4F/4] z/4 [b/2g/2] [g11/8e11/8B/4E,3/8] =c/8 z/8 [B/8B,3/8]\n'
..'z/8 A/8 [BE/4] z/4 [f/2d/2] [e/2c/2] [d/2B/2] [c/2A/2E/2A,3/4]\n'
..'[B/2^G/2^D/2] [c/2A/2E/2A,3/4] [B/2^G/2^D/2] [c/2A/2E/2A,5/8]\n'
..'[g3/8e3/8^C3/8] [f/2d/2=D/2D,/2] [e/2^c/2^C/2^C,/2] [f/2d/2D/2D,/2]\n'
..'[e/2^c/2E/2E,/2] [d/2B/2F/2F,/2] [=c/2A/2^F/2^F,/2] [B/2=G17/8G,]\n'
..'[c/2A/2] [A/2^F9/8D,9/8] z/8 B/2 [G9/8G,9/8] [f/2d/2G,] [g/2e/2]\n'
..'[e5/8c5/8G,5/4] [f5/8d5/8] [d3/4B3/4G,5/4] [e/4c/4] [f/4d/4]\n'
..'[g/2e/2=C,/2] [^f/2^d/2G,/2] [g/2e/2G/4=C/4] z/4 [^f3/8^d3/8]\n'
..'[g/2e/2G/4C/4] z/4 c\'/2 [a3/2=f3/2=F,/2] C/2 [A/4=F/4] z/4 [g/2e/2]\n'
..'[f/2=d/2A/4F/4] z/4 [e/2c/2] [f/2d/2G,/2] [e3/8^c3/8D3/8] z/8\n'
..'[f3/8d3/8A/8G/8] z/4 [e/2^c/2] [f/2d/2G/4F/4] z/4 [b/2g/2]\n'
..'[g3/2e3/2B/4E,/2] =c/4 [B/4B,/2] ^A/4 [B5/4E/4] z/4 [f/2d/2] [e/2c/2]\n'
..'[d3/8B3/8] z/8 [c3/8=A3/8E3/8A,5/8] [B/2^G/2^D/2] [c/2A/2E/2A,3/4]\n'
..'[B/2^G/2^D/2] [c/2A/2E/2A,] [g/2e/2^C/2] [f/2d/2=D/2D,/2]\n'
..'[e/2^c/2^C/2^C,/2] [f/2d/2D/2D,/2] [e/2^c/2E/2E,/2]\n'
..'[d3/8B3/8F3/8F,3/8] [=c/2A/2^F/2^F,/2] [B/2=G17/8G,] [c/2A/2] z/8\n'
..'[A/2^FD,] B/2 [G9/8G,9/8] [f/2d/2G,9/8] [g5/8e5/8] [e/2c/2G,9/8]\n'
..'[f5/8d5/8] [d3/4B3/4G,5/4] [e/4c/4] [f/4d/4] [g/2e/2=C,/2]\n'
..'[^f/2^d/2G,/2] [g/2e/2E/4=C/4] z/4 [^f/2^d/2] [g3/8e3/8E/4C/4] z/4\n'
..'c\'3/8 [a3/2=f3/2=F,/2] C/2 [A/4=F/4] z/4 [g/2e/2] [f/2=d/2A/4F/4] z/4\n'
..'[e/2c/2] [f/2d/2G,/2] [e/2^c/2D/2] [f/2d/2A/4G/4] z/4 [e3/8^c3/8]\n'
..'[f/2d/2G/4F/4] z/4 [b/2g/2] [g3/2e3/2B/4E,/2] =c/4 [B/4B,/2] ^A/4\n'
..'[B5/4E/4] z/4 [f/2d/2] [e/2c/2] [d/2B/2] [^c/2=A/2E/2A,5/8]\n'
..'[=c3/8^D3/8] [^c/2A/2E/2A,3/4] [=c/2^D/2] [^c/2A/2E/2A,]\n'
..'[g/2^c/2^C/2] [f/2d/2=D7/4D,/2] [e/2^c/2^C,/2] [f/2d/2D,/2]\n'
..'[c\'/2a/2E,/2] [b/2g/2^D7/8F,/2] [a3/8f3/8^F,3/8] z/8\n'
..'[g3/8e3/8E3/8G,15/8] [^f/2^d/2^D/2] [g/2e/2E/2] [e/2=c/2=C/2]\n'
..'[=f/2=d/2=D3/4G,] [d/2B/2] [g/4e/4E/4G,15/8] [^f/4^d/4^D/4]\n'
..'[g/4e/4E/4] [^f/4^d/4^D/4] [g/2e/2E/2] [c\'3/8g3/8] z/8\n'
..'[g3/8e3/8E3/8G,7/8] [e/2c/2] [=f/4=d/4=D/4G,2] [e/4^c/4^C/4]\n'
..'[f/4d/4D/4] [e/4^c/4^C/4] [f/2d/2D/2] [b/2g/2] [f/2d/2D/2G,] [d/2B/2]\n'
..'[g/4e/4E/4G,15/8] [^f/4^d/4^D/4] [g/4e/4E/4] [^f/4^d/4^D/4]\n'
..'[g3/8e3/8E3/8] [c\'/2g/2] [g/2e/2E/2G,] [e/2=c/2] [=f/4=d/4=D/4G,2]\n'
..'[e/4^c/4^C/4] [f/4d/4D/4] [e/4^c/4^C/4] [f/2d/2D/2] [b/2g/2]\n'
..'[f/2d/2D/4G,] z/4 [d/2B/2] [=c/4E/4=C/4=C,67/8] [B/4D/4B,/4]\n'
..'[c3/8E3/8C3/8] [B/4D/4B,/4] [c5/8E5/8C5/8] [e5/8G5/8E5/8]\n'
..'[c5/8E5/8C5/8] z/8 [e5/8G5/8E5/8] [c37/8E37/8C37/8]'
BCtune='X:1\n'
..'T:Toccata and Fugue in D min \n'
..'C:Bach\n'
..'Z:celestial\n'
..'I:flute but any wind would do\n'
..'Q:1/4=115\n'
..'M:4/4\n'
..'L:1/8\n'
..'K:F\n'
..'A/2G/2A6 z G/2 F/2 E/2 D/2 ^C3/2 D4 z z2 A,/2G,/2A,6 z E,3/2 F,3/2 ^C,3/2 D,4 z z2 |A,/2G,/2A,6 z G,/2 F,/2 E,/2 D,/2 ^C,3/2 D,4 z z2 D,4 ^C,4 E,4 G,4 B,4 ^C,4 D,4 |E,4 D,4 z3 z/2 ^C,/2 |D,/2 E,/2 ^C,/2 D,/2 E,/2 ^C,/2 D,/2 E,/2 ^C,/2 D,/2 E,/2 F,/2 G,/2 E,/2 F,/2 G,/2 E,/2 F,/2 G,/2 E,/2 F,/2 G,/2 |A,/2 B,/2 G,/2 A,/2 B,/2 G,/2 A,/2 B,/2 G,/2 A,/2 z5 ^C/2 |D/2 E/2 ^C/2 D/2 E/2 ^C/2 D/2 E/2 ^C/2 D/2 E/2 F/2 G/2 E/2 F/2 G/2 E/2 F/2 G/2 E/2 F/2 G/2 |A/2 B/2 G/2 A/2 B/2 G/2 A/2 B/2\n'
..'G/2 A/2 z5 A/2 |G/2 B/2 E/2 G/2 B/2 E/2 F/2 A/2 D/2 F/2 A/2 D/2 E/2 G/2 C/2 E/2 G/2 C/2 D/2 F/2 B,/2 D/2 F/2 B,/2 |C/2 E/2 A,/2 C/2 E/2 A,/2 B,/2 D/2 G,/2 B,/2 D/2 B,/2 A,/2 C/2 F,/2 A,/2 C/2 F,/2 G,/2 B,/2 E,/2 G,/2 B,/2 E,/2 |F,/2 A,/2 D,/2 F,/2 A,/2 D,/2 E,/2 G,/2 ^C,/2 E,/2 G,/2 ^C,/2 z2 B,4-B,/3 |A,/3 G,/3 F,/3 E,/3 D,/3 ^C,/3 =B,/3 ^C,/2 A,/2 ^C,/2 E,/3 G,/3 F,G,/2F,/2 E,/2 |\n'
..'F,6 z z/2 A,/2 D/2 E/2 F/2 D/2 E/2 F/2 G/2 E/2 |F/2 G/2 A/2 F/2 G/2 A/2 B/2 G/2 A/2 F/2 G/2 E/2 F/2 D/2 E/2 ^C/2 |D/2 A,/2 B,/2 G,/2 A,/2 F,/2 G,/2 E,/2 F,/2 D,/2 G,/2 E,/2 F,/2 D,/2 E,/2 ^C,/2 |C/2 A,/2 B,/2 G,/2 A,/2 F,/2 G,/2 E,/2 F,/2 D,/2 G,/2 E,/2 F,/2 D,/2 E,/2 ^C,/2 |D, D/3 F/3 B/3 F/3 C/3 E/3 A/3 E/3 B,/3 D/3 G/3 D/3 A,/3 ^C/3 E/3 A/3 D/2 B/2 A,/2 A/2 B,/2 G/2 |A D/3 F/3 B/3\n'
..'F/3 C/3 E/3 A/3 E/3 B,/3 D/3 G/3 D/3 A,/3 ^C/3 E/3 A/3 D/2 B/2 A,/2 A/2 B,/2 G/2 |A2-A/3 G/3 F/3 E/3 D/3 ^C/3 =B,/3 ^C/3 A,/3 =B,/3 ^C/3 D/3 E/3 F/3 G/3 A/3 G/3 F/3 E/3 F/3 D/3 F/3 A/3 ^c/3 |d/3 A/3 =B/3 ^c/3 d/3 e/3 f/4 g/4 a/3 b d/2 b/2 A/2 a/2 B/2 g/2 a/2 d/3 f/3 b/3 f/3 |c/3 e/3 a/3 e/3 B/3 d/3 g/3 d/3 A/3 ^c/3 e/3 a/3 d/2 b/2 A/2 a/2 B/2 g/2 a =B |^c-^c/2 =B/2 A/2 ^c/2 e/3 g/3 b/2 a/3 g/3 f/3 e/3 f/3 e/3 d/3 ^c/3 d/3 ^c/3 B/3 A/3 G/3 F/3 E/3 D/3 |E4 ^C/2 E/2 ^C/2 B,/2 ^C/2 B,/2 ^C/2 E/2 ^C/2 B,/2 ^C/2 B,/2 |\n'
..'^C/2 E/2 ^C/2 B,/2 ^C/2 B,/2 ^C/2 E/2 ^C/2 B,/2 ^C/2 B,/2 G,/2 B,/2 B,/2 E,/2 G,/2 E,/2 G,/2 B,/2 G,/2 E,/2 G,/2 E,/2 |G,/2 B,/2 G,/2 E,/2 G,/2 E,/2 G,/2 B,/2 G,/2 E,/2 G,/2 E,/2 ^C,/2 E,/2 ^C,/2 ^C,/2 E,/2 ^C,/2 ^C,/2 E,/2 ^C,/2 ^C,/2 E,/2 ^C,/2 |^C,/2 E,/2 ^C,/2 ^C,/2 E,/2 ^C,/2 ^C,/2 E,/2 ^C,/2 ^C,/2 E,/2 ^C,/2 ^C,/2 E,/2 ^C,/2 E,/2 G,/2 E,/2 ^C,/2 E,/2 ^C,/2 E,/2 G,/2 E,/2 |^C,/2 E,/2 ^C,/2 E,/2 G,/2 E,/2 ^C,/2 E,/2 ^C,/2 E,/2 G,/2 E,/2 G,/2 B,/2 G,/2 B,/2 G,/2 B,/2 G,/2 B,/2 G,/2 B,/2 G,/2 B,/2 |^C/2 B,/2 ^C/2 E/2 ^C/2 E/2 ^C/2 E/2 ^C/2 E/2 ^C/2 E/2 A2 A2 |B3 A/2 G/2 A-A/2 E/2 F/2 D/2 E/2 ^C/2 |D/2 =B,/2 ^C/2 A,/2 _B,/2 ^G,/2 A,/2 G/2 F D A2 |G F/2 E/2 F2 z/2 A/2 G/2 A/2 F/2 A/2 E/2 A/2 |D/2 A/2 ^C/2 A/2 D/2 A/2 E/2 A/2 F/2 A/2 A,/2 A/2 =B,/2 A/2 ^C/2 A/2 |D,/2 A,/2 ^C,/2 A,/2 D,/2 A,/2 E,/2 A,/2 z/2 D/2 ^C/2 D/2 B,/2 D/2 A,/2 D/2 |G,/2 D/2 ^F,/2 D/2 G,/2 D/2 A,/2 D/2 B,/2 D/2 D,/2 D/2 E,/2 D/2 ^F,/2 D/2 |G,/2 D/2 ^F,/2 D/2 G,/2 D/2 A,/2 D/2 B, D B, D |_E G, _E G, C A, C A, |D F, D F, B, G, B, G, |^C E, ^C E, A, F, A, F, |\n'
..'G, ^C, G, ^C, F, D, F, D, |D, B, D, B, z/2 A/2 G/2 A/2 F/2 A/2 E/2 A/2 |D/2 A/2 ^C/2 A/2 D/2 A/2 E/2 A/2 F/2 A/2 A,/2 A/2 =B,/2 A/2 ^C/2 A/2 |D/2 A/2 ^C/2 A/2 D/2 A/2 E/2 A/2 F/2 A/2 E/2 A/2 D/2 A/2 C/2 A/2 |B,/2 A/2 C/2 A/2 E/2 G/2 B,/2 G/2 E/2 G/2 D/2 G/2 C/2 G/2 B,/2 G/2 |A,/2 G/2 B,/2 G/2 C/2 F/2 A,/2 F/2 D/2 F/2 C/2 F/2 B,/2 F/2 A,/2 F/2 |G,/2 F/2 A,/2 F/2 B,/2 E/2 G,/2 E/2 ^C/2 E/2 B,/2 E/2 A,/2 E/2 G,/2 E/2 |F,/2 E/2 G,/2 E/2 A,/2 D/2 F,/2 D/2 E,/2 E/2 E,/2 E/2 F,/2 D/2 F,/2 D/2 |B,/2 ^C/2 B,/2 ^C/2 A,/2 D/2 F,/2 D/2 E,/2 E/2 E,/2 E/2 F,/2 D/2 F,/2 D/2 |z/2 D/2 ^C/2 D/2 =B,/2 D/2 ^C/2 =B,/2 z/2 A,/2 G,/2 A,/2 E,/2 G,/2 F,/2 E,/2 |F,/2 D/2 ^C/2 D/2 F/2 D/2 ^C/2 =B,/2 ^C/2 A,/2 G,/2 A,/2 E/2 G,/2 F,/2 E,/2 |z/2 d/2 ^c/2 d/2 A/2 A/2 G/2 A/2 ^F/2 d/2 ^c/2 d/2 G/2 f/2 _e/2 d/2 |^c/2 e/2 A/2 ^c/2 D/2 _e/2 d/2 =c/2 c/2 d/2 G/2 B/2 C/2 d/2 c/2 _B/2 |A/2 c/2 ^F/2 A/2 D/2 c/2 B/2 A/2 B,/2 A/2 G/2 ^F/2 G/2 B,/2 A,/2 G,/2 |D,2 D C B, A, B, ^F, |G, ^F, G, A, B, A, B, ^F, |D/2 G/2 F/2 G/2 E/2 F/2 D/2 E/2 C/2 A/2 G/2 A/2 F/2 G/2 E/2 F/2 |D/2 B/2 A/2 B/2 G/2 A/2 F/2 G/2 E/2 c/2 B/2 c/2 A/2 B/2 G/2 A/2 |\n'
..'F/2 _E/2 D/2 C/2 D/2 C/2 B,/2 A,/2 B,/2 D/2 B,/2 A,/2 G,/2 B,/2 G,/2 F,/2 |E,/2 F,/2 G,/2 A,/2 B,/2 D/2 C/2 B,/2 A,2 C B, |A, G, A, B, C E, F, G, |A, G, A, B, C/2 B,/2 A,/2 G,/2 F,/2 _E,/2 D,/2 C,/2 |D/2 C/2 B,/2 A,/2 G,/2 F,/2 E,/2 D,/2 C,/2 |F/2 E/2 D/2 C/2 B,/2 A,/2 G,/2 F,/2 G/2 F/2 E/2 D/2 C/2 B,/2 A,/2 G,/2 |A/2 F/2 E/2 F/2 C/2 F/2 E/2 F/2 A/2 F/2 E/2 F/2 C/2 F/2 E/2 F/2 |G/2 E/2 D/2 E/2 C/2 E/2 D/2 E/2 G/2 E/2 D/2 E/2 C/2 E/2 D/2 E/2 |A/2 F/2 E/2 F/2 C/2 F/2 E/2 F/2 A/2 F/2 E/2 F/2 C/2 F/2 E/2 F/2 |G/2 E/2 D/2 E/2 C/2 E/2 D/2 E/2 G/2 E/2 D/2 E/2 C/2 E/2 D/2 E/2 |F/2 G/2 F/2 E/2 D/2 C/2 =B,/2 A,/2 =B,/2 G,/2 =B,/2 D/2 F/2 A/2 F/2 D/2 |=B,/2 G,/2 =B,/2 D/2 F/2 A/2 F/2 D/2 _B,/2 G,/2 _B,/2 C/2 E/2 G/2 E/2 C/2 |B,/2 G,/2 B,/2 C/2 E/2 G/2 E/2 C/2 A,/2 F,/2 A,/2 C/2 D/2 F/2 D/2 B,/2 |A,/2 F,/2 A,/2 C/2 D/2 F/2 D/2 B,/2 G,/2 E,/2 G,/2 B,/2 ^C/2 E/2 ^C/2 B,/2 |G,/2 E,/2 G,/2 B,/2 ^C/2 E/2 ^C/2 B,/2 z/2 A/2 G/2 A/2 F/2 A/2 E/2 A/2 |D/2 A/2 ^C/2 A/2 D/2 A/2 E/2 A/2 F/2 A/2 A,/2 A/2 =B,/2 A/2 ^C/2 A/2 |D/2 A/2 ^C/2 A/2 D E D =C B, A, |B/2 A/2 G/2 F/2 E/2 D/2 ^C/2 =B,/2 ^C/2 A,/2 ^C/2 E/2 G/2 _B/2 G/2 E/2 |^C/2 A,/2 ^C/2 E/2 G/2 B/2 G/2 E/2 D/2 A,/2 D/2 F/2 A/2 d/2 A/2 F/2 |\n'
..'D/2 A,/2 D/2 F/2 A/2 d/2 A/2 F/2 ^C/2 A,/2 ^C/2 E/2 G/2 B/2 G/2 E/2 |^C/2 A,/2 ^C/2 E/2 G/2 B/2 G/2 E/2 D/2 A,/2 D/2 F/2 A/2 d/2 A/2 F/2 |D/2 A,/2 D/2 F/2 A/2 d/2 A/2 F/2 E/2 ^C/2 E/2 G/2 B/2 ^c/2 B/2 G/2 |E/2 ^C/2 E/2 G/2 B/2 ^c/2 B/2 G/2 F/2 D/2 F/2 A/2 d/2 f/2 d/2 A/2 |F/2 D/2 F/2 A/2 d/2 f/2 d/2 A/2 E/2 ^C/2 E/2 G/2 B/2 ^c/2 B/2 G/2 |E/2 ^C/2 E/2 G/2 B/2 ^c/2 B/2 G/2 F/2 D/2 F/2 A/2 d/2 f/2 d/2 A/2 |F/2 D/2 F/2 A/2 d/2 f/2 d/2 A/2 G/2 E/2 G/2 B/2 ^c/2 e/2 ^c/2 B/2 |G/2 E/2 G/2 B/2 ^c/2 e/2 ^c/2 B/2 A/2 F/2 A/2 ^c/2 d/2 f/2 d/2 A/2 |B/2 d/2 B/2 G/2 F/2 A/2 F/2 D/2 A,/2 D/2 A,/2 F,/2 D,/2 D/2 ^C/2 =B,/2 |^C/2 B/2 A/2 G/2 F/2 G/2 F/2 E/2 D/2 B/2 A/2 G/2 F/2 G/2 F/2 E/2 |D/2 E/3 F/3 G/3 A/3 =B/3 ^c/3 d/2 f/2 e/2 d/2 A,/2 =B,/3 ^C/3 D/3 E/3 F/3 G/3 z/2 E/2 D/2 ^C/2 |D/2 _E/3 D/3 C/3 B,/3 A,/3 G,/3 ^F, A,2 G, C =B, |_E D _E =B, C =B, C D |_E D _E F G,/2 G,/2 F,/2 G,/2 _E,/2 G,/2 D,/2 G,/2 |C/2 G/2 =B,/2 G,/2 C/2 G/2 D/2 G/2 _E/2 G/2 G,/2 G/2 A,/2 G/2 =B,/2 G/2 |C/2 G/2 =B,/2 G/2 C/2 G/2 D/2 G/2 G/2 G/2 F/2 G/2 _E/2 F/2 D/2 _E/2 |C/2 F/2 _E/2 F/2 D/2 _E/2 C/2 D/2 B,/2 _E/2 D/2 _E/2 C/2 D/2 B,/2 C/2 |\n'
..'A,/2 D/2 C/2 D/2 B,/2 C/2 A,/2 B,/2 G,/2 B,/2 A,/2 B,/2 C/2 B,/2 A,/2 G,/2 |^F, A, D/2 G,/2 C/2 ^F,/2 B,/2 G,/2 D/2 A,/2 B,/2 G,/2 A,/2 ^F,/2 |G,/2 D/2 ^F,/2 D/2 G,/2 D/2 A,/2 D/2 B,/2 G,/2 D/2 A,/2 B,/2 G,/2 A/2 A,/2 |D/2 C/2 B,/2 A,/2 B,/2 A,/2 B,/2 G,/2 A,/2 B,/2 C/2 D/2 _E/2 D/2 C/2 D/2 |B,/2 C/2 A,/2 B,/2 G, =B, C/2 _E/2 F/2 G/2 _A/2 G/2 F/2 G/2 |_E/2 F/2 D/2 _E/2 C B, A, B,2 A,2 |G,2 ^F, F, _E,2 D,/2 B,/2 |A,/2 B,/2 A,/2 G,/2 ^F,/2 _E/2 D/2 C/2 B,/2 A/2 G/2 ^F/2 G-G/2 =F/2 |_E/2 F/2 D/2 _E/2 ^C/2 B,/2 A,/2 G,/2 D/2 _E/2 D/2 =C/2 D/2 C/2 B/2 A/2 |G,/2 F,/2 _E,/2 D/2 A, ^C D =E A,/2 G,/2 A,/2 F,/2 |G,/2 A,/2 G,/2 A,/2 B,/2 A,/2 G,/2 A,/2 A,/2 B,/2 G,/2 A,/2 F, A, |G D ^C D E D ^C D |E D ^C D E G F D |B, E D D E,/2 A,/2 G,/2 A,/2 F,/2 A,/2 E,/2 A,/2 |D,/2 A,/2 ^C,/2 A,/2 D,/2 A,/2 E,/2 A,/2 F,/2 A,/2 A,/2 A,/2 =B,/2 A,/2 ^C,/2 A,/2 |D,/2 A,/2 ^C,/2 A,/2 D,/2 A,/2 E,/2 A,/2 A/2 B/2 G/2 A/2 F/2 G/2 E/2 F/2 |D/2 A,/2 ^C/2 A,/2 D/2 A,/2 E/2 A,/2 F/2 A,/2 E/2 A,/2 F/2 A,/2 G/2 A,/2 |A/2 A,/2 E/2 A,/2 F/2 A,/2 G/2 A,/2 z/2 A/2 G/2 A/2 F/2 A/2 E/2 A/2 |\n'
..'D/2 A/2 ^C/2 A/2 D/2 A/2 E/2 A/2 F/2 A/2 A,/2 A/2 =B,/2 A/2 ^C/2 A/2 |D/2 A/2 ^C/2 A/2 D/2 A/2 E/2 A/2 z/2 E/2 D/2 ^C/2 D z/2 F/2 |E/2 F/2 G/2 A/2 B/2 A/2 G/2 A/2 F E D/2 E/2 F/2 _E/2 |D/2 C/2 B,/2 A,/2 G,/2 A,/2 B,/2 C/2 E/2 C/2 A,/2 F,/2 A,/2 C/2 _E/2 C/2 |D/2 B,/2 G,/2 D,/2 G,/2 B,/2 D/2 G/2 C/2 D/2 B,/2 C/2 A,/2 G,/2 ^F,/2 E,/2 |^F,/2 D,/2 ^F,/2 G,/2 A,/2 D/2 A,/2 G,/2 ^F,/2 D/2 ^F,/2 G,/2 A,/2 D/2 A,/2 ^F,/2 |G,/2 D,/2 G,/2 A,/2 B,/2 D/2 B,/2 A,/2 G,/2 D,/2 G,/2 A,/2 B,/2 D/2 C/2 B,/2 |A,/2 F,/2 A,/2 B,/2 C/2 _E/2 C/2 B,/2 A,/2 F,/2 A,/2 B,/2 C/2 _E/2 C/2 B,/2 |A,/2 B,/2 D/2 F/2 G/2 B/2 G/2 D/2 B,/2 G,/2 B,/2 D/2 G/2 B/2 G/2 D/2 |C/2 A,/2 C/2 _E/2 ^F/2 A/2 ^F/2 _E/2 C/2 A,/2 C/2 _E/2 ^F/2 A/2 ^F/2 =E/2 |D, z D C B,2 C D |_E2 F G A2 F _E |D/2 _E/2 D/2 C/2 B,/2 C/2 B,/2 A,/2 G,/2 A,/2 B,/2 A,/2 G,/2 A,/2 G,/2 ^F,/2 |G,/2 F,/2 E,/2 D,/2 ^C, E, F,/2 G,/2 A,/2 =B,/2 ^C/2 D/2 E/2 F/2 |G F/2 E/2 D ^C D E F G |A ^C D E F E F D |E D D ^C D G E C |D8 z/3 f/3 g/3 a/3 b/3 A/3 B/3 c/3 d/3 c/3 d/3 _e/3 f/3 F/3 G/3 A/3 |\n'
..'B/3 A/3 B/3 c/3 d/3 A/3 G/3 F/3 _E/3 G/3 A/3 B/3 c/3 G/3 F/3 _E/3 D/3 F/3 G/3 A/3 B/3 A,/3 B,/3 C/3 D/3 C/3 D/3 _E/3 F/3 F,/3 G,/3 A,/3 |B,/3 A,/3 B,/3 C/3 D/3 C/3 B,/3 A,/3 G,/3 B,/3 C/3 D/3 _E/3 D/3 C/3 B,/3 A,/3 C/3 D/3 =E/3 ^F/3 _E/3 D/3 C/3 B,/3 ^F/3 G/3 A/3 B/3 c/3 d/3 G/3 |e6 d6 |z/2 ^G/2 =B/2 F/2 G/2 D/2 F/2 =B,/2 |D/2 ^G,/2 A, z D A,3 =G,/2 F,/2 |C8 z/3 G,/3 F,/3 G,/3 E,/3 E,/3 D,/3 E,/3 C,/3 A,/3 G,/3 A,/3 F,/3 F,/3 E,/3 F,/3 |D,/3 =B,/3 A,/3 =B,/3 G,/3 G,/3 F,/3 G,/3 E,/3 C/3 =B,/3 C/3 A,/3 D/3 C/3 D/3 =B,/3 E/3 D/3 E/3 C/3 F/3 E/3 F/3 D/3 G/3 F/3 G/3 E/3 C/3 =B/3 C/3 |A,/3 D/3 C/3 D/3 =B,/3 ^G,/3 ^F,/3 ^G,/3 E,/3 C/3 =B,/3 C/3 A,/3 =F,/3 E,/3 F,/3 D,/3 =B,/3 A,/3 =B,/3 C,/3 A,/3 =G,/3 A,/3 =B,/3 ^G,/3 ^F,/3 ^G,/3 E,/3 C/3 =B,/3 A,/3 |^G,/3 D/3 C/3 =B,/3 A,/2 D/3 C/3 =B,/3 =B,/3 F/3 E/3 D/3 C/3 =G/3 F/3 E/3 D/3 A/3 G/3 F/3 E/3 G/3 A/3 =B/3 c G |^c A,/3 ^C/3 E/3 A/3 ^c ^c d A,/3 D/3 F/3 A/3 d d |=B G,/3 =B,/3 D/3 G/3 =B, =B, c G,/3 C/3 E/3 G/3 c c |A F,/3 A,/3 C/3 F/3 A A B F,/3 B,/3 D/3 F/3 B B |B E,/3 G,/3 B,/3 ^C/3 B B A D,/3 A,/3 D/3 ^F/3 A A3 |G2 E2 F2 |E2 C2 D2 B,2 |D12 |'
end
--# Main
-- ABCplayerCodea version 0.2.0
-- Plays ABC musical notation format tunes on the Codea/Codify iPad platform.
-- By Fred Bogg, November 2011. Improvements welcome. Thanks to ipda41001 for coding assistance.
-- This program defines musical notes and chords, parses an ABC format tune, creates a table
-- of notes to be played with their durations, and then plays it. With the parsing done
-- first, playback is possible without slowing down draw frames (psuedo-background).
-- 0.4
-- precaching
-- tuplets
-- fade function
-- Use this function to perform your initial setup
function setup()
-- loads data into ABCtune string variable
sampleMusic()
-- Instantiates the class using the tune. arg 1 for loop, arg 2 for debug, arg 3 dumps
-- myTune = ABCMusic(ABCtune,1)
text("Loading...",WIDTH/2, HEIGHT/2)
--[[ secondTune = ABCMusic('X:1\n'
..'T:Pac Man Theme\n'
..'C:Toshio Kai arr. Fred Bogg Copyright NAMCO\n'
..'Q:135\n'
..'M:4/4\n'
..'L:1/16\n'
..'K:C\n'
..'[B,B]b^f[B^d] b/2^f3/2^dB [C,C]c\'g[Ce] c\'/2g3/2[Ce]C|\n'
..'[B,B]b^f[B^d] b/2^f3/2^dB ^d/2e/2[^gf]f/2^f/2[^ag]g/2^g/2ab2')
--]]
end
-- This function gets called once every frame
function draw()
-- insert our game here... :)
background(0, 0, 0, 255)
ellipse(CurrentTouch.x,CurrentTouch.y,100)
if myTune == nil then
myTune = ABCMusic(ABCtune,1)
end
cached = ABCMusic:preCachePlay()
-- Play the next bit of music, not the whole lot
if cached == true then
myTune:play()
else
text("Caching...",WIDTH/2, HEIGHT/2)
end
-- secondTune:play()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment