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