/* * Copyright (C) 2013-2014 たんらる */ package fourthline.mmlTools.parser; import java.util.Iterator; import fourthline.mmlTools.MMLEvent; import fourthline.mmlTools.MMLNoteEvent; import fourthline.mmlTools.MMLTempoEvent; import fourthline.mmlTools.core.MMLTokenizer; import fourthline.mmlTools.core.MelodyParser; import fourthline.mmlTools.core.ParserWarn3ML; import fourthline.mmlTools.core.TuningBase; import fourthline.mmlTools.core.UndefinedTickException; public final class MMLEventParser implements Iterator<MMLEvent> { private final MMLTokenizer tokenizer; private final MelodyParser parser; public MMLEventParser(String mml) { tokenizer = new MMLTokenizer(mml); parser = new MelodyParser(mml); } public static int firstNoteNumber(String mml) { MMLEventParser parser = new MMLEventParser(mml); while (parser.hasNext()) { MMLEvent e = parser.next(); if (e instanceof MMLNoteEvent) { return ((MMLNoteEvent)e).getNote(); } } return -1; } private MMLEvent nextItem = null; // MMLパース用 private boolean hasTie = false; private int totalTick = 0; private MMLNoteEvent prevNoteEvent = null; private int volumn = MMLNoteEvent.INIT_VOL; /** * @return すべてMMLパースが終っているときは、nullを返す. */ private MMLEvent parseNextEvent() { while (tokenizer.hasNext()) { String token = tokenizer.next(); char firstC = token.charAt(0); if ( firstC == '&' ) { hasTie = true; continue; } if ( (firstC == 'v') || (firstC == 'V') ) { try { int nextVolumn = Integer.parseInt( token.substring(1) ); if ( (nextVolumn >= 0) && (nextVolumn <= MMLNoteEvent.MAX_VOL) ) { volumn = nextVolumn; } continue; } catch (NumberFormatException e) { e.printStackTrace(); } } if ( (firstC == 't') || (firstC == 'T') ) { try { int tempo = Integer.parseInt( token.substring(1) ); nextItem = new MMLTempoEvent(tempo, totalTick); } catch (IllegalArgumentException e) { continue; } return nextItem; } try { int tick = parser.noteGT(token); if (MMLTokenizer.isNote(firstC)) { /* tie でかつ、同じノートであれば、前のNoteEventにTickを加算する */ if ( (hasTie) && (prevNoteEvent != null) && (prevNoteEvent.getNote() == parser.getNoteNumber())) { int prevTick = prevNoteEvent.getTick(); if ( (prevTick == tick) && (TuningBase.getInstance(tick) != null) ) { prevNoteEvent.setTuningNote(TuningBase.getInstance(tick)); } prevNoteEvent.setTick( prevTick + tick); prevNoteEvent.getIndexOfMMLString()[1] = tokenizer.getIndex()[1]; } else if (parser.getNoteNumber() >= -1) { nextItem = prevNoteEvent; prevNoteEvent = new MMLNoteEvent(parser.getNoteNumber(), tick, totalTick, volumn); prevNoteEvent.setIndexOfMMLString(tokenizer.getIndex()); } hasTie = false; totalTick += tick; if (nextItem != null) { return nextItem; } } } catch (UndefinedTickException | ParserWarn3ML e) { System.err.println(e.getMessage()); } } nextItem = prevNoteEvent; prevNoteEvent = null; return nextItem; } @Override public boolean hasNext() { if (nextItem == null) { parseNextEvent(); } if (nextItem == null) { return false; } else { return true; } } @Override public MMLEvent next() { if (nextItem == null) { return parseNextEvent(); } MMLEvent returnEvent = nextItem; nextItem = null; return returnEvent; } @Override public void remove() { tokenizer.remove(); } }