Created
March 4, 2012 09:55
-
-
Save fredbogg/1971776 to your computer and use it in GitHub Desktop.
Play ABC notation tunes in your Codea project.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# 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