MIDI-1.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. //MIDI.js-module to handle the%%MIDI parameters
  2. abc2svg.MIDI={do_midi:function(parm){function tb40(qs){var i,n1=[2,25,8,31,14,37,20,3,26,9,32,15,38,21,4,27,10,33,16,39],n2=[0,19,36,13,30,7,24,1,18,35,12,29,6,23,0,17],da=21-3*qs
  3. b=new Float32Array(40)
  4. for(i=0;i<n1.length;i++)
  5. b[n1[i]]=(qs*i+da)%12
  6. for(i=1;i<=n2.length;i++)
  7. b[n2[i]]=12-(qs*i-da)%12
  8. return b}
  9. var n,v,s,maps,o,q,n,qs,a=parm.split(/\s+/),abc=this,cfmt=abc.cfmt(),curvoice=abc.get_curvoice()
  10. if(curvoice){if(curvoice.ignore)
  11. return
  12. if(curvoice.chn==undefined)
  13. curvoice.chn=curvoice.v<9?curvoice.v:curvoice.v+1}
  14. switch(a[1]){case"chordname":if(!cfmt.chord)
  15. cfmt.chord={}
  16. if(!cfmt.chord.names)
  17. cfmt.chord.names={}
  18. cfmt.chord.names[a[2]]=a.slice(3)
  19. break
  20. case"chordprog":if(!cfmt.chord)
  21. cfmt.chord={}
  22. cfmt.chord.prog=a[2]
  23. if(a[3]&&a[3].slice(0,7)=="octave=")
  24. cfmt.chord.trans=Number(a[3].slice(7))
  25. break
  26. case"chordvol":v=Number(a[2])
  27. if(isNaN(v)||v<0||v>127){abc.syntax(1,abc.errs.bad_val,"%%MIDI chordvol")
  28. break}
  29. if(!cfmt.chord)
  30. cfmt.chord={}
  31. cfmt.chord.vol=v/127
  32. break
  33. case"gchordon":case"gchordoff":if(!cfmt.chord)
  34. cfmt.chord={}
  35. if(abc.parse.state>=2&&abc.get_curvoice()){s=abc.new_block("midigch")
  36. s.play=true
  37. s.on=a[1][7]=='n'}else{cfmt.chord.gchon=a[1][7]=='n'}
  38. break
  39. case"channel":v=parseInt(a[2])
  40. if(isNaN(v)||v<=0||v>16){abc.syntax(1,abc.errs.bad_val,"%%MIDI channel")
  41. break}
  42. if(--v!=9){if(abc.parse.state==3){s=abc.new_block("midichn");s.play=true
  43. s.chn=v}else{abc.set_v_param("channel",v)}
  44. break}
  45. abc2svg.MIDI.do_midi.call(abc,"MIDI control 0 1")
  46. abc2svg.MIDI.do_midi.call(abc,"MIDI control 32 0")
  47. break
  48. case"drummap":v=Number(a[3])
  49. if(isNaN(v)){abc.syntax(1,abc.errs.bad_val,"%%MIDI drummap")
  50. break}
  51. n=["C","^C","D","_E","E","F","^F","G","^G","A","_B","B"][v%12]
  52. while(v<60){n+=','
  53. v+=12}
  54. while(v>72){n+="'"
  55. v-=12}
  56. this.do_pscom("map MIDIdrum "+a[2]+" play="+n)
  57. abc.set_v_param("mididrum","MIDIdrum")
  58. break
  59. case"program":if(a[3]!=undefined){abc2svg.MIDI.do_midi.call(abc,"MIDI channel "+a[2])
  60. v=a[3]}else{v=a[2]}
  61. v=parseInt(v)
  62. if(isNaN(v)||v<0||v>127){abc.syntax(1,abc.errs.bad_val,"%%MIDI program")
  63. break}
  64. if(abc.parse.state==3){s=abc.new_block("midiprog");s.play=true
  65. s.instr=v}else{abc.set_v_param("instr",v)}
  66. break
  67. case"control":n=parseInt(a[2])
  68. if(isNaN(n)||n<0||n>127){abc.syntax(1,"Bad controller number in %%MIDI")
  69. break}
  70. v=parseInt(a[3])
  71. if(isNaN(v)||v<0||v>127){abc.syntax(1,"Bad controller value in %%MIDI")
  72. break}
  73. if(abc.parse.state==3){s=abc.new_block("midictl");s.play=true
  74. s.ctrl=n;s.val=v}else{abc.set_v_param("midictl",a[2]+' '+a[3])}
  75. break
  76. case"temperamentequal":n=parseInt(a[2])
  77. if(isNaN(n)||n<5||n>255){abc.syntax(1,abc.errs.bad_val,"%%MIDI "+a[1])
  78. return}
  79. if(n==53){s=abc.get_glyphs()
  80. s.acc12_53='<text id="acc12_53" x="-1">&#xe282;</text>'
  81. s.acc24_53='<text id="acc24_53" x="-1">&#xe282;\
  82. <tspan x="0" y="-10" style="font-size:8px">2</tspan></text>'
  83. s.acc36_53='<text id="acc36_53" x="-1">&#xe262;\
  84. <tspan x="0" y="-10" style="font-size:8px">3</tspan></text>'
  85. s.acc48_53='<text id="acc48_53" x="-1">&#xe262;</text>'
  86. s.acc60_53='<g id="acc60_53">\n\
  87. <text style="font-size:1.2em" x="-1">&#xe282;</text>\n\
  88. <path class="stroke" stroke-width="1.6" d="M-2 1.5l7 -3"/>\n\
  89. </g>'
  90. s["acc-60_53"]='<text id="acc-60_53" x="-1">&#xe260;</text>'
  91. s["acc-48_53"]='<g id="acc-48_53">\n\
  92. <text x="-1">&#xe260;</text>\n\
  93. <path class="stroke" stroke-width="1" d="M-3 -5.5l5 -2"/>\n\
  94. </g>'
  95. s["acc-36_53"]='<g id="acc-36_53">\n\
  96. <text x="-1">&#xe260;\
  97. <tspan x="0" y="-10" style="font-size:8px">3</tspan></text>\n\
  98. <path class="stroke" stroke-width="1" d="M-3 -5.5l5 -2"/>\n\
  99. </g>'
  100. s["acc-24_53"]='<text id="acc-24_53" x="-2">&#xe280;\
  101. <tspan x="0" y="-10" style="font-size:8px">2</tspan></text>'
  102. s["acc-12_53"]='<text id="acc-12_53" x="-2">&#xe280;</text>'}
  103. q=7.019550008653874,o=12
  104. cfmt.nedo=n
  105. qs=((n*q/o+.5)|0)*o/n
  106. if(qs<6.85||qs>7.2)
  107. abc.syntax(0,abc.errs.bad_val,"%%MIDI "+a[1])
  108. cfmt.temper=tb40(qs)
  109. break}},set_vp:function(of,a){var i,item,curvoice=this.get_curvoice()
  110. for(i=0;i<a.length;i++){switch(a[i]){case"channel=":curvoice.chn=a[++i]
  111. break
  112. case"instr=":curvoice.instr=a[++i]
  113. break
  114. case"midictl=":if(!curvoice.midictl)
  115. curvoice.midictl=[]
  116. item=a[++i].split(' ');curvoice.midictl[item[0]]=Number(item[1])
  117. break
  118. case"mididrum=":if(!curvoice.map)
  119. curvoice.map={}
  120. curvoice.map=a[++i]
  121. break}}
  122. of(a)},do_pscom:function(of,text){if(text.slice(0,5)=="MIDI ")
  123. abc2svg.MIDI.do_midi.call(this,text)
  124. else
  125. of(text)},set_hooks:function(abc){abc.do_pscom=abc2svg.MIDI.do_pscom.bind(abc,abc.do_pscom);abc.set_vp=abc2svg.MIDI.set_vp.bind(abc,abc.set_vp)}}
  126. abc2svg.modules.hooks.push(abc2svg.MIDI.set_hooks);abc2svg.modules.MIDI.loaded=true