chromesthesia1.java
1    
2    /* 
3     
4    This program interprets melodic lines given in ABC notation as a 
5    chromesthete might. 
6    A Pitch class will be defined, and will take center stage in the 
7    processing. 
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 be held 
14   * constant at 1 beat. 
15   * Three sorts of images will appear on the screen, the chromesthetic 
16   * output box, a text input box, and an error message box. Simplicity 
17   * of design is rendered by permitting only one box to be on the screen 
18   * at a time. 
19   * 
20   * ABC represents notes in a manner consistent with these examples: 
21   * C, D, E, C D E c d e 
22   * 
23   * Google ABC music representation if you would like to know more about it. 
24    */
25   package chromesthesia1;
26   import java.util.Scanner;
27   import javax.swing.JOptionPane;
28   import javax.swing.SwingUtilities;
29   import painter.SPainter;
30   
31   public class chromesthesia1 {
32       // INFRASTRUCTURE FOR THE PROGRAM -- LAUNCHING A "GRAPHICS" THREAD
33   
34       public static void main(String[] args) {
35           SwingUtilities.invokeLater(new ThreadForGUI());
36       }
37   
38       private static class ThreadForGUI implements Runnable {
39           @Override
40           public void run() {
41               new chromesthesia1();
42           }
43       }
44   
45       public chromesthesia1() {
46           interpreter();
47       }
48   
49       // FEATURED VARIABLES
50       private static SPainter miro;
51       private static Pitch1[] pitch1s;
52   
53       // THE INTERPRETER
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, pitch1s);
63                   } catch (Exception ex) {
64                       showErrorMessage(ex.toString());
65                   }
66               }
67           }
68           cleanup(); // miro has to go
69   
70       }
71   
72       // METHODS PERTAINING TO THE CHROMESTHETIC PITCHES
73       private static Pitch1[] establishPitches(SPainter painter) {
74           Pitch1[] pitch1s = new Pitch1[21];
75           Pitch1 pitch1MiddleC = new Pitch1("C",painter);
76           pitch1s[0] = pitch1MiddleC;
77           Pitch1 pitch1LowC = new Pitch1("C,",painter);
78           pitch1s[1] = pitch1LowC;
79           Pitch1 pitch1HighC = new Pitch1("c",painter);
80           pitch1s[2] = pitch1HighC;
81           Pitch1 pitch1MiddleD = new Pitch1("D",painter);
82           pitch1s[3] = pitch1MiddleD;
83           Pitch1 pitch1LowD = new Pitch1("D,",painter);
84           pitch1s[4] = pitch1LowD;
85           Pitch1 pitch1HighD = new Pitch1("d",painter);
86           pitch1s[5] = pitch1HighD;
87           Pitch1 pitch1MiddleE = new Pitch1("E",painter);
88           pitch1s[6] = pitch1MiddleE;
89           Pitch1 pitch1LowE = new Pitch1("E,",painter);
90           pitch1s[7] = pitch1LowE;
91           Pitch1 pitch1HighE = new Pitch1("e",painter);
92           pitch1s[8] = pitch1HighE;
93           Pitch1 pitch1MiddleF = new Pitch1("F",painter);
94           pitch1s[9] = pitch1MiddleF;
95           Pitch1 pitchLowF = new Pitch1("F,",painter );
96           pitch1s[10] = pitchLowF;
97           Pitch1 pitchHighF = new Pitch1("f",painter );
98           pitch1s[11] = pitchHighF;
99           Pitch1 pitch1MiddleG = new Pitch1("G",painter);
100          pitch1s[12] = pitch1MiddleG;
101          Pitch1 pitchLowG = new Pitch1("G,",painter );
102          pitch1s[13] = pitchLowG;
103          Pitch1 pitchHighG = new Pitch1("g",painter );
104          pitch1s[14] = pitchHighG;
105          Pitch1 pitch1MiddleA = new Pitch1("A",painter);
106          pitch1s[15] = pitch1MiddleA;
107          Pitch1 pitchLowA = new Pitch1("A,",painter );
108          pitch1s[16] = pitchLowA;
109          Pitch1 pitchHighA = new Pitch1("a",painter );
110          pitch1s[17] = pitchHighA;
111          Pitch1 pitch1MiddleB = new Pitch1("B",painter);
112          pitch1s[18] = pitch1MiddleB;
113          Pitch1 pitchLowB = new Pitch1("B,",painter );
114          pitch1s[19] = pitchLowB;
115          Pitch1 pitchHighB = new Pitch1("b",painter );
116          pitch1s[20] = pitchHighB;
117  
118          return pitch1s;
119      }
120  
121      private static Pitch1 find(String token, Pitch1[] pitch1s) throws Exception {
122          for (int i = 0; i < pitch1s.length; i = i + 1 ) {
123              Pitch1 pitch1 = pitch1s[i];
124              if ( pitch1.abcName().equals(token) ) {
125                  return pitch1;
126              }
127          }
128          throw new Exception("### PITCH " + token + " NOT FOUND");
129      }
130      private static void display(Pitch1[] pitch1s) {
131          for (int i = 0; i < pitch1s.length; i = i + 1) {
132              System.out.println(pitch1s[i].toString());
133          }
134      }
135      private static void playMelody(String input, Pitch1[] pitch1s) throws Exception {
136          Scanner scanner = new Scanner(input);
137          while ( scanner.hasNext() ) {
138              String token = scanner.next();
139              Pitch1 pitch1 = find(token, pitch1s);
140              pitch1.play("1");
141          }
142      }
143  
144      // INITIALIZATION, CLEANUP, GETTING INPUT, ERROR MESSAGING
145      static private void showErrorMessage(String message) {
146          miro.setVisible(false);
147          JOptionPane.showMessageDialog(null, message);
148      }
149  
150      private static void initialization() {
151  // ESTABLISH THE PAINTER AND GIVE IT A SUBSTANTIAL BRUSH WIDTH
152          miro = new SPainter("Chromesthesia",500,500);
153          miro.setVisible(false);
154          miro.setBrushWidth(7);
155  // ESTABLISH THE CHROMESTITIC PITCH CLASS OBJECTS
156          pitch1s = establishPitches(miro);
157          display(pitch1s);
158      }
159      private static String getInput() {
160          miro.setVisible(false);
161          String label = "Please enter a melody in ABC notation, or EXIT ...    ";
162          String input = JOptionPane.showInputDialog(null,label);
163          miro.setVisible(true);
164          if ( input == null ) { input = ""; }
165          return input;
166      }
167      static private void cleanup() {
168          System.exit(0);
169      }
170  }
171