play-1.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. //snd-1.js-file to include in html pages with abc2svg-1.js for playing
  2. function AbcPlay(i_conf){var conf=i_conf,init={},audio=ToAudio(),audio5,midi5,current,abcplay={clear:audio.clear,add:audio.add,set_sfu:function(v){if(v==undefined)
  3. return conf.sfu
  4. conf.sfu=v},set_speed:function(v){if(v==undefined)
  5. return conf.speed
  6. conf.new_speed=v},set_vol:function(v){if(v==undefined)
  7. return conf.gain;conf.gain=v
  8. if(current&&current.set_vol)
  9. current.set_vol(v)},play:play,stop:vf}
  10. function vf(){}
  11. function play(istart,i_iend,a_e){init.istart=istart;init.i_iend=i_iend;init.a_e=a_e
  12. if(midi5)
  13. midi5.get_outputs(play2)
  14. else
  15. play2()}
  16. function play2(out){var o
  17. if(!out)
  18. out=[]
  19. o=audio5.get_outputs()
  20. if(o)
  21. Array.prototype.push.apply(out,o)
  22. if(out.length==0){if(conf.onend)
  23. conf.onend()
  24. return}
  25. if(out.length==1){o=0}else{o=-1
  26. var pr="Use"
  27. for(var i=0;i<out.length;i++)
  28. pr+="\n "+i+": "+out[i]
  29. var res=window.prompt(pr,'0')
  30. if(res){o=Number(res)
  31. if(isNaN(o)||o<0||o>=out.length)
  32. o=-1}
  33. if(!res||o<0){if(conf.onend)
  34. conf.onend()
  35. return}}
  36. current=out[o]=='sf2'?audio5:midi5;abcplay.play=current.play;abcplay.stop=current.stop
  37. if(current.set_output)
  38. current.set_output(out[o]);if(abc2svg.pwait){if(typeof abc2svg.pwait=="boolean"){abc2svg.pwait=function(){abcplay.play(init.istart,init.i_iend,init.a_e)}}
  39. return}
  40. abcplay.play(init.istart,init.i_iend,init.a_e)}
  41. conf.gain=0.7;conf.speed=1;(function(){var v
  42. try{if(!localStorage)
  43. return}catch(e){return}
  44. if(!conf.sfu){v=localStorage.getItem("sfu")
  45. if(v)
  46. conf.sfu=v}
  47. v=localStorage.getItem("volume")
  48. if(v)
  49. conf.gain=Number(v)})()
  50. if(typeof Midi5=="function")
  51. midi5=Midi5(conf)
  52. if(typeof Audio5=="function")
  53. audio5=Audio5(conf);return abcplay}
  54. if(typeof module=='object'&&typeof exports=='object')
  55. exports.AbcPlay=AbcPlay
  56. function ToAudio(){var C=abc2svg.C,a_e,p_time,abc_time,play_factor
  57. return{clear:function(){var a_pe=a_e;a_e=null
  58. return a_pe},add:function(start,voice_tb){var i,n,dt,d,v,rep_st_s,rep_en_s,rep_nx_s,rep_st_fac,instr=[],s=start
  59. function set_voices(){var v,p_v,s,mi
  60. a_e.push(new Float32Array([0,0,-1,121,0,1,0]))
  61. for(v=0;v<voice_tb.length;v++){p_v=voice_tb[v];mi=p_v.instr||0
  62. if(p_v.midictl){for(s=p_v.sym;s;s=s.next)
  63. if(s.dur)
  64. break
  65. if(!s)
  66. continue
  67. p_v.midictl.forEach(function(val,i){a_e.push(new Float32Array([s.istart,0,-1,i,val,1,v]))})}
  68. instr[v]=mi}}
  69. function do_tie(s,b40,d){var i,note,v=s.v,end_time=s.time+s.dur
  70. for(s=s.ts_next;;s=s.ts_next){if(!s)
  71. return d
  72. if(s==rep_en_s){s=rep_nx_s
  73. while(s&&s.v!=v)
  74. s=s.ts_next
  75. if(!s)
  76. return d
  77. end_time=s.time}
  78. if(s.time!=end_time)
  79. return d
  80. if(s.type==C.NOTE&&s.v==v)
  81. break}
  82. i=s.notes.length
  83. while(--i>=0){note=s.notes[i]
  84. if(note.b40==b40){note.ti2=true
  85. d+=s.dur/play_factor;return note.tie_ty?do_tie(s,b40,d):d}}
  86. return d}
  87. function gen_grace(s){var g,i,n,t,d,s2,next=s.next
  88. if(s.sappo){d=C.BLEN/16}else if((!next||next.type!=C.NOTE)&&s.prev&&s.prev.type==C.NOTE){d=s.prev.dur/2}else{next.ts_prev.ts_next=next.ts_next;next.ts_next.ts_prev=next.ts_prev;for(s2=next.ts_next;s2;s2=s2.ts_next){if(s2.time!=next.time){next.ts_next=s2
  89. next.ts_prev=s2.ts_prev;next.ts_prev.ts_next=next;s2.ts_prev=next
  90. break}}
  91. d=next.dur/12
  92. if(d&(d-1)==0)
  93. d=next.dur/2
  94. else
  95. d=next.dur/3;next.time+=d;next.dur-=d}
  96. n=0
  97. for(g=s.extra;g;g=g.next)
  98. if(g.type==C.NOTE)
  99. n++;d/=n*play_factor;t=p_time
  100. for(g=s.extra;g;g=g.next){if(g.type!=C.NOTE)
  101. continue
  102. gen_notes(g,t,d);t+=d}}
  103. function gen_notes(s,t,d){for(var i=0;i<=s.nhd;i++){var note=s.notes[i]
  104. if(note.ti2)
  105. continue
  106. a_e.push(new Float32Array([s.istart,t,instr[s.v],note.midi,note.tie_ty?do_tie(s,note.b40,d):d,1,s.v]))}}
  107. if(!a_e){a_e=[]
  108. abc_time=p_time=0;play_factor=C.BLEN/4*120/60}else if(s.time<abc_time){abc_time=s.time}
  109. set_voices()
  110. while(s){if(s.tempo){d=0;n=s.tempo_notes.length
  111. for(i=0;i<n;i++)
  112. d+=s.tempo_notes[i];play_factor=d*s.tempo/60}
  113. dt=s.time-abc_time
  114. if(dt>0){p_time+=dt/play_factor;abc_time=s.time}
  115. switch(s.type){case C.BAR:if(!s.seqst)
  116. break
  117. if(s==rep_en_s){s=rep_nx_s
  118. abc_time=s.time}else if(s.bar_type[0]==':'){rep_nx_s=s
  119. if(!rep_en_s)
  120. rep_en_s=s
  121. if(rep_st_s){s=rep_st_s
  122. play_factor=rep_st_fac}else{s=start;set_voices()}
  123. abc_time=s.time
  124. break}
  125. if(s.bar_type[s.bar_type.length-1]==':'){rep_st_s=s;rep_en_s=null
  126. rep_st_fac=play_factor}else if(s.text&&s.text[0]=='1'){rep_en_s=s}
  127. break
  128. case C.GRACE:if(s.time==0&&abc_time==0){dt=0
  129. if(s.sappo)
  130. dt=C.BLEN/16
  131. else if(!s.next||s.next.type!=C.NOTE)
  132. dt=d/2;abc_time-=dt}
  133. gen_grace(s)
  134. break
  135. case C.REST:case C.NOTE:d=s.dur
  136. if(s.next&&s.next.type==C.GRACE){dt=0
  137. if(s.next.sappo)
  138. dt=C.BLEN/16
  139. else if(!s.next.next||s.next.next.type!=C.NOTE)
  140. dt=d/2;s.next.time-=dt;d-=dt}
  141. d/=play_factor
  142. if(s.type==C.NOTE)
  143. gen_notes(s,p_time,d)
  144. else
  145. a_e.push(new Float32Array([s.istart,p_time,0,0,d,0,s.v]))
  146. break
  147. case C.BLOCK:switch(s.subtype){case"midictl":a_e.push(new Float32Array([s.istart,p_time,-1,s.ctrl,s.val,1,s.v]))
  148. break
  149. case"midiprog":instr[s.v]=s.instr
  150. break}
  151. break}
  152. s=s.ts_next}}}}
  153. if(typeof module=='object'&&typeof exports=='object')
  154. exports.ToAudio=ToAudio
  155. var abcsf2=[]
  156. function Audio5(i_conf){var conf=i_conf,onend=function(){},onnote=function(){},errmsg,ac,gain,params=[],rates=[],w_instr=0,evt_idx,iend,stime,timouts=[]
  157. function js_instr_load(instr,done,fail){abc2svg.loadjs(conf.sfu+'/'+instr+'.js',function(){done(b64dcod(abcsf2[instr]))},fail)}
  158. if(!conf.instr_load)
  159. conf.instr_load=js_instr_load
  160. var b64d=[]
  161. function init_b64d(){var b64l='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',l=b64l.length
  162. for(var i=0;i<l;i++)
  163. b64d[b64l[i]]=i
  164. b64d['=']=0}
  165. function b64dcod(s){var i,t,dl,a,l=s.length,j=0
  166. dl=l*3/4
  167. if(s[l-1]=='='){if(s[l-2]=='=')
  168. dl--;dl--;l-=4}
  169. a=new Uint8Array(dl)
  170. for(i=0;i<l;i+=4){t=(b64d[s[i]]<<18)+
  171. (b64d[s[i+1]]<<12)+
  172. (b64d[s[i+2]]<<6)+
  173. b64d[s[i+3]];a[j++]=(t>>16)&0xff;a[j++]=(t>>8)&0xff;a[j++]=t&0xff}
  174. if(l!=s.length){t=(b64d[s[i]]<<18)+
  175. (b64d[s[i+1]]<<12)+
  176. (b64d[s[i+2]]<<6)+
  177. b64d[s[i+3]];a[j++]=(t>>16)&0xff
  178. if(j<dl)
  179. a[j++]=(t>>8)&0xff}
  180. return a}
  181. function sample_cp(b,s){var i,n,a=b.getChannelData(0)
  182. for(i=0;i<s.length;i++)
  183. a[i]=s[i]/196608}
  184. function sf2_create(parser,instr){var i,sid,gen,parm,sampleRate,sample,j,infos=[],instrument=parser.instrument,zone=parser.instrumentZone
  185. i=instrument[0].instrumentBagIndex
  186. j=instrument[1]?instrument[1].instrumentBagIndex:zone.length
  187. while(i<j){infos.push({generator:parser.createInstrumentGenerator_(zone,i).generator})
  188. i++}
  189. rates[instr]=[]
  190. for(i=0;i<infos.length;i++){gen=infos[i].generator;if(!gen.sampleID)
  191. continue
  192. sid=gen.sampleID.amount;sampleRate=parser.sampleHeader[sid].sampleRate;sample=parser.sample[sid];parm={attack:Math.pow(2,(gen.attackVolEnv?gen.attackVolEnv.amount:-12000)/1200),hold:Math.pow(2,(gen.holdVolEnv?gen.holdVolEnv.amount:-12000)/1200),decay:Math.pow(2,(gen.decayVolEnv?gen.decayVolEnv.amount:-12000)/1200)/3,sustain:gen.sustainVolEnv?(gen.sustainVolEnv.amount/1000):0,buffer:ac.createBuffer(1,sample.length,sampleRate)}
  193. parm.hold+=parm.attack;parm.decay+=parm.hold;if(parm.sustain>=.4)
  194. parm.sustain=0.01
  195. else
  196. parm.sustain=1-parm.sustain/.4
  197. sample_cp(parm.buffer,sample)
  198. if(gen.sampleModes&&(gen.sampleModes.amount&1)){parm.loopStart=parser.sampleHeader[sid].startLoop/sampleRate;parm.loopEnd=parser.sampleHeader[sid].endLoop/sampleRate}
  199. var scale=(gen.scaleTuning?gen.scaleTuning.amount:100)/100,tune=(gen.coarseTune?gen.coarseTune.amount:0)+
  200. (gen.fineTune?gen.fineTune.amount:0)/100+
  201. parser.sampleHeader[sid].pitchCorrection/100-
  202. (gen.overridingRootKey?gen.overridingRootKey.amount:parser.sampleHeader[sid].originalPitch)
  203. for(j=gen.keyRange.lo;j<=gen.keyRange.hi;j++){rates[instr][j]=Math.pow(Math.pow(2,1/12),(j+tune)*scale);params[instr][j]=parm}}}
  204. function load_instr(instr,a_e){w_instr++;conf.instr_load(instr,function(sf2_bin){var parser=new sf2.Parser(sf2_bin);parser.parse();sf2_create(parser,instr);if(--w_instr==0)
  205. play_start(a_e)},function(){errmsg('could not find the instrument '+
  206. ((instr/128)|0).toString()+'-'+
  207. (instr%128).toString());if(--w_instr==0)
  208. play_start(a_e)})}
  209. function load_res(a_e){var i,e,instr,v,bk=[]
  210. for(i=evt_idx;i<iend;i++){e=a_e[i]
  211. if(!e)
  212. break
  213. instr=e[2]
  214. v=e[6]
  215. if(bk[v]==undefined)
  216. bk[v]=0
  217. if(instr<0){switch(e[3]){case 0:bk[v]=(bk[v]&0x3fff)|(e[4]<<14)
  218. break
  219. case 32:bk[v]=(bk[v]&0x1fc07f)|(e[4]<<7)
  220. break
  221. case 121:bk=[]
  222. break}}else{if(bk[v]){instr&=0x7f
  223. instr|=bk[v]
  224. e[2]=instr}
  225. if(!params[instr]){params[instr]=[];load_instr(instr,a_e)}}}}
  226. function note_run(e,t,d){var g,st,instr=e[2],key=e[3]|0,parm=params[instr][key],o=ac.createBufferSource();if(!parm)
  227. return
  228. o.buffer=parm.buffer
  229. if(parm.loopStart){o.loop=true;o.loopStart=parm.loopStart;o.loopEnd=parm.loopEnd}
  230. if(o.detune){var dt=(e[3]*100)%100
  231. if(dt)
  232. o.detune.value=dt}
  233. o.playbackRate.value=rates[instr][key];g=ac.createGain();if(parm.hold<0.002){g.gain.setValueAtTime(1,t)}else{if(parm.attack<0.002){g.gain.setValueAtTime(1,t)}else{g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(1,t+parm.attack)}
  234. g.gain.setValueAtTime(1,t+parm.hold)}
  235. g.gain.exponentialRampToValueAtTime(parm.sustain,t+parm.decay);o.connect(g);g.connect(gain);o.start(t);o.stop(t+d)}
  236. function play_next(a_e){var t,e,e2,maxt,st,d;if(a_e)
  237. e=a_e[evt_idx]
  238. if(!e||evt_idx>=iend){onend()
  239. return}
  240. if(conf.new_speed){stime=ac.currentTime-
  241. (ac.currentTime-stime)*conf.speed/conf.new_speed;conf.speed=conf.new_speed;conf.new_speed=0}
  242. timouts=[];t=e[1]/conf.speed;maxt=t+3
  243. while(1){d=e[4]/conf.speed
  244. if(e[2]>=0){if(e[5]!=0)
  245. note_run(e,t+stime,d)
  246. var i=e[0];st=(t+stime-ac.currentTime)*1000;timouts.push(setTimeout(onnote,st,i,true));setTimeout(onnote,st+d*1000,i,false)}
  247. e=a_e[++evt_idx]
  248. if(!e||evt_idx>=iend){setTimeout(onend,(t+stime-ac.currentTime+d)*1000)
  249. return}
  250. t=e[1]/conf.speed
  251. if(t>maxt)
  252. break}
  253. timouts.push(setTimeout(play_next,(t+stime-ac.currentTime)*1000-300,a_e))}
  254. function play_start(a_e){if(iend==0){onend()
  255. return}
  256. if(w_instr!=0)
  257. return
  258. gain.connect(ac.destination);stime=ac.currentTime+.2
  259. -a_e[evt_idx][1]*conf.speed;play_next(a_e)}
  260. init_b64d();if(!conf.sfu)
  261. conf.sfu="Scc1t2"
  262. return{get_outputs:function(){return(window.AudioContext||window.webkitAudioContext)?['sf2']:null},play:function(istart,i_iend,a_e){if(!a_e||istart>=a_e.length){onend()
  263. return}
  264. if(conf.onend)
  265. onend=conf.onend
  266. if(conf.onnote)
  267. onnote=conf.onnote
  268. errmsg=conf.errmsg||alert
  269. function play_unlock(){var buf=ac.createBuffer(1,1,22050),src=ac.createBufferSource();src.buffer=buf;src.connect(ac.destination);src.noteOn(0)}
  270. if(!gain){ac=conf.ac
  271. if(!ac){conf.ac=ac=new(window.AudioContext||window.webkitAudioContext);if(/iPad|iPhone|iPod/.test(navigator.userAgent))
  272. play_unlock()}
  273. gain=ac.createGain();gain.gain.value=conf.gain}
  274. iend=i_iend;evt_idx=istart;load_res(a_e);play_start(a_e)},stop:function(){iend=0
  275. timouts.forEach(function(id){clearTimeout(id)})
  276. play_next()
  277. if(gain){gain.disconnect();gain=null}},set_vol:function(v){if(gain)
  278. gain.gain.value=v}}}
  279. (function(root,factory){if(typeof exports==="object"){root.sf2=exports;factory(exports)}else if(typeof define==="function"&&define.amd){define(["exports"],function(exports){root.sf2=exports;return(root.sf2,factory(exports))})}else{root.sf2={};factory(root.sf2)}}(this,function(sf2){"use strict";sf2.Parser=function(input,options){options=options||{};this.input=input;this.parserOptions=options.parserOptions};sf2.Parser.prototype.parse=function(){var parser=new sf2.Riff.Parser(this.input,this.parserOptions),chunk;parser.parse();if(parser.chunkList.length!==1)
  280. throw new Error('wrong chunk length');chunk=parser.getChunk(0);if(chunk===null)
  281. throw new Error('chunk not found');this.parseRiffChunk(chunk);this.input=null};sf2.Parser.prototype.parseRiffChunk=function(chunk){var parser,data=this.input,ip=chunk.offset,signature;if(chunk.type!=='RIFF')
  282. throw new Error('invalid chunk type:'+chunk.type);signature=String.fromCharCode(data[ip++],data[ip++],data[ip++],data[ip++]);if(signature!=='sfbk')
  283. throw new Error('invalid signature:'+signature);parser=new sf2.Riff.Parser(data,{'index':ip,'length':chunk.size-4});parser.parse();if(parser.getNumberOfChunks()!==3)
  284. throw new Error('invalid sfbk structure');this.parseInfoList(parser.getChunk(0));this.parseSdtaList(parser.getChunk(1));this.parsePdtaList(parser.getChunk(2))};sf2.Parser.prototype.parseInfoList=function(chunk){var parser,data=this.input,ip=chunk.offset,signature;if(chunk.type!=='LIST')
  285. throw new Error('invalid chunk type:'+chunk.type);signature=String.fromCharCode(data[ip++],data[ip++],data[ip++],data[ip++]);if(signature!=='INFO')
  286. throw new Error('invalid signature:'+signature);parser=new sf2.Riff.Parser(data,{'index':ip,'length':chunk.size-4});parser.parse()};sf2.Parser.prototype.parseSdtaList=function(chunk){var parser,data=this.input,ip=chunk.offset,signature;if(chunk.type!=='LIST')
  287. throw new Error('invalid chunk type:'+chunk.type);signature=String.fromCharCode(data[ip++],data[ip++],data[ip++],data[ip++]);if(signature!=='sdta')
  288. throw new Error('invalid signature:'+signature);parser=new sf2.Riff.Parser(data,{'index':ip,'length':chunk.size-4});parser.parse();if(parser.chunkList.length!==1)
  289. throw new Error('TODO');this.samplingData=parser.getChunk(0)};sf2.Parser.prototype.parsePdtaList=function(chunk){var parser,data=this.input,ip=chunk.offset,signature;if(chunk.type!=='LIST')
  290. throw new Error('invalid chunk type:'+chunk.type);signature=String.fromCharCode(data[ip++],data[ip++],data[ip++],data[ip++]);if(signature!=='pdta')
  291. throw new Error('invalid signature:'+signature);parser=new sf2.Riff.Parser(data,{'index':ip,'length':chunk.size-4});parser.parse();if(parser.getNumberOfChunks()!==9)
  292. throw new Error('invalid pdta chunk');this.parsePhdr((parser.getChunk(0)));this.parsePbag((parser.getChunk(1)));this.parsePmod((parser.getChunk(2)));this.parsePgen((parser.getChunk(3)));this.parseInst((parser.getChunk(4)));this.parseIbag((parser.getChunk(5)));this.parseImod((parser.getChunk(6)));this.parseIgen((parser.getChunk(7)));this.parseShdr((parser.getChunk(8)))};sf2.Parser.prototype.parsePhdr=function(chunk){var data=this.input,ip=chunk.offset,presetHeader=this.presetHeader=[],size=chunk.offset+chunk.size;if(chunk.type!=='phdr')
  293. throw new Error('invalid chunk type:'+chunk.type);while(ip<size){presetHeader.push({presetName:String.fromCharCode.apply(null,data.subarray(ip,ip+=20)),preset:data[ip++]|(data[ip++]<<8),bank:data[ip++]|(data[ip++]<<8),presetBagIndex:data[ip++]|(data[ip++]<<8),library:(data[ip++]|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24))>>>0,genre:(data[ip++]|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24))>>>0,morphology:(data[ip++]|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24))>>>0})}};sf2.Parser.prototype.parsePbag=function(chunk){var data=this.input,ip=chunk.offset,presetZone=this.presetZone=[],size=chunk.offset+chunk.size;if(chunk.type!=='pbag')
  294. throw new Error('invalid chunk type:'+chunk.type);while(ip<size){presetZone.push({presetGeneratorIndex:data[ip++]|(data[ip++]<<8),presetModulatorIndex:data[ip++]|(data[ip++]<<8)})}};sf2.Parser.prototype.parsePmod=function(chunk){if(chunk.type!=='pmod')
  295. throw new Error('invalid chunk type:'+chunk.type);this.presetZoneModulator=this.parseModulator(chunk)};sf2.Parser.prototype.parsePgen=function(chunk){if(chunk.type!=='pgen')
  296. throw new Error('invalid chunk type:'+chunk.type);this.presetZoneGenerator=this.parseGenerator(chunk)};sf2.Parser.prototype.parseInst=function(chunk){var data=this.input,ip=chunk.offset,instrument=this.instrument=[],size=chunk.offset+chunk.size;if(chunk.type!=='inst')
  297. throw new Error('invalid chunk type:'+chunk.type);while(ip<size){instrument.push({instrumentName:String.fromCharCode.apply(null,data.subarray(ip,ip+=20)),instrumentBagIndex:data[ip++]|(data[ip++]<<8)})}};sf2.Parser.prototype.parseIbag=function(chunk){var data=this.input,ip=chunk.offset,instrumentZone=this.instrumentZone=[],size=chunk.offset+chunk.size;if(chunk.type!=='ibag')
  298. throw new Error('invalid chunk type:'+chunk.type);while(ip<size){instrumentZone.push({instrumentGeneratorIndex:data[ip++]|(data[ip++]<<8),instrumentModulatorIndex:data[ip++]|(data[ip++]<<8)})}};sf2.Parser.prototype.parseImod=function(chunk){if(chunk.type!=='imod')
  299. throw new Error('invalid chunk type:'+chunk.type);this.instrumentZoneModulator=this.parseModulator(chunk)};sf2.Parser.prototype.parseIgen=function(chunk){if(chunk.type!=='igen')
  300. throw new Error('invalid chunk type:'+chunk.type);this.instrumentZoneGenerator=this.parseGenerator(chunk)};sf2.Parser.prototype.parseShdr=function(chunk){var data=this.input,ip=chunk.offset,samples=this.sample=[],sampleHeader=this.sampleHeader=[],size=chunk.offset+chunk.size,sampleName,start,end,startLoop,endLoop,sampleRate,originalPitch,pitchCorrection,sampleLink,sampleType;if(chunk.type!=='shdr')
  301. throw new Error('invalid chunk type:'+chunk.type);while(ip<size){sampleName=String.fromCharCode.apply(null,data.subarray(ip,ip+=20));start=(data[ip++]<<0)|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24);end=(data[ip++]<<0)|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24);startLoop=(data[ip++]<<0)|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24);endLoop=(data[ip++]<<0)|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24);sampleRate=(data[ip++]<<0)|(data[ip++]<<8)|(data[ip++]<<16)|(data[ip++]<<24);originalPitch=data[ip++];pitchCorrection=(data[ip++]<<24)>>24;sampleLink=data[ip++]|(data[ip++]<<8);sampleType=data[ip++]|(data[ip++]<<8);var sample=new Int16Array(new Uint8Array(data.subarray(this.samplingData.offset+start*2,this.samplingData.offset+end*2)).buffer);startLoop-=start;endLoop-=start;if(sampleRate>0){var adjust=this.adjustSampleData(sample,sampleRate);sample=adjust.sample;sampleRate*=adjust.multiply;startLoop*=adjust.multiply;endLoop*=adjust.multiply}
  302. samples.push(sample);sampleHeader.push({sampleName:sampleName,startLoop:startLoop,endLoop:endLoop,sampleRate:sampleRate,originalPitch:originalPitch,pitchCorrection:pitchCorrection,sampleLink:sampleLink,sampleType:sampleType})}};sf2.Parser.prototype.adjustSampleData=function(sample,sampleRate){var newSample,i,il,j,multiply=1;while(sampleRate<22050){newSample=new Int16Array(sample.length*2);for(i=j=0,il=sample.length;i<il;++i){newSample[j++]=sample[i];newSample[j++]=sample[i]}
  303. sample=newSample;multiply*=2;sampleRate*=2}
  304. return{sample:sample,multiply:multiply}};sf2.Parser.prototype.parseModulator=function(chunk){var data=this.input,ip=chunk.offset,size=chunk.offset+chunk.size,code,key,output=[];while(ip<size){ip+=2;code=data[ip++]|(data[ip++]<<8);key=sf2.Parser.GeneratorEnumeratorTable[code];if(key===undefined){output.push({type:key,value:{code:code,amount:data[ip]|(data[ip+1]<<8)<<16>>16,lo:data[ip++],hi:data[ip++]}})}else{switch(key){case'keyRange':case'velRange':case'keynum':case'velocity':output.push({type:key,value:{lo:data[ip++],hi:data[ip++]}});break;default:output.push({type:key,value:{amount:data[ip++]|(data[ip++]<<8)<<16>>16}});break}}
  305. ip+=2;ip+=2}
  306. return output};sf2.Parser.prototype.parseGenerator=function(chunk){var data=this.input,ip=chunk.offset,size=chunk.offset+chunk.size,code,key,output=[];while(ip<size){code=data[ip++]|(data[ip++]<<8);key=sf2.Parser.GeneratorEnumeratorTable[code];if(key===undefined){output.push({type:key,value:{code:code,amount:data[ip]|(data[ip+1]<<8)<<16>>16,lo:data[ip++],hi:data[ip++]}});continue}
  307. switch(key){case'keynum':case'keyRange':case'velRange':case'velocity':output.push({type:key,value:{lo:data[ip++],hi:data[ip++]}});break;default:output.push({type:key,value:{amount:data[ip++]|(data[ip++]<<8)<<16>>16}});break}}
  308. return output};sf2.Parser.prototype.getPresets=function(){var preset=this.presetHeader,zone=this.presetZone,output=[],bagIndex,bagIndexEnd,zoneInfo,presetGenerator,presetModulator,i,il,j,jl
  309. for(i=0,il=preset.length;i<il;++i){j=preset[i].presetBagIndex
  310. jl=preset[i+1]?preset[i+1].presetBagIndex:zone.length
  311. zoneInfo=[];for(;j<jl;++j){presetGenerator=this.createPresetGenerator_(zone,j);presetModulator=this.createPresetModulator_(zone,j);zoneInfo.push({generator:presetGenerator.generator,modulator:presetModulator.modulator,})}
  312. output.push({info:zoneInfo,header:preset[i],})}
  313. return output};sf2.Parser.prototype.createInstrumentGenerator_=function(zone,index){var modgen=this.createBagModGen_(zone,zone[index].instrumentGeneratorIndex,zone[index+1]?zone[index+1].instrumentGeneratorIndex:this.instrumentZoneGenerator.length,this.instrumentZoneGenerator);return{generator:modgen.modgen,}};sf2.Parser.prototype.createInstrumentModulator_=function(zone,index){var modgen=this.createBagModGen_(zone,zone[index].presetModulatorIndex,zone[index+1]?zone[index+1].instrumentModulatorIndex:this.instrumentZoneModulator.length,this.instrumentZoneModulator);return{modulator:modgen.modgen}};sf2.Parser.prototype.createPresetGenerator_=function(zone,index){var modgen=this.createBagModGen_(zone,zone[index].presetGeneratorIndex,zone[index+1]?zone[index+1].presetGeneratorIndex:this.presetZoneGenerator.length,this.presetZoneGenerator);return{generator:modgen.modgen,}};sf2.Parser.prototype.createPresetModulator_=function(zone,index){var modgen=this.createBagModGen_(zone,zone[index].presetModulatorIndex,zone[index+1]?zone[index+1].presetModulatorIndex:this.presetZoneModulator.length,this.presetZoneModulator);return{modulator:modgen.modgen,}};sf2.Parser.prototype.createBagModGen_=function(zone,indexStart,indexEnd,zoneModGen){var modgen={unknown:[],'keyRange':{hi:127,lo:0}};var info,i,il;for(i=indexStart,il=indexEnd;i<il;++i){info=zoneModGen[i];if(info.type==='unknown')
  314. modgen.unknown.push(info.value);else
  315. modgen[info.type]=info.value}
  316. return{modgen:modgen}};sf2.Parser.GeneratorEnumeratorTable=['startAddrsOffset','endAddrsOffset','startloopAddrsOffset','endloopAddrsOffset','startAddrsCoarseOffset','modLfoToPitch','vibLfoToPitch','modEnvToPitch','initialFilterFc','initialFilterQ','modLfoToFilterFc','modEnvToFilterFc','endAddrsCoarseOffset','modLfoToVolume',undefined,'chorusEffectsSend','reverbEffectsSend','pan',undefined,undefined,undefined,'delayModLFO','freqModLFO','delayVibLFO','freqVibLFO','delayModEnv','attackModEnv','holdModEnv','decayModEnv','sustainModEnv','releaseModEnv','keynumToModEnvHold','keynumToModEnvDecay','delayVolEnv','attackVolEnv','holdVolEnv','decayVolEnv','sustainVolEnv','releaseVolEnv','keynumToVolEnvHold','keynumToVolEnvDecay','instrument',undefined,'keyRange','velRange','startloopAddrsCoarseOffset','keynum','velocity','initialAttenuation',undefined,'endloopAddrsCoarseOffset','coarseTune','fineTune','sampleID','sampleModes',undefined,'scaleTuning','exclusiveClass','overridingRootKey'];sf2.Riff={};sf2.Riff.Parser=function(input,options){options=options||{};this.input=input;this.ip=options.index||0;this.length=options.length||input.length-this.ip;this.offset=this.ip;this.padding=options.padding!==undefined?options.padding:true;this.bigEndian=options.bigEndian!==undefined?options.bigEndian:false};sf2.Riff.Chunk=function(type,size,offset){this.type=type;this.size=size;this.offset=offset};sf2.Riff.Parser.prototype.parse=function(){var length=this.length+this.offset;this.chunkList=[];while(this.ip<length)
  317. this.parseChunk()};sf2.Riff.Parser.prototype.parseChunk=function(){var input=this.input,ip=this.ip,size;this.chunkList.push(new sf2.Riff.Chunk(String.fromCharCode(input[ip++],input[ip++],input[ip++],input[ip++]),(size=this.bigEndian?((input[ip++]<<24)|(input[ip++]<<16)|(input[ip++]<<8)|(input[ip++])):((input[ip++])|(input[ip++]<<8)|(input[ip++]<<16)|(input[ip++]<<24))),ip));ip+=size;if(this.padding&&((ip-this.offset)&1)===1)
  318. ip++;this.ip=ip};sf2.Riff.Parser.prototype.getChunk=function(index){var chunk=this.chunkList[index];if(chunk===undefined)
  319. return null;return chunk};sf2.Riff.Parser.prototype.getNumberOfChunks=function(){return this.chunkList.length};return sf2}));function Midi5(i_conf){var conf=i_conf,onend=function(){},onnote=function(){},rf,op,v_i=[],bk=[],evt_idx,iend,stime,timouts=[]
  320. function note_run(e,t,d){var k=e[3]|0,i=e[2],c=e[6]&0x0f,a=(e[3]*100)%100
  321. if(bk[c]==128)
  322. c=9
  323. if(i!=v_i[c]){if(v_i[c]==undefined)
  324. op.send(new Uint8Array([0xb0+c,121,0]));v_i[c]=i
  325. op.send(new Uint8Array([0xc0+c,i&0x7f]))}
  326. if(a&&Midi5.ma.sysexEnabled){op.send(new Uint8Array([0xf0,0x7f,0x7f,0x08,0x02,i&0x7f,0x01,k,k,a/.78125,0,0xf7]),t)}
  327. op.send(new Uint8Array([0x90+c,k,127]),t);op.send(new Uint8Array([0x80+c,k,0]),t+d-20)}
  328. function play_next(a_e){var t,e,e2,maxt,st,d,c
  329. if(a_e)
  330. e=a_e[evt_idx]
  331. if(!op||evt_idx>=iend||!e){onend()
  332. return}
  333. if(conf.new_speed){stime=window-performance.now()-
  334. (window.performance.now()-stime)*conf.speed/conf.new_speed;conf.speed=conf.new_speed;conf.new_speed=0}
  335. timouts=[];t=e[1]/conf.speed*1000;maxt=t+3000
  336. while(1){d=e[4]/conf.speed*1000
  337. if(e[2]>=0){if(e[5]!=0)
  338. note_run(e,t+stime,d)
  339. st=t+stime-window.performance.now();timouts.push(setTimeout(onnote,st,e[0],true));setTimeout(onnote,st+d,e[0],false)}else{c=e[6]&0x0f
  340. op.send(new Uint8Array([0xb0+c,e[3],e[4]]),t+stime)
  341. if(bk[c]==undefined)
  342. bk[c]=0
  343. switch(e[3]){case 0:bk[c]=(bk[c]&0x7f)|(e[4]<<7)
  344. break
  345. case 32:bk[c]=(bk[c]&0x3f80)|e[4]
  346. break
  347. case 121:bk=[]
  348. break}}
  349. e=a_e[++evt_idx]
  350. if(!e||evt_idx>=iend){setTimeout(onend,t+stime-window.performance.now()+d)
  351. return}
  352. t=e[1]/conf.speed*1000
  353. if(t>maxt)
  354. break}
  355. timouts.push(setTimeout(play_next,(t+stime-window.performance.now())
  356. -300,a_e))}
  357. function send_outputs(access){var o,os,out=[];Midi5.ma=access;if(access&&access.outputs.size>0){os=access.outputs.values()
  358. while(1){o=os.next()
  359. if(!o||o.done)
  360. break
  361. out.push(o.value.name)}}
  362. rf(out)}
  363. return{get_outputs:function(f){if(!navigator.requestMIDIAccess){f()
  364. return}
  365. rf=f;navigator.requestMIDIAccess({sysex:true}).then(send_outputs,function(msg){navigator.requestMIDIAccess().then(send_outputs,function(msg){rf()})})},set_output:function(name){var o,os
  366. if(!Midi5.ma)
  367. return
  368. os=Midi5.ma.outputs.values()
  369. while(1){o=os.next()
  370. if(!o||o.done)
  371. break
  372. if(o.value.name==name){op=o.value
  373. break}}},play:function(istart,i_iend,a_e){if(!a_e||istart>=a_e.length){onend()
  374. return}
  375. if(conf.onend)
  376. onend=conf.onend
  377. if(conf.onnote)
  378. onnote=conf.onnote;iend=i_iend;evt_idx=istart;if(0){op.send(new Uint8Array([0xf0,0x7f,0x7f,0x08,0x02,0x00,0x01,0x69,0x69,0x00,0,0xf7]),t)}
  379. v_i=[];stime=window.performance.now()+200
  380. -a_e[evt_idx][1]*conf.speed*1000;play_next(a_e)},stop:function(){iend=0
  381. timouts.forEach(function(id){clearTimeout(id)})
  382. play_next()
  383. if(op&&op.clear)
  384. op.clear()}}}
  385. function follow(abc,user,playconf){var keep_types={note:true,rest:true}
  386. user.anno_stop=function(type,start,stop,x,y,w,h){if(!keep_types[type])
  387. return
  388. abc.out_svg('<rect class="abcr _'+start+'_" x="');abc.out_sxsy(x,'" y="',y);abc.out_svg('" width="'+w.toFixed(2)+'" height="'+abc.sh(h).toFixed(2)+'"/>\n')}
  389. playconf.onnote=function(i,on){var b,x,y,elts=document.getElementsByClassName('_'+i+'_')
  390. if(elts&&elts[0]){elts[0].style.fillOpacity=on?0.4:0
  391. if(on&&!window.no_scroll){b=elts[0].getBoundingClientRect()
  392. if(b.top<0)
  393. y=window.scrollY+b.top-
  394. window.innerHeight/2
  395. else if(b.bottom>window.innerHeight)
  396. y=window.scrollY+b.bottom+
  397. window.innerHeight/2
  398. if(b.left<0)
  399. x=window.scrollX+b.left-
  400. window.innerWidth/2
  401. else if(b.right>window.innerWidth)
  402. x=window.scrollX+b.right+
  403. window.innerWidth/2
  404. if(x!=undefined||y!=undefined)
  405. window.scrollTo(x||0,y||0)}}}}
  406. (function(){var sty=document.createElement("style")
  407. sty.innerHTML=".abcr {fill: #d00000; fill-opacity: 0; z-index: 15}"
  408. document.head.appendChild(sty)})()