smallpond

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/smallpond
Log | Files | Refs | README | LICENSE

commit fce96243d55d851f67c8d769ae6e7c98f9dddc82
parent 2eea7ea8b215fa2a994c6246398cf6baf48c8f62
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Mon,  7 Nov 2022 19:44:54 -0600

grace notes

Diffstat:
Mmain.c | 3++-
Msmallpond.lua | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
2 files changed, 79 insertions(+), 23 deletions(-)

diff --git a/main.c b/main.c @@ -82,6 +82,7 @@ draw_quad(lua_State *L) int draw_glyph(lua_State *L) { + double size = lua_tonumber(L, -4); unsigned int val = lua_tonumber(L, -3); double x = lua_tonumber(L, -2); double y = lua_tonumber(L, -1); @@ -90,7 +91,7 @@ draw_glyph(lua_State *L) cairo_glyph_t glyph = {index, x, y}; cairo_set_font_face(cr, cface); - cairo_set_font_size(cr, 32.0); + cairo_set_font_size(cr, size); cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); cairo_show_glyphs(cr, &glyph, 1); diff --git a/smallpond.lua b/smallpond.lua @@ -155,6 +155,7 @@ local commands = { goto start end + -- barline local s, e = string.find(text, "^|", i) if s then i = i + e - s + 1 @@ -162,6 +163,24 @@ local commands = { goto start end + -- grace (untimed precursor) + local s, e = string.find(text, "^%b{}", i) + if s then + local notes = {} + -- TODO: deal with notegroups + i = i + 1 + while i <= e - 1 do + i = i + #(string.match(text, "^%s*", i) or "") + if i >= #text then return i end + i, note = parsenote(text, i) + i, col = parsenotecolumn(text, i) + table.insert(voice, {command="newnotegroup", count=col.count, stemdir=col.stemdir, beam=col.beam, dot=col.dot, grace=true, notes={[1] = note}}) + end + i = e + 1 + goto start + end + + -- note column local s, e = string.find(text, "^%b<>", i) if s then i = i + 1 @@ -268,7 +287,13 @@ local dispatch1 = { incr = incr + (1 / (2*data.count)) end - local note = {kind="notecolumn", beamcount=beamcount, stemdir=data.stemdir, stemlen=3.5, dot=data.dot, count=incr, length=data.count, time=maxtime, heads=heads} + local stemlen + if data.grace then + stemlen = 2.5 + else + stemlen = 3.5 + end + local note = {kind="notecolumn", beamcount=beamcount, stemdir=data.stemdir, stemlen=stemlen, dot=data.dot, grace=data.grace, count=incr, length=data.count, time=maxtime, heads=heads} if data.beam == 1 then assert(inbeam == 0) inbeam = 1 @@ -281,9 +306,14 @@ local dispatch1 = { note.beamed = inbeam end table.insert(staff1[curname], note) - table.insert(timings[time].staffs[curname].on, note) + + if note.grace then + table.insert(timings[time].staffs[curname].pre, note) + else + table.insert(timings[time].staffs[curname].on, note) + time = time + incr + end lastnote = note - time = time + incr end, changeclef = function(data) local class = assert(Clef[data.kind]) @@ -312,7 +342,7 @@ local dispatch1 = { srest = function(data) table.insert(staff1[curname], {kind='srest', length=data.count, time=time}) time = time + 1 / data.count - end + end, } for _, voice in ipairs(voices) do @@ -365,7 +395,7 @@ function trybeam(staffname, tobeam, beampattern) table.insert(staff, note) end end - local beam = {kind='beam', notes=tobeam, pattern=beampattern, stemdir=stemdir, maxbeams=math.max(table.unpack(beampattern))} + local beam = {kind='beam', notes=tobeam, grace=tobeam[1].grace, pattern=beampattern, stemdir=stemdir, maxbeams=math.max(table.unpack(beampattern))} table.insert(staff, beam) tobeam[#tobeam].beamref = beam elseif #tobeam == 1 then @@ -414,6 +444,12 @@ end local staff3ify = function(timing, el, staff) local xdiff if el.kind == "notecolumn" then + local glyphsize + if el.grace then + glyphsize = 24 + else + glyphsize = 32 + end local rx = x xdiff = 10 rx = rx + xdiff @@ -445,17 +481,17 @@ local staff3ify = function(timing, el, staff) local ry = (em*head.y) / 2 + 2*em if not lowheight then lowheight = ry end if not highheight then highheight = ry end - table.insert(staff3[staff], {kind="glyph", glyph=glyph, x=preoffset + rx, y=ry, time={start=head.time}}) + table.insert(staff3[staff], {kind="glyph", size=glyphsize, glyph=glyph, x=preoffset + rx, y=ry, time={start=head.time}}) if el.dot then xdiff = xdiff + 5 table.insert(staff3[staff], {kind="circle", r=1.5, x=preoffset + rx + w + 5, y=ry, time={start=head.time}}) end if head.acc == "s" then - table.insert(staff3[staff], {kind="glyph", glyph=Glyph["accidentalSharp"], x=rx, y=ry, time={start=head.time}}) + table.insert(staff3[staff], {kind="glyph", size=glyphsize, glyph=Glyph["accidentalSharp"], x=rx, y=ry, time={start=head.time}}) elseif head.acc == "f" then - table.insert(staff3[staff], {kind="glyph", glyph=Glyph["accidentalFlat"], x=rx, y=ry, time={start=head.time}}) + table.insert(staff3[staff], {kind="glyph", size=glyphsize, glyph=Glyph["accidentalFlat"], x=rx, y=ry, time={start=head.time}}) elseif head.acc == "n" then - table.insert(staff3[staff], {kind="glyph", glyph=Glyph["accidentalNatural"], x=rx, y=ry, time={start=head.time}}) + table.insert(staff3[staff], {kind="glyph", size=glyphsize, glyph=Glyph["accidentalNatural"], x=rx, y=ry, time={start=head.time}}) end lowheight = math.min(lowheight, ry) @@ -510,11 +546,11 @@ local staff3ify = function(timing, el, staff) if el.length == 8 and el.beamed == 0 then if el.stemdir == 1 then local fx, fy = glyph_extents(Glyph["flag8thDown"]) - table.insert(staff3[staff], {kind="glyph", glyph=Glyph["flag8thDown"], x=preoffset + rx, y=highheight + 3.5*em, time={start=el.time}}) + table.insert(staff3[staff], {kind="glyph", glyph=Glyph["flag8thDown"], size=glyphsize, x=preoffset + rx, y=highheight + 3.5*em, time={start=el.time}}) else -- TODO: move glyph extents to a precalculated table or something local fx, fy = glyph_extents(Glyph["flag8thUp"]) - table.insert(staff3[staff], {kind="glyph", glyph=Glyph["flag8thUp"], x=el.stemx - .48, y=lowheight -.168*em - 3.5*em, time={start=el.time}}) + table.insert(staff3[staff], {kind="glyph", glyph=Glyph["flag8thUp"], size=glyphsize, x=el.stemx - .48, y=lowheight -.168*em - 3.5*em, time={start=el.time}}) xdiff = xdiff + fx end end @@ -523,6 +559,14 @@ local staff3ify = function(timing, el, staff) elseif el.kind == "srest" then xdiff = 0 elseif el.kind == "beam" then + local beamheight, beamspace + if el.grace then + beamheight = 3 + beamspace = 5 + else + beamheight = 5 + beamspace = 7 + end local m = (el.notes[#el.notes].stemy - el.notes[1].stemy) / (el.notes[#el.notes].stemx - el.notes[1].stemx) local x0 = el.notes[1].stemx local y0 = el.notes[1].stemy @@ -536,21 +580,21 @@ local staff3ify = function(timing, el, staff) local first, last, inc if el.stemdir == 1 then - first = 7*(el.maxbeams - 2) - last = 7*(el.maxbeams - n - 1) - el.notes[i].stem.y2 = y0 + m*(x2 - x0) + 7*(el.maxbeams - 2) + 5 - inc = -7 + first = beamspace*(el.maxbeams - 2) + last = beamspace*(el.maxbeams - n - 1) + el.notes[i].stem.y2 = y0 + m*(x2 - x0) + 7*(el.maxbeams - 2) + beamheight + inc = -beamspace else el.notes[i].stem.y2 = y0 + m*(x2 - x0) first = 0 - last = 7*(n-1) - inc = 7 + last = beamspace*(n-1) + inc = beamspace end for yoff=first, last, inc do local starttime, stoptime if el.notes[i].time then stoptime = el.notes[i].time + .25 else stoptime = nil end if el.notes[i].time then starttime = el.notes[i-1].time + .25 else starttime = nil end - table.insert(staff3[staff], {kind="vshear", x1=x1 - 0.5, x2=x2, y1=y0 + m*(x1 - x0) + yoff, x2=x2, y2=y0 + m*(x2 - x0) + yoff, h=5, time={start=starttime, stop=stoptime}}) + table.insert(staff3[staff], {kind="vshear", x1=x1 - 0.5, x2=x2, y1=y0 + m*(x1 - x0) + yoff, x2=x2, y2=y0 + m*(x2 - x0) + yoff, h=beamheight, time={start=starttime, stop=stoptime}}) end ::continue:: end @@ -601,6 +645,17 @@ for _, time in ipairs(points) do for staff, vals in pairs(todraw) do if #vals.on == 0 then goto nextstaff end + for _, el in ipairs(vals.pre) do + local diff = staff3ify(time, el, staff) + if el.beamref then staff3ify(time, el.beamref, staff) end + x = x + diff + end + ::nextstaff:: + end + xdiff = 0 + + for staff, vals in pairs(todraw) do + if #vals.on == 0 then goto nextstaff end local diff for _, el in ipairs(vals.on) do diff = staff3ify(time, el, staff) @@ -746,8 +801,8 @@ for staff, item in ipairs(extra3) do end function drawframe(time) - local toff = -50*time - if time > 15 then + local toff = -90*time + if time > 30 then return true end @@ -757,7 +812,7 @@ function drawframe(time) if not d.time.start then goto continue end if d.time.start < time then if d.kind == "glyph" then - draw_glyph(d.glyph, toff + d.x - extent.xmin, d.y - extent.ymin + extent.yoff) + draw_glyph(d.size, d.glyph, toff + d.x - extent.xmin, d.y - extent.ymin + extent.yoff) elseif d.kind == "line" then local delta = (time - d.time.start) / (d.time.stop - d.time.start) local endx, endy @@ -787,7 +842,7 @@ function drawframe(time) else endy = math.max(d.y1 + delta*(d.y2 - d.y1), d.y2) end - draw_quad(toff + d.x1 - extent.xmin, d.y1 - extent.ymin + extent.yoff, toff + endx - extent.xmin, endy - extent.ymin + extent.yoff, toff + endx - extent.xmin, endy + 5 - extent.ymin + extent.yoff, toff + d.x1 - extent.xmin, d.y1 + 5 - extent.ymin + extent.yoff) + draw_quad(toff + d.x1 - extent.xmin, d.y1 - extent.ymin + extent.yoff, toff + endx - extent.xmin, endy - extent.ymin + extent.yoff, toff + endx - extent.xmin, endy + d.h - extent.ymin + extent.yoff, toff + d.x1 - extent.xmin, d.y1 + d.h - extent.ymin + extent.yoff) elseif d.kind == "quad" then draw_quad(toff + d.x1 - extent.xmin, d.y1 - extent.ymin + extent.yoff, toff + d.x2 - extent.xmin, d.y2 - extent.ymin + extent.yoff, toff + d.x3 - extent.xmin, d.y3 - extent.ymin + extent.yoff, toff + d.x4 - extent.xmin, d.y4 - extent.ymin + extent.yoff) end