package org.myrobotlab.roomba; import java.util.ArrayList; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * */ public class RTTTLParser { public static HashMap<String, Integer> noteToNum; static { noteToNum = new HashMap<String, Integer>(); noteToNum.put("c", new Integer(0)); noteToNum.put("c#", new Integer(1)); noteToNum.put("d", new Integer(2)); noteToNum.put("d#", new Integer(3)); noteToNum.put("e", new Integer(4)); noteToNum.put("f", new Integer(5)); noteToNum.put("f#", new Integer(6)); noteToNum.put("g", new Integer(7)); noteToNum.put("g#", new Integer(8)); noteToNum.put("a", new Integer(9)); noteToNum.put("a#", new Integer(10)); noteToNum.put("b", new Integer(11)); noteToNum.put("h", new Integer(7)); } public static int bpmToMillis(int bpm) { return (60 * 1000) / bpm; } public static void main(String[] args) { if (args.length == 0) { System.out.println("usage: roombacomm.RTTTLParser <rttlstring>"); System.exit(0); } String rtttl = args[0]; ArrayList<Note> notelist = parse(rtttl); for (int i = 0; i < notelist.size(); i++) { System.out.println("notelist[" + i + "]=" + notelist.get(i)); } } public static ArrayList<Note> parse(String rtttl) { System.out.println("parsing: " + rtttl); String rtttl_working = rtttl.toLowerCase(); String parts[] = rtttl_working.split(":"); // String name = parts[0]; String defaults[] = parts[1].split("[,=]"); String notes[] = parts[2].split(","); // global defaults int bpm = 63; int octave = 6; int duration = 4; ArrayList<Note> notelist = new ArrayList<Note>(); for (int i = 0; i < defaults.length; i++) { // System.out.println("defaults["+i+"]="+defaults[i]); if (defaults[i].equals("b")) try { bpm = Integer.parseInt(defaults[i + 1]); } catch (Exception e) { } else if (defaults[i].equals("o")) try { octave = Integer.parseInt(defaults[i + 1]); } catch (Exception e) { } else if (defaults[i].equals("d")) try { duration = Integer.parseInt(defaults[i + 1]); } catch (Exception e) { } } System.out.println("bpm:" + bpm + ",octave:" + octave + ",duration:" + duration); for (int i = 0; i < notes.length; i++) { Matcher m = Pattern.compile("(\\d+)*(.+?)(\\d)*(\\.)*").matcher(notes[i]); m.find(); // group(1) == duration (optional) // group(2) == note (required) // group(3) == scale (optional) // group(4) == triplet (optional) int dur = duration; int oct = octave; if (m.group(1) != null) try { dur = Integer.parseInt(m.group(1)); } catch (Exception e) { } if (m.group(4) != null && m.group(4).equals(".")) dur += dur / 2; if (m.group(3) != null) try { oct = Integer.parseInt(m.group(3)); } catch (Exception e) { } if (m.group(2) != null) { int notenum; if (m.group(2).equals("p")) { notenum = 0; } else { Integer nn = (Integer) noteToNum.get(m.group(2)); notenum = nn.intValue(); notenum = notenum + 12 * oct; } dur = bpmToMillis(bpm) / dur; notelist.add(new Note(notenum, dur)); } } return notelist; } }