App-Music-ChordPro

 view release on metacpan or  search on metacpan

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

				if (!s.p_v.ckey.k_drum) {
					for (m = 0; m <= g.nhd; m++) {
						note = g.notes[m]
						if (!note.opit)
							note.opit = note.pit
						note.pit += d
					}
				}
			}
			break
		}
	} // sym_ott()

	// remove the ottava decorations of a symbol
	function deco_rm(s) {
		for (var i = s.a_dd.length; --i >= 0;) {
			if (s.a_dd[i].name.match(/1?[85][vm][ab]/))
				s.a_dd.splice(i, 1)
		}
	} // deco_rm()

	for (s = tsfirst; s; s = s.ts_next) {
		st = s.st
		o = s.ottava
		if (o) {				// some ottava start or stop
			if (o[0]) {
				if (staff_d[st] && !o[1]) {
					sym_ott(s, staff_d[st])
					deco_rm(s)
					continue	// same ottava
				}
			} else if (!staff_d[st]) {
				deco_rm(s)
				continue		// already no ottava
			}
			s1 = s
			while (s1 && !s1.seqst)
				s1 = s1.ts_prev
			if (s1) {			// update the previous symbols
				while (s1 != s) {
					if (s1.st == st) {
						if (o[1])
							sym_ott(s1, -staff_d[st])
						if (o[0])
							sym_ott(s1, -o[0] * 7)
					}
					s1 = s1.ts_next
				}
			}
			if (o[0]) {			// ottava start
				staff_d[st] = -o[0] * 7
			} else {
				staff_d[st] = 0
			}
		}
		if (staff_d[st])
			sym_ott(s, staff_d[st])
	}
}

// expand the multi-rests as needed
function mrest_expand() {
    var	s, s2

	// expand a multi-rest into a set of rest + bar
	function mexp(s) {
	    var	bar, s3, s4, tim, nbar,
		nb = s.nmes,
		dur = s.dur / nb,
		s2 = s.next

		// get the bar (there may be some other symbols before the bar)
		while (s2 && !s2.bar_type)
			s2 = s2.next
		if (!s2)
			return error(1, s, "Lack of bar after multi-measure rest")
		bar = s2
		while (!s2.bar_num)		// get the bar number
			s2 = s2.ts_prev
		nbar = s2.bar_num - s.nmes

		// change the multi-rest into a single rest
		s.type = C.REST
		s.notes[0].dur = s.dur = s.dur_orig = dur
		s.nflags = -2
		s.head = C.FULL
		s.fmr = 1			// full measure rest

		/* add the bar(s) and rest(s) */
		tim = s.time + dur
		s3 = s
		while (--nb > 0) {

			// add the bar
			s2 = clone(bar)
			delete s2.soln
			delete s2.a_gch
			delete s2.a_dd
			delete s2.text
			delete s2.rbstart
			delete s2.rbstop
			lkvsym(s2, s.next)	// before symbol at end of rests

			s2.time = tim
			while (s3.time < tim)
				s3 = s3.ts_next	// bar at end of measure
			if (s3.time == tim)
				while (!s3.bar_type
				    && s3.ts_next && s3.ts_next.time == tim)
					s3 = s3.ts_next
			while (s3 && s3.v < s.v && s3.type == C.BAR)
				s3 = s3.ts_next	// keep in order
			if (s3) {
				if (s3.bar_type)
					s3.seqst = 0 //false
				lktsym(s2, s3)
				if (s3.type == C.BAR)
					delete s3.bar_num
			} else {
				s3 = s
				while (s3.ts_next)
					s3 = s3.ts_next
				s3.ts_next = s2
				s2.ts_prev = s3
				s2.ts_next = null

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

			delete s4.a_gch
			delete s4.part
			if (s2.next) {
				s4.next = s2.next
				s4.next.prev = s4
			} else {
				s4.next = null
			}
			s2.next = s4
			s4.prev = s2
			s4.time = tim

			while (s3 && !s3.dur && s3.time == tim)
				s3 = s3.ts_next
			while (s3 && s3.v < s.v) {
				s3 = s3.ts_next	// keep in order
				if (s3 && s3.seqst)
					break
			}
			if (s3) {
				if (s3.dur)
					s3.seqst = 0 //false
				lktsym(s4, s3)
			} else {
				s3 = s
				while (s3.ts_next)
					s3 = s3.ts_next
				s3.ts_next = s4
				s4.ts_prev = s3
				s4.ts_next = null
			}

			tim += dur
			s = s3 = s4
		}
	} // mexp()

	for (s = tsfirst; s; s = s.ts_next) {
		if (s.type != C.MREST)
			continue
		if (!s.seqst && w_tb[s.ts_prev.type]) {
			s2 = s
		} else {
			s2 = s.ts_next
			while (!s2.seqst) {
				if (s2.type != C.MREST
				 || s2.nmes != s.nmes)
					break
				s2 = s2.ts_next
			}
		}
		if (!s2.seqst) {
			while (s.type == C.MREST) {
				mexp(s)
				s = s.ts_next
			}
		} else {
			s = s2.ts_prev
		}
	}
} // mrest_expand()

// set the clefs (treble or bass) in a 'auto clef' sequence
// return the starting clef type
function set_auto_clef(st, s_start, clef_type_start) {
    var	s, time, s2, s3,
	max = 14,				// "A,"
	min = 18				// "E"

	/* get the max and min pitches in the sequence */
	for (s = s_start; s; s = s.ts_next) {
		if (s.type == C.STAVES && s != s_start)
			break
		if (s.st != st)
			continue
		if (s.type != C.NOTE) {
			if (s.type == C.CLEF) {
				if (s.clef_type != 'a')
					break
				unlksym(s)
			}
			continue
		}
		if (s.notes[0].pit < min)
			min = s.notes[0].pit
		if (s.notes[s.nhd].pit > max)
			max = s.notes[s.nhd].pit
	}

	if (min >= 19					/* upper than 'F' */
	 || (min >= 13 && clef_type_start != 'b'))	/* or 'G,' */
		return 't'
	if (max <= 13					/* lower than 'G,' */
	 || (max <= 19 && clef_type_start != 't'))	/* or 'F' */
		return 'b'

	/* set clef changes */
	if (clef_type_start == 'a') {
		if ((max + min) / 2 >= 16)
			clef_type_start = 't'
		else
			clef_type_start = 'b'
	}
	var	clef_type = clef_type_start,
		s_last = s,
		s_last_chg = null
	for (s = s_start; s != s_last; s = s.ts_next) {
		if (s.type == C.STAVES && s != s_start)
			break
		if (s.st != st || s.type != C.NOTE)
			continue

		/* check if a clef change may occur */
		time = s.time
		if (clef_type == 't') {
			if (s.notes[0].pit > 12		/* F, */
			 || s.notes[s.nhd].pit > 20) {	/* G */
				if (s.notes[0].pit > 20
				 || s.notes[s.nhd].pit > 20)
					s_last_chg = s
				continue

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

				continue
			if (s.rbstop)
				break
			if (!s.next) {
				s.rbstop = 2	// right repeat with end
				break
			}
			n++
			if (n == s.fmt.rbmin)
				s2 = s
			if (n == s.fmt.rbmax) {
				if (s2)
					s = s2;
				s.rbstop = 1	// right repeat without end
				break
			}
		}
	}
}

/* -- initialize the generator -- */
// this function is called only once per tune

var delpit = [0, -7, -14, 0]

function set_global() {
    var	p_voice, v,
	nv = voice_tb.length,
	sy = cur_sy,
	st = sy.nstaff

	insert_meter = cfmt.writefields.indexOf('M') >= 0

	/* get the max number of staves */
	while (1) {
		sy = sy.next
		if (!sy)
			break
		if (sy.nstaff > st)
			st = sy.nstaff
	}
	nstaff = st;

	// there must be a bar at end of tune
	check_end_bar()

	/* set the pitches, the words (beams) and the repeat brackets */
	for (v = 0; v < nv; v++) {
		p_voice = voice_tb[v];
		set_words(p_voice)
		p_voice.ckey = p_voice.key	// starting key
// (test removed because v.second may change after %%staves)
//		if (!p_voice.second && !p_voice.norepbra)
			set_rb(p_voice)
	}

	/* set the staff of the floating voices */
	if (nv > 1) {
		set_float()

	// expand the multi-rests as needed
		if (glovar.mrest_p)
			mrest_expand()
	}

	if (glovar.ottava && cfmt.sound != "play")
		set_ottava();

	// set the clefs and adjust the pitches of all symbol
	set_clefs();
	self.set_pitch(null)
}

// get the left offsets of the first and other staff systems
// return left shift [no name, first music line, other lines
function get_lshift() {
    var	st, v, p_v, p1, po, fnt, w,
	sy = cur_sy,
	lsh = [0, 0, 0],
	nv = voice_tb.length

	// get the max width of a voice name/subname
	function get_wx(p, wx) {
	    var	w, j,
		i = 0

		p += '\n'
		while (1) {
			j = p.indexOf("\n", i)
			if (j < 0)
				break
			w = strwh(p.slice(i, j))[0] + 12
			if (w > wx)
				wx = w
			if (j < 0)
				break
			i = j + 1
		}
		return wx
	} // get_wx()

	for (v = 0; v < nv; v++) {
		p_v = voice_tb[v]
		p1 = p_v.nm
		po = p_v.snm
		if ((p1 || po) && !fnt) {
			set_font("voice")
			fnt = gene.deffont
		}
		if (p1) {
			w = get_wx(p1, lsh[1])
			if (w > lsh[1])
				lsh[1] = w
		}
		if (po) {
			w = get_wx(po, lsh[2])
			if (w > lsh[2])
				lsh[2] = w
		}
	}
	// add the width of the braces/brackets
	w = 0
	while (sy) {

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

			if (s.invis)
				continue
			if (sy.staves[st].staffnonote
			 || s.type == C.NOTE)
				break
			continue
		}
		non_empty_gl[st] = non_empty[st] = true
	}
	tsnext = s;

	/* set the last empty staves */
	set_brace()
	sy.st_print = non_empty

	/* define the offsets of the measure bars */
	set_top_bot()

	// if not the end of the tune, set the end of the music line
	if (tsnext) {
		s = tsnext;
		delete s.nl;
		last = s.ts_prev;
		last.ts_next = null;

		// and the end of the voices
		nv = voice_tb.length
		for (v = 0; v < nv; v++) {
			p_voice = voice_tb[v]
			if (p_voice.sym
			 && p_voice.sym.time <= tsnext.time) {
				for (s = last; s; s = s.ts_prev) {
					if (s.v == v) {
						p_voice.s_next = s.next;
						s.next = null;
						break
					}
				}
				if (s)
					continue
			}
			p_voice.s_next = p_voice.sym;
			p_voice.sym = null
		}
	}

	// initialize the music line
	init_music_line()

	// keep the array of the staves to be printed
	gene.st_print = non_empty_gl
}

/* -- position the symbols along the staff -- */
// (possible hook)
Abc.prototype.set_sym_glue = function(width) {
    var	g, x, some_grace, stretch,
	cnt = 4,
	xmin = 0,		// sigma shrink = minimum spacing
	xx = 0,			// sigma natural spacing
	xs = 0,			// sigma unexpandable elements with no space
	xse = 0,		// sigma unexpandable elements with space
	ll = !tsnext ||		// last line? yes
		(tsnext.type == C.BLOCK	// no, but followed by %%command
		 && !tsnext.play)
		|| blocks.length,	//	(abcm2ps compatibility)
	s = tsfirst,
	spf = 1,		// spacing factor
	xx0 = 0

	/* calculate the whole space of the symbols */
	for ( ; s; s = s.ts_next) {
		if (s.type == C.GRACE && !some_grace)
			some_grace = s
		if (s.seqst) {
			xmin += s.shrink
			if (xmin > width) {
			    if (cfmt.singleline)
				width = xmin
			    else
				error(1, s, "Line too much shrunk $1 $2 $3",
					xmin.toFixed(1),
					xx.toFixed(1),
					width.toFixed(1))
//				break
			}
			if (s.space) {
				if (s.space < s.shrink) {
					xse += s.shrink;
					xx += s.shrink
				} else {
//					xx += s.space * spf + s.shrink * (1 - spf)
					xx += s.space
					xx0 += s.shrink
				}
			} else {
				xs += s.shrink
			}
		}
	}

	// can occur when bar alone in a staff system
	if (!xx) {
		realwidth = 0
		return
	}

	// stretch or not?
	s = tsfirst

	if (ll) {
		if ((xx - xx0 + xs) / width > (1 - s.fmt.stretchlast))
			stretch = 1 //true
	} else if (s.fmt.stretchstaff) {
		stretch = 1 //true
	}

	// strong shrink
	if (xmin >= width) {
		x = 0
		for ( ; s; s = s.ts_next) {
			if (s.seqst)

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

	"\\","|", "n", "n",		/* \ ] ^ _ */
	"i", "n", "n", "n",	 	/* ` a b c */
	"n", "n", "n", "n",	 	/* d e f g */
	"d", "d", "d", "d",		/* h i j k */
	"d", "d", "d", "d",		/* l m n o */
	"d", "d", "d", "d",		/* p q r s */
	"d", "!upbow!",
		"!downbow!", "d",	/* t u v w */
	"n", "n", "n", "{",		/* x y z { */
	"|", "}", "!gmark!", nil,	/* | } ~ (del) */
] // char_tb[]

function parse_music_line() {
	var	grace, last_note_sav, a_dcn_sav, no_eol, s, tps,
		tp = [],
		tpn = -1,
		sls = [],
		line = parse.line

	// check if a transposing macro matches a source sequence
	// if yes return the base note
	function check_mac(m) {
	    var	i, j, b

		for (i = 1, j = line.index + 1; i < m.length; i++, j++) {
			if (m[i] == line.buffer[j])
				continue
			if (m[i] != 'n')		// search the base note
				return //undefined
			b = ntb.indexOf(line.buffer[j])
			if (b < 0)
				return //undefined
			while (line.buffer[j + 1] == "'") {
				b += 7;
				j++
			}
			while (line.buffer[j + 1] == ',') {
				b -= 7;
				j++
			}
		}
		line.index = j
		return b
	} // check_mac()

	// convert a note as a number into a note as a ABC string
	function n2n(n) {
	    var	c = ''

		while (n < 0) {
			n += 7;
			c += ','
		}
		while (n >= 14) {
			n -= 7;
			c += "'"
		}
		return ntb[n] + c
	} // n2n()

	// expand a transposing macro
	function expand(m, b) {
		if (b == undefined)		// if static macro
			return m
	    var	c, i,
		r = "",				// result
		n = m.length

		for (i = 0; i < n; i++) {
			c = m[i]
			if (c >= 'h' && c <= 'z') {
				r += n2n(b + c.charCodeAt(0) - 'n'.charCodeAt(0))
			} else {
				r += c
			}
		}
		return r
	} // expand()

	// parse a macro
	function parse_mac(k, m, b) {
	    var	te, ti, curv, s,
		line_sav = line,
		istart_sav = parse.istart;

		parse.line = line = new scanBuf;
		parse.istart += line_sav.index;

		// if the macro is not displayed
		if (cfmt.writefields.indexOf('m') < 0) {

			// build the display sequence from the original sequence
			line.buffer = k.replace('n', n2n(b))
			s = curvoice.last_sym
			ti = curvoice.time		// start time
			parse_seq(true)
			if (!s)
				s = curvoice.sym
			for (s = s.next ; s; s = s.next)
				s.noplay = true
			te = curvoice.time		// end time
			curv = curvoice

			// and put the macro sequence in a play specific voice
			curvoice = clone_voice(curv.id + '-p')
			if (!par_sy.voices[curvoice.v]) {
				curvoice.second = true
				par_sy.voices[curvoice.v] = {
					st: curv.st,
					second: true,
					range: curvoice.v
				}
			}
			curvoice.time = ti
			s = curvoice.last_sym
			parse.line = line = new scanBuf
			parse.istart += line_sav.index
			line.buffer = expand(m, b)
			parse_seq(true)
			if (curvoice.time != te)
				syntax(1, "Bad length of the macro sequence")
			if (!s)
				s = curvoice.sym
			for ( ; s; s = s.next)
				s.invis = s.play = true
			curvoice = curv
		} else {
			line.buffer = expand(m, b)
			parse_seq(true)
		}

		parse.line = line = line_sav
		parse.istart = istart_sav
	} // parse_mac()

	// parse a music sequence
	function parse_seq(in_mac) {
	    var	c, idx, type, k, s, dcn, i, n, text, note

		while (1) {
			c = line.char()
			if (!c)
				break

			// check if start of a macro
			if (!in_mac && maci[c]) {
				n = undefined
				for (k in mac) {
					if (!mac.hasOwnProperty(k)
					 || k[0] != c)
						continue
					if (k.indexOf('n') < 0) {
						if (line.buffer.indexOf(k, line.index)
								!= line.index)
							continue
						line.index += k.length
					} else {
						n = check_mac(k)
						if (n == undefined)
							continue
					}
					parse_mac(k, mac[k], n)
					n = 1
					break
				}
				if (n)
					continue
			}

			idx = c.charCodeAt(0)
			if (idx >= 128) {
				syntax(1, errs.not_ascii)
				line.index++
				break
			}

			type = char_tb[idx]
			switch (type[0]) {
			case ' ':			// beam break
				s = curvoice.last_note
				if (s) {
					s.beam_end = true
					if (grace)
						grace.gr_shift = true
				}
				break
			case '\n':			// line break
				if (cfmt.barsperstaff)



( run in 1.484 second using v1.01-cache-2.11-cpan-788537b7465 )