Chromesthesia2.java
1    
2    
3            /* 
4             *This program interprets melodic lines given in ABC notation as a 
5             * chromesthete might. 
6             * 
7             * A Pitch class will be defined, and will take center stage in the 
8             * processing. 
9             * 
10            * Interpreting a melody in ABC notation will amount to flashing 
11            * colored rectangles for prescribed durations, while sounding 
12            * the pitch! The color of the rectangle will correspond to pitch 
13            * class. The duration will correspond to the duration of the note. 
14            * 
15            * For this first version of the program, the duration will be held 
16            * constant at 1 beat. 
17            * 
18            * Three sorts of images will appear on the screen, the chromesthetic 
19            * output box, a text input box, and an error message box. Simplicity 
20            * of design is rendered by permitting only one box to be on the screen 
21            * at a time. 
22            * 
23            * ABC represents notes in a manner consistent with these examples: 
24            * C, D, E, C D E c d e 
25            * 
26            * Google ABC music representation if you would like to know more about it 
27            */
28   
29           package chromesthesia2;
30   
31   import java.util.Scanner;
32   import javax.swing.JOptionPane;
33   import javax.swing.SwingUtilities;
34   import painter.SPainter;
35   
36   
37   public class Chromesthesia2 {
38   
39   
40       // INFRASTRUCTURE FOR THE PROGRAM -- LAUNCHING A "GRAPHICS" THREAD
41   
42       public static void main(String[] args) {
43           SwingUtilities.invokeLater(new chromesthesia2.Chromesthesia2.ThreadForGUI());
44       }
45   
46       private static class ThreadForGUI implements Runnable {
47           @Override
48           public void run() {
49               new chromesthesia2.Chromesthesia2();
50           }
51       }
52   
53       public Chromesthesia2() {
54           interpreter();
55       }
56   
57       // FEATURED VARIABLES
58   
59       private static SPainter miro;
60       private static Pitch[] pitches;
61   
62       // THE INTERPRETER
63   
64       public static void interpreter() {
65   
66           initialization(); // miro and pitches
67   
68           while ( true ) {
69               String input = getInput();
70               if ( input.equalsIgnoreCase("EXIT") ) {
71                   break;
72               } else {
73                   try {
74                       playMelody(input,pitches);
75                   } catch (Exception ex) {
76                       showErrorMessage(ex.toString());
77                   }
78               }
79           }
80   
81           cleanup(); // miro has to go
82       }
83   
84       // METHODS PERTAINING TO THE CHROMESTHETIC PITCHES
85   
86       private static Pitch[] establishPitches(SPainter painter) {
87           Pitch[] pitches = new Pitch[21];
88   
89           Pitch pitchMiddleC = new Pitch("C", painter);
90           pitches[0] = pitchMiddleC;
91   
92           Pitch pitchLowC = new Pitch("C,", painter);
93           pitches[1] = pitchLowC;
94   
95           Pitch pitchHighC = new Pitch("c", painter);
96           pitches[2] = pitchHighC;
97   
98           Pitch pitchMiddleD = new Pitch("D",painter);
99           pitches[3] = pitchMiddleD;
100  
101          Pitch pitchLowD = new Pitch("D,",painter);
102          pitches[4] = pitchLowD;
103  
104          Pitch pitchHighD = new Pitch("d",painter);
105          pitches[5] = pitchHighD;
106  
107          Pitch pitchMiddleE = new Pitch("E",painter);
108          pitches[6] = pitchMiddleE;
109  
110          Pitch pitchLowE = new Pitch("E,",painter);
111          pitches[7] = pitchLowE;
112  
113          Pitch pitchHighE = new Pitch("e",painter);
114          pitches[8] = pitchHighE;
115  
116          Pitch pitchMiddleF = new Pitch("F", painter);
117          pitches[9] = pitchMiddleF;
118  
119          Pitch pitchLowF = new Pitch("F,", painter);
120          pitches[10] = pitchLowF;
121  
122          Pitch pitchHighF = new Pitch( "f", painter);
123          pitches[11] = pitchHighF;
124  
125          Pitch pitchMiddleG = new Pitch("G", painter);
126          pitches[12] = pitchMiddleG;
127  
128          Pitch pitchLowG = new Pitch("G,", painter);
129          pitches[13] = pitchLowG;
130  
131          Pitch pitchHighG = new Pitch( "g", painter);
132          pitches[14] = pitchHighG;
133  
134          Pitch pitchMiddleA = new Pitch("A", painter);
135          pitches[15] = pitchMiddleA;
136  
137          Pitch pitchLowA = new Pitch("A,", painter);
138          pitches[16] = pitchLowA;
139  
140          Pitch pitchHighA = new Pitch( "a", painter);
141          pitches[17] = pitchHighA;
142  
143          Pitch pitchMiddleB = new Pitch("B", painter);
144          pitches[18] = pitchMiddleB;
145  
146          Pitch pitchLowB = new Pitch("B,", painter);
147          pitches[19] = pitchLowB;
148  
149          Pitch pitchHighB = new Pitch( "b", painter);
150          pitches[20] = pitchHighB;
151  
152          return pitches;
153      }
154      private static Pitch find(String token, Pitch[] pitches) throws Exception {
155          for ( int i = 0; i < pitches.length; i = i + 1 ) {
156              Pitch pitch = pitches[i];
157              if ( pitch.abcName().equals(token) ) {
158                  return pitch;
159              }
160          }
161          throw new Exception("### PITCH " + token + " NOT FOUND");
162      }
163  
164      private static void display(Pitch[] pitches) {
165          for ( int i = 0; i < pitches.length; i = i + 1 ) {
166              System.out.println(pitches[i].toString());
167          }
168      }
169  
170      private static void playMelody(String input, Pitch[] pitches) throws Exception {
171          Scanner scanner = new Scanner(input);
172          while ( scanner.hasNext() ) {
173              String token = scanner.next();
174              String pitchName;
175              String duration = "";
176              if ( token.indexOf(",") < 0 ) {
177                  pitchName = token.substring(0,1);
178                  duration = token.substring(1);
179              } else {
180                  pitchName = token.substring(0,2);
181                  duration = token.substring(2);
182              }
183              if ( duration.length() == 0 ) { duration = "1"; }
184              Pitch pitch = find(pitchName,pitches);
185              pitch.play(duration);
186          }
187      }
188  
189      // INITIALIZATION, CLEANUP< GETTING INPUT< ERROR MESSAGING
190  
191      static private void showErrorMessage(String message) {
192          miro.setVisible(false);
193          JOptionPane.showMessageDialog(null, message);
194      }
195  
196      private static void initialization() {
197          // ESTABLISH THE PAINTER AND GIVE IT A SUBSTANTIAL BRUSH WIDTH
198          miro = new SPainter("Chromesthesia",500,500);
199          miro.setVisible(false);
200          miro.setBrushWidth(7);
201          // ESTABLISH THE CHROMESTITIC PITCH CLASS OBJECTS
202          pitches = establishPitches(miro);
203          display(pitches);
204      }
205  
206      private static String getInput() {
207          miro.setVisible(false);
208          String label = "Please enter a melody in ABC notation, or EXIT ...    ";
209          String input = JOptionPane.showInputDialog(null,label);
210          miro.setVisible(true);
211          if ( input == null ) { input = "";}
212          return input;
213      }
214  
215      static private void cleanup() {
216          System.exit(0);
217      }
218  }
219  
220  
221