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