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