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