1 2 /* 3 4 This program interprets melodic lines given in ABC notation as a 5 chromesthete might. 6 A Pitch class will be defined, and will take center stage in the 7 processing. 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 * 13 * For this first version of the program, the duration will be held 14 * constant at 1 beat. 15 * Three sorts of images will appear on the screen, the chromesthetic 16 * output box, a text input box, and an error message box. Simplicity 17 * of design is rendered by permitting only one box to be on the screen 18 * at a time. 19 * 20 * ABC represents notes in a manner consistent with these examples: 21 * C, D, E, C D E c d e 22 * 23 * Google ABC music representation if you would like to know more about it. 24 */ 25 package chromesthesia1; 26 import java.util.Scanner; 27 import javax.swing.JOptionPane; 28 import javax.swing.SwingUtilities; 29 import painter.SPainter; 30 31 public class chromesthesia1 { 32 // INFRASTRUCTURE FOR THE PROGRAM -- LAUNCHING A "GRAPHICS" THREAD 33 34 public static void main(String[] args) { 35 SwingUtilities.invokeLater(new ThreadForGUI()); 36 } 37 38 private static class ThreadForGUI implements Runnable { 39 @Override 40 public void run() { 41 new chromesthesia1(); 42 } 43 } 44 45 public chromesthesia1() { 46 interpreter(); 47 } 48 49 // FEATURED VARIABLES 50 private static SPainter miro; 51 private static Pitch1[] pitch1s; 52 53 // THE INTERPRETER 54 public static void interpreter() { 55 initialization(); // miro and pitches 56 while ( true ) { 57 String input = getInput(); 58 if ( input.equalsIgnoreCase("EXIT") ) { 59 break; 60 } else { 61 try { 62 playMelody(input, pitch1s); 63 } catch (Exception ex) { 64 showErrorMessage(ex.toString()); 65 } 66 } 67 } 68 cleanup(); // miro has to go 69 70 } 71 72 // METHODS PERTAINING TO THE CHROMESTHETIC PITCHES 73 private static Pitch1[] establishPitches(SPainter painter) { 74 Pitch1[] pitch1s = new Pitch1[21]; 75 Pitch1 pitch1MiddleC = new Pitch1("C",painter); 76 pitch1s[0] = pitch1MiddleC; 77 Pitch1 pitch1LowC = new Pitch1("C,",painter); 78 pitch1s[1] = pitch1LowC; 79 Pitch1 pitch1HighC = new Pitch1("c",painter); 80 pitch1s[2] = pitch1HighC; 81 Pitch1 pitch1MiddleD = new Pitch1("D",painter); 82 pitch1s[3] = pitch1MiddleD; 83 Pitch1 pitch1LowD = new Pitch1("D,",painter); 84 pitch1s[4] = pitch1LowD; 85 Pitch1 pitch1HighD = new Pitch1("d",painter); 86 pitch1s[5] = pitch1HighD; 87 Pitch1 pitch1MiddleE = new Pitch1("E",painter); 88 pitch1s[6] = pitch1MiddleE; 89 Pitch1 pitch1LowE = new Pitch1("E,",painter); 90 pitch1s[7] = pitch1LowE; 91 Pitch1 pitch1HighE = new Pitch1("e",painter); 92 pitch1s[8] = pitch1HighE; 93 Pitch1 pitch1MiddleF = new Pitch1("F",painter); 94 pitch1s[9] = pitch1MiddleF; 95 Pitch1 pitchLowF = new Pitch1("F,",painter ); 96 pitch1s[10] = pitchLowF; 97 Pitch1 pitchHighF = new Pitch1("f",painter ); 98 pitch1s[11] = pitchHighF; 99 Pitch1 pitch1MiddleG = new Pitch1("G",painter); 100 pitch1s[12] = pitch1MiddleG; 101 Pitch1 pitchLowG = new Pitch1("G,",painter ); 102 pitch1s[13] = pitchLowG; 103 Pitch1 pitchHighG = new Pitch1("g",painter ); 104 pitch1s[14] = pitchHighG; 105 Pitch1 pitch1MiddleA = new Pitch1("A",painter); 106 pitch1s[15] = pitch1MiddleA; 107 Pitch1 pitchLowA = new Pitch1("A,",painter ); 108 pitch1s[16] = pitchLowA; 109 Pitch1 pitchHighA = new Pitch1("a",painter ); 110 pitch1s[17] = pitchHighA; 111 Pitch1 pitch1MiddleB = new Pitch1("B",painter); 112 pitch1s[18] = pitch1MiddleB; 113 Pitch1 pitchLowB = new Pitch1("B,",painter ); 114 pitch1s[19] = pitchLowB; 115 Pitch1 pitchHighB = new Pitch1("b",painter ); 116 pitch1s[20] = pitchHighB; 117 118 return pitch1s; 119 } 120 121 private static Pitch1 find(String token, Pitch1[] pitch1s) throws Exception { 122 for (int i = 0; i < pitch1s.length; i = i + 1 ) { 123 Pitch1 pitch1 = pitch1s[i]; 124 if ( pitch1.abcName().equals(token) ) { 125 return pitch1; 126 } 127 } 128 throw new Exception("### PITCH " + token + " NOT FOUND"); 129 } 130 private static void display(Pitch1[] pitch1s) { 131 for (int i = 0; i < pitch1s.length; i = i + 1) { 132 System.out.println(pitch1s[i].toString()); 133 } 134 } 135 private static void playMelody(String input, Pitch1[] pitch1s) throws Exception { 136 Scanner scanner = new Scanner(input); 137 while ( scanner.hasNext() ) { 138 String token = scanner.next(); 139 Pitch1 pitch1 = find(token, pitch1s); 140 pitch1.play("1"); 141 } 142 } 143 144 // INITIALIZATION, CLEANUP, GETTING INPUT, ERROR MESSAGING 145 static private void showErrorMessage(String message) { 146 miro.setVisible(false); 147 JOptionPane.showMessageDialog(null, message); 148 } 149 150 private static void initialization() { 151 // ESTABLISH THE PAINTER AND GIVE IT A SUBSTANTIAL BRUSH WIDTH 152 miro = new SPainter("Chromesthesia",500,500); 153 miro.setVisible(false); 154 miro.setBrushWidth(7); 155 // ESTABLISH THE CHROMESTITIC PITCH CLASS OBJECTS 156 pitch1s = establishPitches(miro); 157 display(pitch1s); 158 } 159 private static String getInput() { 160 miro.setVisible(false); 161 String label = "Please enter a melody in ABC notation, or EXIT ... "; 162 String input = JOptionPane.showInputDialog(null,label); 163 miro.setVisible(true); 164 if ( input == null ) { input = ""; } 165 return input; 166 } 167 static private void cleanup() { 168 System.exit(0); 169 } 170 } 171