1 /* 2 * This program interprets melodic lines given in ABC notation as a 3 * chromesthete might. 4 * 5 * A Pitch class will be defined, and will take center stage in the 6 * processing. 7 * 8 * Interpreting a melody in ABC notation will amount to flashing 9 * colored rectangles for prescribed durations, while sounding 10 * the pitch! The color of the rectangle will correspond to pitch 11 * class. The duration will correspond to the duration of the note. 12 130 13 * 14 * For this first version of the program, the duration will be held 15 * constant at 1 beat. 16 * 17 * Three sorts of images will appear on the screen, the chromesthetic 18 * output box, a text input box, and an error message box. Simplicity 19 * of design is rendered by permitting only one box to be on the screen 20 * at a time. 21 * 22 * ABC represents notes in a manner consistent with these examples: 23 * C, D, E, C D E c d e 24 * 25 * Google ABC music representation if you would like to know more about it. 26 */ 27 package chromesthesia0; 28 import java.util.Scanner; 29 import javax.swing.JOptionPane; 30 import javax.swing.SwingUtilities; 31 import painter.SPainter; 32 33 public class Chromesthesia { 34 // INFRASTRUCTURE FOR THE PROGRAM -- LAUNCHING A "GRAPHICS" THREAD 35 public static void main(String[] args) { 36 SwingUtilities.invokeLater(new ThreadForGUI()); 37 } 38 private static class ThreadForGUI implements Runnable { 39 @Override 40 public void run() { 41 new Chromesthesia(); 42 } 43 } 44 public Chromesthesia() { 45 interpreter(); 46 } 47 // FEATURED VARIABLES 48 private static SPainter miro; 49 private static Pitch[] pitches; 50 // THE INTERPRETER 51 public static void interpreter() { 52 initialization(); // miro and pitches 53 while ( true ) { 54 String input = getInput(); 55 if ( input.equalsIgnoreCase("EXIT") ) { 56 break; 57 } else { 58 try { 59 playMelody(input,pitches); 60 } catch (Exception ex) { 61 showErrorMessage(ex.toString()); 62 } 63 } 64 } 65 cleanup(); // miro has to go 66 } 67 // METHODS PERTAINING TO THE CHROMESTHETIC PITCHES 68 private static Pitch[] establishPitches(SPainter painter) { 69 Pitch[] pitches = new Pitch[9]; 70 Pitch pitchMiddleC = new Pitch("C",painter); 71 pitches[0] = pitchMiddleC; 72 Pitch pitchLowC = new Pitch("C,",painter); 73 pitches[1] = pitchLowC; 74 Pitch pitchHighC = new Pitch("c",painter); 75 pitches[2] = pitchHighC; 76 Pitch pitchMiddleD = new Pitch("D",painter); 77 pitches[3] = pitchMiddleD; 78 Pitch pitchLowD = new Pitch("D,",painter); 79 pitches[4] = pitchLowD; 80 Pitch pitchHighD = new Pitch("d",painter); 81 pitches[5] = pitchHighD; 82 Pitch pitchMiddleE = new Pitch("E",painter); 83 pitches[6] = pitchMiddleE; 84 Pitch pitchLowE = new Pitch("E,",painter); 85 pitches[7] = pitchLowE; 86 Pitch pitchHighE = new Pitch("e",painter); 87 pitches[8] = pitchHighE; 88 return pitches; 89 } 90 private static Pitch find(String token, Pitch[] pitches) throws Exception { 91 for ( int i = 0; i < pitches.length; i = i + 1 ) { 92 Pitch pitch = pitches[i]; 93 if ( pitch.abcName().equals(token) ) { 94 return pitch; 95 } 96 } 97 throw new Exception("### PITCH " + token + " NOT FOUND"); 98 } 99 private static void display(Pitch[] pitches) { 100 for ( int i = 0; i < pitches.length; i = i + 1 ) { 101 System.out.println(pitches[i].toString()); 102 } 103 } 104 private static void playMelody(String input, Pitch[] pitches) throws Exception { 105 Scanner scanner = new Scanner(input); 106 while ( scanner.hasNext() ) { 107 String token = scanner.next(); 108 Pitch pitch = find(token,pitches); 109 pitch.play("1"); 110 } 111 } 112 // INITIALIZATION, CLEANUP, GETTING INPUT, ERROR MESSAGING 113 static private void showErrorMessage(String message) { 114 miro.setVisible(false); 115 JOptionPane.showMessageDialog(null, message); 116 } 117 private static void initialization() { 118 // ESTABLISH THE PAINTER AND GIVE IT A SUBSTANTIAL BRUSH WIDTH 119 miro = new SPainter("Chromesthesia",500,500); 120 miro.setVisible(false); 121 miro.setBrushWidth(7); 122 // ESTABLISH THE CHROMESTITIC PITCH CLASS OBJECTS 123 pitches = establishPitches(miro); 124 display(pitches); 125 } 126 private static String getInput() { 127 miro.setVisible(false); 128 String label = "Please enter a melody in ABC notation, or EXIT ... "; 129 String input = JOptionPane.showInputDialog(null,label); 130 miro.setVisible(true); 131 if ( input == null ) { input = ""; } 132 return input; 133 } 134 static private void cleanup() { 135 System.exit(0); 136 } 137 }