Chromesthesia.java
1    /* 
2    * This program interprets melodic lines given in ABC notation as a chromesthete might. 
3    * 
4    * A Pitch class will be defined, and will take center stage in the processing. 
5    * 
6    * Interpreting a melody in ABC notation will amount to flashing colored rectangles for prescribed durations,while sounding the pitch! The color of the rectangle will correspond to pitch class. 
7    * The duration will correspond to the duration of the note. 
8    * 
9    * The duration will be held constant at 1 beat. 
10   * 
11   * These sorts of images will appear on the screen, the chromesthetic output  box, a text input box, and an error message box. Simplicity of design is rendered by permitting only one box 
12   * to be on the screen at a time. 
13   * 
14   * ABC notes represent these examples: 
15   * C, D, E, C D E c d e 
16   * 
17   * Google ABC music representation if you need help. 
18   * 
19   * By Hunter Gersitz | SUNY Oswego Fall 2019 
20   * */
21   
22   package chromesthesia0;
23   
24   import painter.SPainter;
25   
26   import javax.swing.*;
27   import java.util.Scanner;
28   
29   public class Chromesthesia {
30   
31       // INFRASTRUCTURE FOR THE PROBLEM -- LAUNCHING A "GRAPHICS" THREAD
32   
33       public static void main(String[] args) {
34           SwingUtilities.invokeLater(new ThreadForGUI());
35       }
36   
37       private static class ThreadForGUI implements Runnable {
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       private static void interpreter() {
55   
56           initialization(); //miro and pitches
57   
58           while (true) {
59               String input = getInput();
60   
61               if ( input.equalsIgnoreCase("EXIT") ) {
62                   break;
63               } else {
64                   try {
65                       playMelody(input,pitches);
66                   } catch (Exception ex) {
67                       showErrorMessage(ex.toString());
68                   }
69               }
70           }
71           cleanup(); //miro has to go
72   
73       }
74   
75       // METHODS FEATURING TO THE CHROMESTHETIC PITCHES
76   
77       private static Pitch[] establishPitches(SPainter painter) {
78           Pitch[] pitches = new Pitch[9];
79           Pitch pitchMiddleC = new Pitch("C", painter);
80           pitches[0] = pitchMiddleC;
81           Pitch pitchLowC = new Pitch("C,",painter);
82           pitches[1] = pitchLowC;
83           Pitch pitchHighC = new Pitch("c",painter);
84           pitches[2] = pitchHighC;
85           Pitch pitchMiddleD = new Pitch("D",painter);
86           pitches[3] = pitchMiddleD;
87           Pitch pitchLowD = new Pitch("D,",painter);
88           pitches[4] = pitchLowD;
89           Pitch pitchHighD = new Pitch("d",painter);
90           pitches[5] = pitchHighD;
91           Pitch pitchMiddleE = new Pitch("E",painter);
92           pitches[6] = pitchMiddleE;
93           Pitch pitchLowE = new Pitch("E,",painter);
94           pitches[7] = pitchLowE;
95           Pitch pitchHighE = new Pitch("e",painter);
96           pitches[8] = pitchHighE;
97           return pitches;
98       }
99   
100      private static Pitch find (String token, Pitch[] pitches) throws Exception {
101          for (Pitch pitch : pitches) {
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 (Pitch pitch : pitches) {
111              System.out.println(pitch.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 THE 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 PITCH CLASS 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, or EXIT ....      ";
144          String input = JOptionPane.showInputDialog(null, label);
145          miro.setVisible(true);
146          if ( input == null ) { input = ""; }
147          return input;
148      }
149  
150      static private void cleanup() {
151          int i = 0;
152          System.exit(i);
153      }
154  
155  }
156  // END PROGRAM
157