/** Reads the given MusicXML document and returns the score. */ public static Score read( MxlScorePartwise doc, Score baseScore, ErrorProcessing err, boolean ignoreErrors) { MusicReaderContext context = new MusicReaderContext(baseScore, new MusicReaderSettings(err, ignoreErrors)); // read the parts int staffIndexOffset = 0; It<MxlPart> mxlParts = it(doc.getParts()); for (MxlPart mxlPart : mxlParts) { // clear part-dependent context values int stavesCount = baseScore.getStavesList().getParts().get(mxlParts.getIndex()).getStavesCount(); context = context.beginNewPart(mxlParts.getIndex()); staffIndexOffset += stavesCount; // read the measures It<MxlMeasure> mxlMeasures = it(mxlPart.getMeasures()); for (MxlMeasure mxlMeasure : mxlMeasures) { try { context = readMeasure(context, mxlMeasure, mxlMeasures.getIndex()); } catch (MusicReaderException ex) { throw new RuntimeException("Error at " + ex.getContext().toString(), ex); } catch (Exception ex) { throw new RuntimeException("Error (roughly) around " + context.toString(), ex); } } } // go through the whole score, and fill empty measures (that means, measures where // voice 0 has no single VoiceElement) with rests Fraction measureDuration = fr(1, 4); for (int iStaff = 0; iStaff < context.getScore().getStavesCount(); iStaff++) { Staff staff = context.getScore().getStaff(atStaff(iStaff)); for (int iMeasure = 0; iMeasure < staff.getMeasures().size(); iMeasure++) { Measure measure = staff.getMeasures().get(iMeasure); Time newTime = context.getScore().getScoreHeader().getColumnHeader(iMeasure).getTime(); if (newTime != null) { // time signature has changed if (newTime instanceof NormalTime) { measureDuration = ((NormalTime) newTime).getBeatsPerMeasure(); } else { measureDuration = fr(1, 4); // default: 1/4 } } Voice voice0 = measure.getVoices().get(0); if (voice0.isEmpty()) { // TODO: "whole rests" or split. currently, also 3/4 rests are possible context = context.withScore( ScoreController.writeVoiceElement( context.getScore(), mp(iStaff, iMeasure, 0, _0), new Rest(measureDuration))); } } } return context.getScore(); }
@Test public void test() { Pitch[] expectedPitches = getExpectedPitches(); int iPitch = 0; Staff staff = getFirstStaff(); for (int iM = 0; iM < staff.getMeasures().size(); iM++) { Measure measure = staff.getMeasures().get(iM); Voice voice = measure.getVoice(0); for (VoiceElement e : voice.getElements()) { if (e instanceof Chord) { // check note and pitch Chord chord = (Chord) e; assertEquals(expectedPitches[iPitch++], chord.getNotes().get(0).getPitch()); } } } // TODO - ignore this test, since MusicXML input file has a bug (only a single measure), // so currently only the first measure is tested // assertEquals("not all notes found", expectedPitches.length, iPitch); }
/** * Creates a score with a single staff, two measures with each two voices, with key changes and * chords with accidentals. */ private Score createTestScoreAccidentals() { // create two measures with two voices: // measure 0 | measure 1 // beat: 0 1 | 0 1 // key: Gmaj | *Fmaj Cmaj // voice 0: C4 | F#4 Bb4 Bb4 // voice 1: Fnat4 | Bb4 F#4 F#4 // (*) is a private key (not in measure column) Score score = ScoreFactory.create1Staff(); new MeasureAdd(score, 1).execute(); new VoiceAdd(score.getMeasure(atMeasure(0, 0)), 1).execute(); new VoiceAdd(score.getMeasure(atMeasure(0, 1)), 1).execute(); // keys new ColumnElementWrite( new TraditionalKey(1, Mode.Major), score.getColumnHeader(0), fr(0, 4), null) .execute(); new MeasureElementWrite( new TraditionalKey(-1, Mode.Major), score.getMeasure(atMeasure(0, 1)), fr(0, 4)) .execute(); new ColumnElementWrite( new TraditionalKey(0, Mode.Major), score.getColumnHeader(1), fr(1, 4), null) .execute(); // measure 0, voice 0 Voice voice = score.getVoice(MP.atVoice(0, 0, 0)); voice.addElement(chord(pi(0, 0, 4), fr(2, 4))); // measure 1, voice 0 voice = score.getVoice(MP.atVoice(0, 1, 0)); voice.addElement(chord(pi(3, 1, 4), fr(1, 4))); voice.addElement(chord(pi(6, -1, 4), fr(1, 8))); voice.addElement(chord(pi(6, -1, 4), fr(1, 8))); // measure 0, voice 1 voice = score.getVoice(MP.atVoice(0, 0, 1)); voice.addElement(chord(pi(3, 0, 4), fr(2, 4))); // measure 1, voice 1 voice = score.getVoice(MP.atVoice(0, 1, 1)); voice.addElement(chord(pi(6, -1, 4), fr(1, 4))); voice.addElement(chord(pi(3, 1, 4), fr(1, 8))); voice.addElement(chord(pi(3, 1, 4), fr(1, 8))); return score; }