Last active
August 3, 2019 14:50
-
-
Save c3r38r170/a919d5042db42d7eaa6ed09ea1222de2 to your computer and use it in GitHub Desktop.
A little script to take parts from MusicXML files and turn them into a Pascal script that plays it. Lacks: || |: symbol (start of repetition, as far as I know) and multiple notes at the same time (yeah, can only play well simple songs, like kids classics or 8-bit OSTs). Free for anyone, tested in last version of Chrome as of today.
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
function checkTied(r,s){ | |
r=r.querySelector('notations'); | |
if(r){ | |
r=r.querySelector('tied'); | |
if(r) | |
return r.getAttribute('type')==s; | |
} | |
return false; | |
} | |
let a='',i=1,d={A:[0,0,0,220,440,880,1760],B:[0,0,0,247,494,988,1975],C:[0,0,0,131,262,523,1046,2093],D:[0,0,0,147,294,587,1175,2349],E:[0,0,0,165,330,659,1318,2637],F:[0,0,0,175,349,698,1397,2793],Es:[0,0,0,175,349,698,1397,2793],G:[0,0,0,196,392,784,1568,3136],As:[0,0,0,233,466,932,1865,3729],Cs:[0,0,0,139,277,554,1109,2217],Ds:[0,0,0,156,311,622,1244,2489],Fs:[0,0,0,185,370,740,1480,2960],Gs:[0,0,0,208,415,831,1661,3322]},f=['C','D','F','G','A'],h=[],tempo=0,tempAcc=[]; | |
for(let b of document.querySelectorAll('#P1 note')){ | |
let j=[]; | |
if(b.querySelector('rest')) | |
j[0]=0; | |
else{ | |
let c=b.querySelector('pitch'),e=b.querySelector('accidental'); | |
if(e){ | |
let k=[c.querySelector('step').innerHTML,+c.querySelector('octave').innerHTML,e.innerHTML],l=tempAcc.findIndex(function(e){return e[0]==k[0]&&e[1]==k[1]}); | |
j[0]=d[k[0]+(k[2]=='sharp'?'s':'')][k[1]]; | |
if(l==-1) | |
tempAcc.push(k); | |
else | |
tempAcc[l]=k; | |
}else{ | |
let g=c.querySelector('step').innerHTML,n=(+c.querySelector('octave').innerHTML),m=tempAcc.findIndex(function(e){return e[0]==g&&e[1]==n}); | |
j[0]=d[(m==-1?f.includes(g):tempAcc[m][2]=='sharp')?g+'s':g][n]; | |
} | |
} | |
let q=(+b.querySelector('duration').innerHTML); | |
j[1]=Math.round(q/48*260); | |
if(h.length&&h[h.length-1][0]==j[0]&&(!j[0]||checkTied(b,'stop'))) | |
h[h.length-1][1]+=j[1]; | |
else | |
h.push(j); | |
let o=0,p=b.querySelector('type'); | |
if(p) | |
switch(p.innerHTML){ | |
case '16th': | |
o+=.125; | |
break; | |
case 'eighth': | |
o+=.25; | |
break; | |
case 'quarter': | |
o+=.5; | |
break; | |
case 'half': | |
o+=1; | |
break; | |
case 'whole': | |
o+=2; | |
break; | |
} | |
else | |
o+=q/24; | |
tempo+=b.querySelector('dot')?o*1.5:o; | |
if(!checkTied(b,'start')&&tempo>=2){ | |
tempo-=2; | |
tempAcc=[]; | |
} | |
} | |
for(let b of h){ | |
a+=i+':begin\n getNext[1]:='+b[0]+';\n getNext[2]:='+b[1]+';\n end;'; | |
i++; | |
} | |
console.log('program music;\nuses crt;\n\ntype nota=array[1..2]of integer;\n\nvar player:nota;\n i,j,k:integer;\n\nprocedure playSound(a,b:integer);\nbegin\n if a=0 then\n nosound()\n else\n sound(a);\n delay(b);\nend;\n\nfunction getNext(a:integer):nota;\nbegin\n case a of\n '+ | |
a+ | |
'else begin\n i:=22;\n getNext:=getNext(22);\n end;end;\nend;\n\nbegin\nclrscr();\nplayer:=getNext(1);\ni:=1;\nrepeat\n playSound(player[1],player[2]*5);\n i:=i+1;\n player:=getNext(i)\nuntil keypressed();\nnosound();\nclrscr();\nend.'); | |
/* Customization: | |
Line 10, variable "f": Define the key as the notes that should be sharp by default | |
Line 11: #PX is the id of the part to be analyzed | |
Line 30: That 48 has to be the <duration> of a "whole" note in that sheet, 260 is a personal practical constant for the duration of a pascal delay on my computer | |
Line 55: That 24 has to be the <duration> of a "half" note in that sheet. | |
flat.io is a very good place to take MusicXML files from.*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment