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 )