// ParserListener methods public void noteEvent(Note note) { if (layer >= staves) { return; } // System.out.println(note.getMusicString() + " " + note.getMillisDuration() + " " + // note.getDecimalDuration()); Vector<Chord> currChords = chords[layer]; Iterator<NotePanel> currNote = currNotes[layer]; if (!currNote.hasNext()) { System.err.println("Received noteEvent, but no PostScript notes are left"); return; } if (note.getMillisDuration() > 0) { NotePanel notePanel = currNote.next(); // time the last chord ended long tempTime = 0; for (int i = currChords.size() - 1; i >= 0; --i) { if (!currChords.get(i).isTie()) { tempTime = currChords.get(i).getTime() + currChords.get(i).getDuration(); break; } } if (notePanel.isTie) { Chord chord = new Chord(); // for each note in the last chord, set the next note as a tied note for (int i = 0; i < currChords.lastElement().size(); ++i) { notePanel.setTie(true).setTime(Math.min(tempTime, time - 1)).setTempo(tempo); chord.addNote(notePanel); notePanel = currNote.next(); } currChords.add(chord); } while (notePanel.isRest) { notePanel .setTime(Math.min(tempTime, time - 1)) // hack, in case the rest should be trimmed .setTempo(tempo); tempTime += notePanel.getDuration(); Chord chord = new Chord(notePanel); currChords.add(chord); // System.out.println("REST: " + notePanel.getMusicString() + " " + // notePanel.getDuration()); notePanel = currNote.next(); } notePanel.setNote(note).setTime(time).setTempo(tempo); if (currChords.isEmpty() || currChords.lastElement().getTime() != time) { Chord chord = new Chord(notePanel); currChords.add(chord); } else { currChords.lastElement().addNote(notePanel); } } }
private void parseMidi() { try { // Allow for alternate file extensions of midi files. File midiFile = new File("data/out/" + name + ".midi"); File altFile = new File("data/out/" + name + ".mid"); if (!midiFile.exists() && altFile.exists()) { midiFile = altFile; } // parse midi Sequence sequence = MidiSystem.getSequence(midiFile); resolution = sequence.getResolution(); for (int i = 0; i < staves; ++i) { currNotes[i] = notes[i].iterator(); } MidiParser parser = new MidiParser(); parser.addParserListener(this); parser.parse(sequence); // initialize any rests trailing at the end for (int i = 0; i < staves; ++i) { Vector<Chord> currChords = chords[i]; Iterator<NotePanel> currNote = currNotes[i]; long tempTime = 0; for (int j = currChords.size() - 1; j >= 0; --j) { if (!currChords.get(j).isTie()) { tempTime = currChords.get(j).getTime() + currChords.get(j).getDuration(); break; } } while (currNote.hasNext()) { NotePanel notePanel = currNote.next(); if (notePanel.getNote() != null) { notePanel.setTime(tempTime).setTempo(tempo); tempTime += notePanel.getDuration(); Chord chord = new Chord(notePanel); currChords.add(chord); } } } // attach staff lines for (int layer = 0; layer < staves; ++layer) { NotePanel prevNote = null; for (Chord chord : chords[layer]) { for (NotePanel note : chord.notes) { double staffLine = 0.0; for (double line : staffLines.get(layer).get(note.page - 1)) { if (staffLine < 0.0001 || Math.abs(staffLine - note.y) > Math.abs(line - note.y)) { staffLine = line; } } if (prevNote != null) { if (Math.abs(staffLine - prevNote.staffLine) > 0.001) { // either reached the end of the line, or the note is really high/low // make a hacky guess if the note is really high/low, // and if so, set its staffline equal to the previous note's if (prevNote.x < note.x + 1.0) { note.setStaffLine(prevNote.staffLine); prevNote = note; continue; } } } note.setStaffLine(staffLine); prevNote = note; } } } } catch (Exception e) { System.err.println("Parsing the score from Lilypond's output has failed. Error: "); e.printStackTrace(); } }
private void parsePostScript() { try { BufferedReader PSIn = new BufferedReader(new FileReader("data/out/" + name + ".ps")); // parse header while (PSIn.ready()) { String S = PSIn.readLine().trim(); if (S.contains("EndSetup")) { break; } else { if (S.startsWith("/magfont")) { fontInfo.add(S); } else if (S.startsWith("/lily-output-units")) { outputUnits = Float.parseFloat(S.split(" ")[1]); for (String T : fontInfo) { addFont( T.split(" ")[0].substring(1), T.split(" ")[2].substring(1), (float) outputUnits * Float.parseFloat(T.split(" ")[3])); } } else if (S.startsWith("/output-scale")) { outputScale = Float.parseFloat(S.split(" ")[1]); } else if (S.startsWith("/staff-height")) { staffLineHeight = Float.parseFloat(S.split(" ")[1]) / 4; } } } scale = outputUnits * outputScale; for (int layer = 0; layer < staves; ++layer) { Vector<Vector<Double>> staff = new Vector<Vector<Double>>(); for (int page = 0; page < pages; ++page) { staff.add(new Vector<Double>()); } staffLines.add(staff); } Vector<Double> cStaffs = new Vector<Double>(); String prevLine = ""; int currPage = 1; // parse the rest of the file while (PSIn.ready()) { String S = PSIn.readLine().trim(); if (S.contains("noteheads") || S.contains("rests")) { // extract coordinate, glyph, and font information String T[] = S.split(" "); NotePanel N = new NotePanel(); N.setCoordinates(Double.parseDouble(T[0]), -Double.parseDouble(T[1])) .setGlyph(T[4].substring(1)) .setGonville(fonts.get(T[3])); if (S.contains("rests")) { T = S.substring(S.lastIndexOf("rests")).split("[. ]"); N.setRest(Integer.parseInt(T[1])); } T = prevLine.substring(prevLine.lastIndexOf(this.name + ".ly")).split(":"); N.setLine(Integer.parseInt(T[1]), Integer.parseInt(T[2])).setPage(currPage); if (N.lyLine < staffLine || staffLine == 0) { notes[0].add(N); } else { notes[1].add(N); } } else if (S.contains("accidentals")) { // String T[] = S.split(" "); // lastNote.setAccidentals(Double.parseDouble(T[0]), -Double.parseDouble(T[1]), // T[4].substring(1), T[3]); } else if (S.startsWith("%%Page:")) { currPage = Integer.parseInt(S.split(" ")[1]); } if (S.contains("draw_line")) { cStaffs.add(-Double.parseDouble(S.split(" ")[1])); if (cStaffs.size() >= 5 * staves) { // found a full staff Collections.sort(cStaffs); staffLines.get(0).get(currPage - 1).add(cStaffs.get(4) + staffLineHeight); if (staves > 1) { staffLines.get(1).get(currPage - 1).add(cStaffs.get(5) - staffLineHeight); } cStaffs.clear(); } } else if (!S.contains("draw_round_box")) { cStaffs.clear(); } if (S.contains(this.name + ".ly")) { prevLine = S; } } // sort the notes we found from the PS by where they occurred in the .ly for (int i = 0; i < staves; ++i) { Collections.sort(notes[i]); } // find tied notes for (int i = 0; i < staves; ++i) { int cTie = 0; int cNote = 0; while (cTie < ties.size() && cNote < notes[i].size() - 1) { ArrayList<Integer> tie = ties.get(cTie); NotePanel prevNote = notes[i].get(cNote); NotePanel nextNote = notes[i].get(cNote + 1); if (pairComp(tie.get(0), tie.get(1), prevNote.lyLine, prevNote.lyNumber) != -1 && pairComp(tie.get(0), tie.get(1), nextNote.lyLine, nextNote.lyNumber) != 1) { // tie is located between these notes nextNote.setTie(true); ++cNote; ++cTie; } else if (pairComp(tie.get(0), tie.get(1), prevNote.lyLine, prevNote.lyNumber) != -1) { ++cNote; } else { ++cTie; } } } PSIn.close(); } catch (Exception e) { System.err.println("Parsing the score from Lilypond's output has failed. Error: "); e.printStackTrace(); } }