# HG changeset patch # User Daniel O'Connor # Date 1462264481 -34200 # Node ID ea98c9507f477c47839aa1f74b3a1ba75273a375 # Parent f46cc9401e795690774bf14f456b5998299bac28 Preliminary multi-page support. Breaks time marks though. diff -r f46cc9401e79 -r ea98c9507f47 musiccutter.py --- a/musiccutter.py Tue May 03 09:10:33 2016 +0930 +++ b/musiccutter.py Tue May 03 18:04:41 2016 +0930 @@ -25,7 +25,7 @@ m.processMidi(filename, base + '-%02d.pdf') class Midi2PDF(object): - def __init__(self, notefile, pagewidth, pageheight, pitch, slotsize, heel, leadin, timemarks, trytranspose, drawrect, notenames, notelines, noteoffset, timescale, notescale, fontname, fontsize): + def __init__(self, notefile, pagewidth, pageheight, pitch, slotsize, heel, leadin, timemarks, trytranspose, drawrect, notenames, notelines, noteoffset, pagesperpdf, timescale, notescale, fontname, fontsize): self.midi2note, self.note2midi = Midi2PDF.genmidi2note() self.note2slot, self.slot2note = Midi2PDF.loadnote2slot(notefile, self.note2midi) self.pagewidth = pagewidth # Dimensions are in millimetres @@ -40,11 +40,14 @@ self.notenames = notenames # Draw note names on the right edge self.notelines = notelines # Draw line rulers self.noteoffset = noteoffset # Amount to adjust note pitches by (+12 = 1 octave) + self.pagesperpdf = pagesperpdf # Number of pages to emit per PDF self.timescale = timescale # Width per second self.notescale = notescale # Multiply all note lengths by this (to get rearticulation) self.fontname = fontname self.fontsize = fontsize # Points + self.pdfwidth = self.pagewidth * self.pagesperpdf + def processMidi(self, midifile, outpat): playablecount = 0 unplayablecount = 0 @@ -57,10 +60,13 @@ channels.append({}) npages = int(math.ceil(((midi.length * self.timescale) + self.leadin) / self.pagewidth)) - print 'npages', npages + npdfs = int(math.ceil(float(npages) / self.pagesperpdf)) + print 'npages %d, npdfs %d' % (npages, npdfs) + pdfs = [] - for i in range(npages): - pdf = reportlab.pdfgen.canvas.Canvas(file(outpat % (i + 1), 'w'), pagesize = (self.pagewidth * mm, self.pageheight * mm)) + for i in range(npdfs): + pdf = reportlab.pdfgen.canvas.Canvas(file(outpat % (i + 1), 'w'), + pagesize = (self.pdfwidth * mm, self.pageheight * mm)) pdfs.append(pdf) title = os.path.basename(midifile) @@ -126,21 +132,27 @@ print 'Transpose down:', transposedowncount print 'Transpose up:', transposeupcount - for pindx in range(len(pdfs)): - pdf = pdfs[pindx] + for pindx in range(npages): + pdf = pdfs[pindx / self.pagesperpdf] # PDF for this page + # Offset into PDF where the page starts + pageofs = self.pagewidth * (self.pagesperpdf - (pindx % self.pagesperpdf) - 1) # Add title and page number - Midi2PDF.textHelper(pdf, 0 * mm, 1 * mm, ENGRAVE_COLOUR, True, self.fontname, self.fontsize, '%s (%d / %d)' % (title, pindx + 1, npages)) - + Midi2PDF.textHelper(pdf, pageofs * mm, 1 * mm, + ENGRAVE_COLOUR, True, self.fontname, self.fontsize, + '%s (%d / %d)' % (title, pindx + 1, npages)) + pdf.saveState() pdf.setLineWidth(0) - # Draw time marks + # Draw time marks every 5 seconds if self.timemarks: + pdfidx = pindx / self.pagesperpdf + # Work out start and end times (pdf 1 is special due to leadin) tstart = self.leadin / self.timescale - tend = self.pagewidth / self.timescale + tend = (self.pagewidth * self.pagesperpdf) / self.timescale if pindx > 0: - tsize = self.pagewidth / self.timescale - tstart = tend + tsize * pindx - tend = tend + tsize * (pindx + 1) + tsize = self.pagewidth / self.timescale # Amount of time per pdf + tstart = tend + tsize * pdfidx + tend = tend + tsize * (pdfidx + 1) for s in range(tstart, tend, 5): x = self.pagewidth - (float(s * self.timescale + self.leadin) % self.pagewidth) pdf.line(x * mm, self.heel, x * mm, self.pageheight * mm) @@ -148,18 +160,19 @@ # Draw rectangle around page (upper and right hand ends don't seem to render though) if self.drawrect: - pdf.rect(0, 0, self.pagewidth * mm, self.pageheight * mm, fill = False, stroke = True) + pdf.rect((pindx % self.pagesperpdf) * self.pagewidth * mm, 0, + self.pagewidth * mm, self.pageheight * mm, fill = False, stroke = True) # Draw lines per note for slot in sorted(self.slot2note.keys()): ofs = self.pageheight - (self.heel + slot * self.pitch) - self.slotsize / 2 if self.notelines: - pdf.line(0, ofs * mm, self.pagewidth * mm, ofs * mm) + pdf.line(0, ofs * mm, self.pdfwidth * mm, ofs * mm) # Note name if self.notenames: - Midi2PDF.textHelper(pdf, (self.pagewidth - 10) * mm, (ofs + 0.5) * mm, ENGRAVE_COLOUR, False, self.fontname, self.fontsize, self.slot2note[slot]) - - # Save PDF + Midi2PDF.textHelper(pdf, (self.pdfwidth - 10) * mm, (ofs + 0.5) * mm, ENGRAVE_COLOUR, False, self.fontname, self.fontsize, self.slot2note[slot]) + pdf.restoreState() + for pdf in pdfs: pdf.save() # http://newt.phys.unsw.edu.au/jw/notes.html @@ -198,24 +211,24 @@ def emitnote(self, pdfs, slot, start, notelen): x = start * self.timescale + self.leadin # Convert start time to distance - pageidx = int(x / self.pagewidth) # Determine which page - x = x % self.pagewidth # and where on that page + pdfidx = int(x / self.pdfwidth) # Determine which pdf + x = x % self.pdfwidth # and where on that pdf h = self.slotsize y = self.pageheight - (self.heel + slot * self.pitch - self.slotsize / 2) - self.slotsize w = notelen * self.timescale # Convert note length in time to distance - print 'page = %d x = %.3f y = %.3f w = %.3f h = %.3f' % (pageidx, x, y, w, h) + print 'pdf = %d x = %.3f y = %.3f w = %.3f h = %.3f' % (pdfidx, x, y, w, h) w1 = w - # Check if the note crosses a page - if x + w > self.pagewidth: - w1 = self.pagewidth - x # Crop first note + # Check if the note crosses a pdf + if x + w > self.pdfwidth: + w1 = self.pdfwidth - x # Crop first note w2 = w - w1 # Calculate length of second note - assert w2 <= self.pagewidth, 'note extends for more than a page' + assert w2 <= self.pdfwidth, 'note extends for more than a pdf' # Emit second half of note - print 'split note, page %d w2 = %.3f' % (pageidx + 1, w2) - Midi2PDF._emitnote(pdfs[pageidx + 1], self.pagewidth - w2, y, w2, h) + print 'split note, pdf %d w2 = %.3f' % (pdfidx + 1, w2) + Midi2PDF._emitnote(pdfs[pdfidx + 1], self.pdfwidth - w2, y, w2, h) - Midi2PDF._emitnote(pdfs[pageidx], self.pagewidth - x - w1, y, w1, h) + Midi2PDF._emitnote(pdfs[pdfidx], self.pdfwidth - x - w1, y, w1, h) @staticmethod def _emitnote(pdf, x, y, w, h):