App-Music-ChordPro

 view release on metacpan or  search on metacpan

lib/ChordPro/res/abc/abc2svg/MIDI-1.js  view on Meta::CPAN

    // build the equal temperament as a b40 float array
    function tb40(qs) {
// b40	  C  D   E   F   G   A   B
//	[ 2, 8, 14, 19, 25, 31, 37 ]
    var	i,
//	      C  G  D  A  E  B ^F ^C ^G ^D ^A ^E ^B^^F^^C^^G^^D^^A^^E^^B
	n1 = [2,25, 8,31,14,37,20, 3,26, 9,32,15,38,21, 4,27,10,33,16,39],
//	      C  F _B _E _A _D _G _C _F__B__E__A__D__G__C__F
	n2 = [0,19,36,13,30, 7,24, 1,18,35,12,29, 6,23, 0,17],
	da = 21 - 3 * qs,		// 21 = 12 (octave) + 9 (A)
	b = new Float32Array(40)

	for (i = 0; i < n1.length; i++)
		b[n1[i]] = (qs * i + da) % 12
	for (i = 1; i <= n2.length; i++)
		b[n2[i]] = 12 - (qs * i - da) % 12
	return b
    } // tb40()

    // do_midi()
    var	n, v, s, maps,
	o, q, n, qs,
	a = parm.split(/\s+/),
	abc = this,
	cfmt = abc.cfmt(),
	curvoice = abc.get_curvoice(),
	parse = abc.get_parse()

	if (curvoice) {
		if (curvoice.ignore)
			return
		if (curvoice.chn == undefined)
			curvoice.chn = curvoice.v < 9 ?
					curvoice.v :
					curvoice.v + 1
	}
	switch (a[1]) {
//	case "bassprog":	// %%MIDI bassprog <#MIDI program> [octave=<n>]
//		break
//	case "bassvol":		// %%MIDI bassvol <volume>
//		break
//	case "beatstring":	// %%MIDI beatstring <string of fmp>
//		break
	case "chordname":	// %%MIDI chordname <list of MIDI pitches>
				// example: %%MIDI chordname m 0 3 7
		if (!cfmt.chord)
			cfmt.chord = {}
		if (!cfmt.chord.names)
			cfmt.chord.names = {}
		cfmt.chord.names[a[2]] = a.slice(3)
		break
	case "chordprog":	// %%MIDI chordprog <#MIDI program> [octave=<n>]
		if (!cfmt.chord)
			cfmt.chord = {}
		cfmt.chord.prog = a[2]
		if (a[3] && a[3].slice(0, 7) == "octave=")
			cfmt.chord.trans = Number(a[3].slice(7))
		break
	case "chordvol":	// %%MIDI chordvol <volume>
		v = Number(a[2])
		if (isNaN(v) || v < 0 || v > 127) {
			abc.syntax(1, abc.errs.bad_val, "%%MIDI chordvol")
			break
		}
		if (!cfmt.chord)
			cfmt.chord = {}
		cfmt.chord.vol = v
		break
//	case "drone":		// %%MIDI drone <#prog> <pit_1> <pit_2> <vol_1> <vol_2>
//				//	default: 70 45 33 80 80
//		break
//	case "droneon":		// %%MIDI droneon
//		break
//	case "droneoff":	// %%MIDI droneoff
//		break
	case "gchord":		// %%MIDI gchord <list of letters and repeat numbers>
//				//	z rest
//				//	c chord
//				//	f fundamental
//				//	b fundamental + chord
//				//	G/H/I/J/K	individual notes starting
//				//		from the lowest note of the chord
//				//	g/h/i/j/k	an octave above these
//				// defaults:
//				//	M:2/4 or 4/4	fzczfzcz
//				//	M:3/4	fzczcz
//				//	M:6/8	fzcfzc
//				//	M:9/8	fzcfzcfzc
		// fall thru
	case "gchordbars":	// %%MIDI gchordbars n
	case "gchordon":	// %%MIDI gchordon
	case "gchordoff":	// %%MIDI gchordoff
		if (!cfmt.chord)
			cfmt.chord = {}
		if (parse.state >= 2
		 && curvoice) {
			s = abc.new_block("midigch")
			s.play = s.invis = 1 //true
			if (a[1][6] == 'o')
				s.on = a[1][7] == 'n'
			else if (a[1][6] == 'b')
				s.gchnb = +a[2]
			else
				s.rhy = a[2]		// chord rhythm
		} else if (a[1][6] == 'o') {
			cfmt.chord.gchon = a[1][7] == 'n'
		} else if (a[1][6] == 'b') {
			cfmt.chord.gchnb = +a[2]
		} else {
			cfmt.chord.rhy = a[2]
		}
		break
	case "channel":
		v = parseInt(a[2])
		if (isNaN(v) || v <= 0 || v > 16) {
			abc.syntax(1, abc.errs.bad_val, "%%MIDI channel")
			break
		}
		v--				// channel range 1..16 => 0..15
			if (parse.state >= 2) {
				s = abc.new_block("midiprog")
				s.play = s.invis = 1 //true
				s.chn = v
			} else {
				abc.set_v_param("channel", v)
			}
		break
	case "drummap":
//fixme: should have a 'MIDIdrum' per voice?
		v = Number(a[3])
		if (isNaN(v)) {
			abc.syntax(1, abc.errs.bad_val, "%%MIDI drummap")
			break
		}
		n = ["C","^C","D","_E","E","F","^F","G","^G","A","_B","B"][v % 12]
		while (v < 60) {
			n += ','
			v += 12
		}
		while (v > 72) {
			n += "'"
			v -= 12
		}
		this.do_pscom("map MIDIdrum " + a[2] + " play=" + n)
		abc.set_v_param("mididrum", "MIDIdrum")
		break
	case "program":
		a.shift()
		v = []
		if (a[2]) {
			v[0] = +a[2]		// program
			v[1] = +a[1]		// channel
		} else {
			v[0] = +a[1]
			v[1] = 0
		}
		if (isNaN(v[0]) || v[0] < 0 || v[0] > 127
		 || (v[1]
		  && (isNaN(v[1]) || v[1] <= 0 || v[1] > 16))) {
			abc.syntax(1, abc.errs.bad_val, "%%MIDI program")
			break
		}
		if (parse.state >= 2) {
			s = abc.new_block("midiprog");
			s.play = s.invis = 1 //true
			s.instr = v[0]
			s.chn = v[1] > 0
				? (v[1] - 1)
				: curvoice.v < 9 ? curvoice.v : curvoice.v + 1
		} else {
			abc.set_v_param("instr", a.slice(1).join(' '))
		}
		break
	case "control":
		n = parseInt(a[2])
		if (isNaN(n) || n < 0 || n > 127) {
			abc.syntax(1, "Bad controller number in %%MIDI")
			break
		}
		v = parseInt(a[3])
		if (isNaN(v) || v < 0 || v > 127) {
			abc.syntax(1, "Bad controller value in %%MIDI")
			break
		}
		if (parse.state >= 2) {
			s = abc.new_block("midictl");
			s.play = s.invis = 1 //true
			s.ctrl = n;
			s.val = v
		} else {
			abc.set_v_param("midictl", a[2] + ' ' + a[3])
		}
		break
	case "temperamentequal":
		n = parseInt(a[2])
		if (isNaN(n) || n < 5 || n > 255) {
			abc.syntax(1, abc.errs.bad_val, "%%MIDI " + a[1])
			return
		}

		// define the Turkish accidentals (53-TET)
		s = abc.get_glyphs()
		if (n == 53
		 && !s.acc12_53) {		// do not redefine the glyphs
// #1
			s.acc12_53 = '<text id="acc12_53" x="-1">&#xe282;</text>'

// #2
			s.acc24_53 = '<text id="acc24_53" x="-1">&#xe282;\
	<tspan x="0" y="-9" style="font-size:9px">2</tspan></text>'

// #3
			s.acc36_53 = '<text id="acc36_53" x="-1">&#xe262;\
	<tspan x="0" y="-9" style="font-size:9px">3</tspan></text>'

// #4
			s.acc48_53 = '<text id="acc48_53" x="-1">&#xe262;</text>'

// #5
			s.acc60_53 = '<g id="acc60_53">\n\
	<text style="font-size:1.1em" x="-1">&#xe282;</text>\n\
	<path class="stroke" stroke-width="1.6" d="M-2 1l7 -2.2"/>\n\
</g>'

// #8
			s.acc96_53 = '<g id="acc96_53">\n\
	<text style="font-size:1.1em" x="-2">&#xe262;</text>\n\
	<path class="stroke" stroke-width="1.6" d="M-2.8 1.4l8.5 -2.8"/>\n\
</g>'

// #9
			s.acc108_53 = '<text id="acc108_53" x="-3">&#xe263;</text>'

// b9
			s["acc-108_53"] = '<text id="acc-108_53" x="-3">&#xe264;</text>'

// b8
			s["acc-96_53"] = '<g id="acc-96_53">\n\
	<text x="-1">&#xe260;</text>\n\
	<path class="stroke" stroke-width="1.3" d="M-3 -7l5 -2m0 3l-5 2"/>\n\
</g>'

// b5
			s["acc-60_53"] = '<text id="acc-60_53" x="-1">&#xe260;</text>'

// b4
			s["acc-48_53"] = '<g id="acc-48_53">\n\
	<text x="-1">&#xe260;</text>\n\
	<path class="stroke" stroke-width="1.3" d="M-3 -5.5l5 -2"/>\n\
</g>'

// b3
			s["acc-36_53"] = '<g id="acc-36_53">\n\
	<text x="-1">&#xe260;\
		<tspan x="0" y="-12" style="font-size:9px">3</tspan></text>\n\
	<path class="stroke" stroke-width="1.3" d="M-3 -5.5l5 -2"/>\n\



( run in 0.517 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )