/Users/lyon/j4p/src/video/CapturePlayBackPanel.java

1    package video; 
2     
3     
4    import sound.soundDemo.ControlContext; 
5    import sound.soundDemo.JavaSound; 
6    import sound.UlawCodec; 
7    import sound.OscopePanel; 
8     
9    import javax.sound.sampled.AudioFileFormat; 
10   import javax.sound.sampled.AudioFormat; 
11   import javax.sound.sampled.AudioInputStream; 
12   import javax.sound.sampled.AudioSystem; 
13   import javax.sound.sampled.DataLine; 
14   import javax.sound.sampled.LineUnavailableException; 
15   import javax.sound.sampled.SourceDataLine; 
16   import javax.sound.sampled.TargetDataLine; 
17   import javax.swing.AbstractButton; 
18   import javax.swing.ButtonGroup; 
19   import javax.swing.JButton; 
20   import javax.swing.JFileChooser; 
21   import javax.swing.JFrame; 
22   import javax.swing.JPanel; 
23   import javax.swing.JTextField; 
24   import javax.swing.JToggleButton; 
25   import javax.swing.border.BevelBorder; 
26   import javax.swing.border.CompoundBorder; 
27   import javax.swing.border.EmptyBorder; 
28   import java.awt.BasicStroke; 
29   import java.awt.BorderLayout; 
30   import java.awt.Color; 
31   import java.awt.Container; 
32   import java.awt.Dimension; 
33   import java.awt.FlowLayout; 
34   import java.awt.Font; 
35   import java.awt.Graphics; 
36   import java.awt.Graphics2D; 
37   import java.awt.GridLayout; 
38   import java.awt.Toolkit; 
39   import java.awt.event.ActionEvent; 
40   import java.awt.event.ActionListener; 
41   import java.awt.event.WindowAdapter; 
42   import java.awt.event.WindowEvent; 
43   import java.awt.font.FontRenderContext; 
44   import java.awt.font.LineBreakMeasurer; 
45   import java.awt.font.TextAttribute; 
46   import java.awt.font.TextLayout; 
47   import java.awt.geom.Line2D; 
48   import java.io.ByteArrayInputStream; 
49   import java.io.ByteArrayOutputStream; 
50   import java.io.File; 
51   import java.io.IOException; 
52   import java.text.AttributedCharacterIterator; 
53   import java.text.AttributedString; 
54   import java.util.Enumeration; 
55   import java.util.Vector; 
56    
57   /** 
58    * Capture/Playback sample.  Record audio in different formats 
59    * and then playback the recorded audio.  The captured audio can 
60    * be saved either as a WAVE, AU or AIFF.  Or load an audio file 
61    * for streaming playback. 
62    * 
63    * @author Brian Lichtenwalter 
64    * @version @(#)sound.audioDigitizer.CapturePlaybackFrame.java  1.12    02/02/06 
65    */ 
66   public class CapturePlayBackPanel extends JPanel 
67           implements ActionListener, ControlContext { 
68       private final int bufSize = 16384; 
69       private FormatControls formatControls = new FormatControls(); 
70       private Capture capture = new Capture(); 
71       private Playback playback = new Playback(); 
72       private int[] audioData = {0}; 
73       private UlawCodec ulc = new UlawCodec(); 
74       OscopePanel osp = new OscopePanel(); 
75       private AudioInputStream audioInputStream; 
76       private JButton playB, captB, pausB, loadB; 
77       private JButton auB, aiffB, waveB; 
78       private JTextField textField; 
79       private String fileName = "untitled"; 
80       private String errStr; 
81       private double duration, seconds; 
82       private File file; 
83       private Vector lines = new Vector(); 
84    
85       public CapturePlayBackPanel() { 
86           setLayout(new BorderLayout()); 
87           add(osp, BorderLayout.CENTER); 
88           add(getButtons(), BorderLayout.SOUTH); 
89           JPanel saveBpanel = new JPanel(); 
90           auB = addButton("Save AU", saveBpanel, false); 
91           aiffB = addButton("Save AIFF", saveBpanel, false); 
92           waveB = addButton("Save WAVE", saveBpanel, false); 
93       } 
94    
95       public JPanel getButtons() { 
96           JPanel buttonsPanel = new JPanel(); 
97           buttonsPanel.setLayout(new FlowLayout()); 
98           playB = addButton("Play", buttonsPanel, false); 
99           captB = addButton("Record", buttonsPanel, true); 
100          pausB = addButton("Pause", buttonsPanel, false); 
101          loadB = addButton("Load...", buttonsPanel, true); 
102          return buttonsPanel; 
103      } 
104   
105      public void open() { 
106      } 
107   
108      public void close() { 
109          if (playback.thread != null) { 
110              playB.doClick(0); 
111          } 
112          if (capture.thread != null) { 
113              captB.doClick(0); 
114          } 
115      } 
116   
117      private JButton addButton(String name, JPanel p, boolean state) { 
118          JButton b = new JButton(name); 
119          b.addActionListener(this); 
120          b.setEnabled(state); 
121          p.add(b); 
122          return b; 
123      } 
124   
125      public void actionPerformed(ActionEvent e) { 
126          Object obj = e.getSource(); 
127          if (obj.equals(auB)) { 
128              saveToFile(textField.getText().trim(), AudioFileFormat.Type.AU); 
129          } else if (obj.equals(aiffB)) { 
130              saveToFile(textField.getText().trim(), AudioFileFormat.Type.AIFF); 
131          } else if (obj.equals(waveB)) { 
132              saveToFile(textField.getText().trim(), AudioFileFormat.Type.WAVE); 
133          } else if (obj.equals(playB)) { 
134              if (playB.getText().startsWith("Play")) { 
135                  playback.start(); 
136                  // samplingGraph.start(); 
137                  captB.setEnabled(false); 
138                  pausB.setEnabled(true); 
139                  playB.setText("Stop"); 
140              } else { 
141                  playback.stop(); 
142                  captB.setEnabled(true); 
143                  pausB.setEnabled(false); 
144                  playB.setText("Play"); 
145              } 
146          } else if (obj.equals(captB)) { 
147              if (captB.getText().startsWith("Record")) { 
148                  file = null; 
149                  capture.start(); 
150                  fileName = "untitled"; 
151                  // samplingGraph.start(); 
152                  loadB.setEnabled(false); 
153                  playB.setEnabled(false); 
154                  pausB.setEnabled(true); 
155                  auB.setEnabled(false); 
156                  aiffB.setEnabled(false); 
157                  waveB.setEnabled(false); 
158                  captB.setText("Stop"); 
159              } else { 
160                  lines.removeAllElements(); 
161                  capture.stop(); 
162                  loadB.setEnabled(true); 
163                  playB.setEnabled(true); 
164                  pausB.setEnabled(false); 
165                  auB.setEnabled(true); 
166                  aiffB.setEnabled(true); 
167                  waveB.setEnabled(true); 
168                  captB.setText("Record"); 
169                  getUpdateDisplay(); 
170              } 
171          } else if (obj.equals(pausB)) { 
172              if (pausB.getText().startsWith("Pause")) { 
173                  if (capture.thread != null) { 
174                      capture.line.stop(); 
175                  } else { 
176                      if (playback.thread != null) { 
177                          playback.line.stop(); 
178                      } 
179                  } 
180                  pausB.setText("Resume"); 
181              } else { 
182                  if (capture.thread != null) { 
183                      capture.line.start(); 
184                  } else { 
185                      if (playback.thread != null) { 
186                          playback.line.start(); 
187                      } 
188                  } 
189                  pausB.setText("Pause"); 
190              } 
191          } else if (obj.equals(loadB)) { 
192              try { 
193                  File file = new File(System.getProperty("user.dir")); 
194                  JFileChooser fc = new JFileChooser(file); 
195                  fc.setFileFilter(new javax.swing.filechooser.FileFilter() { 
196                      public boolean accept(File f) { 
197                          if (f.isDirectory()) { 
198                              return true; 
199                          } 
200                          String name = f.getName(); 
201                          if (name.endsWith(".au") || name.endsWith(".wav") || name.endsWith(".aiff") || name.endsWith(".aif")) { 
202                              return true; 
203                          } 
204                          return false; 
205                      } 
206   
207                      public String getDescription() { 
208                          return ".au, .wav, .aif"; 
209                      } 
210                  }); 
211                  if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { 
212                      createAudioInputStream(fc.getSelectedFile(), true); 
213                  } 
214              } catch (SecurityException ex) { 
215                  JavaSound.showInfoDialog(); 
216                  ex.printStackTrace(); 
217              } catch (Exception ex) { 
218                  ex.printStackTrace(); 
219              } 
220          } 
221      } 
222   
223      public int[] getData() { 
224          return audioData; 
225      } 
226   
227      public void createWaveForm(byte[] audioBytes) { 
228          AudioFormat format = audioInputStream.getFormat(); 
229          System.out.println("format="+format); 
230          if (audioBytes == null) { 
231              try { 
232                  audioBytes = new byte[ 
233                          (int) (audioInputStream.getFrameLength() 
234                          * format.getFrameSize())]; 
235                  audioInputStream.read(audioBytes); 
236              } catch (Exception ex) { 
237                  reportStatus(ex.toString()); 
238                  return; 
239              } 
240          } 
241          Dimension d = getSize(); 
242          if (format.getSampleSizeInBits() == 16) { 
243              int nlengthInSamples = audioBytes.length / 2; 
244              audioData = new int[nlengthInSamples]; 
245              System.out.println(audioData.length); 
246              System.out.println("audio 1 " + audioData[10]); 
247              if (format.isBigEndian()) { 
248                  for (int i = 0; i < nlengthInSamples; i++) { 
249                      /* First byte is MSB (high order) */ 
250                      int MSB = (int) audioBytes[2 * i]; 
251                      /* Second byte is LSB (low order) */ 
252                      int LSB = (int) audioBytes[2 * i + 1]; 
253                      audioData[i] = MSB << 8 | (255 & LSB); 
254                  } 
255              } else { 
256                  for (int i = 0; i < nlengthInSamples; i++) { 
257                      /* First byte is LSB (low order) */ 
258                      int LSB = (int) audioBytes[2 * i]; 
259                      /* Second byte is MSB (high order) */ 
260                      int MSB = (int) audioBytes[2 * i + 1]; 
261                      audioData[i] = MSB << 8 | (255 & LSB); 
262                  } 
263              } 
264          } else if (format.getSampleSizeInBits() == 8) { 
265              int nlengthInSamples = audioBytes.length; 
266              audioData = new int[nlengthInSamples]; 
267              if (format.getEncoding().toString().startsWith("PCM_SIGN")) { 
268                  for (int i = 0; i < audioBytes.length; i++) { 
269                      audioData[i] = audioBytes[i]; 
270                  } 
271              } else { 
272                  for (int i = 0; i < audioBytes.length; i++) { 
273                      audioData[i] = audioBytes[i] - 128; 
274                  } 
275              } 
276          } 
277          osp.setData(getDoubleData(audioData)); 
278      } 
279      /** 
280       * Convert the 16 bit data into double data 
281       * @param audioData 
282       * @return  data that ranges from -1 to 1 
283       */ 
284      private double[] getDoubleData(int[] audioData) { 
285          double d[] = new double[audioData.length]; 
286          for (int i=0; i < audioData.length; i++) 
287              d[i] = audioData[i]/32768.0; 
288          return d; 
289      } 
290   
291      private void getUpdateDisplay() { 
292      } 
293   
294      public void createAudioInputStream(File file, boolean updateComponents) { 
295          if (file != null && file.isFile()) { 
296              try { 
297                  this.file = file; 
298                  errStr = null; 
299                  audioInputStream = AudioSystem.getAudioInputStream(file); 
300                  playB.setEnabled(true); 
301                  fileName = file.getName(); 
302                  long milliseconds = (long) ((audioInputStream.getFrameLength() * 1000) / audioInputStream.getFormat().getFrameRate()); 
303                  duration = milliseconds / 1000.0; 
304                  auB.setEnabled(true); 
305                  aiffB.setEnabled(true); 
306                  waveB.setEnabled(true); 
307                  if (updateComponents) { 
308                      formatControls.setFormat(audioInputStream.getFormat()); 
309                  } 
310              } catch (Exception ex) { 
311                  reportStatus(ex.toString()); 
312              } 
313          } else { 
314              reportStatus("Audio file required."); 
315          } 
316      } 
317   
318      public void saveToFile(String name, AudioFileFormat.Type fileType) { 
319          if (audioInputStream == null) { 
320              reportStatus("No loaded audio to save"); 
321              return; 
322          } else if (file != null) { 
323              createAudioInputStream(file, false); 
324          } 
325   
326          // reset to the beginnning of the captured data 
327          try { 
328              audioInputStream.reset(); 
329          } catch (Exception e) { 
330              reportStatus("Unable to reset stream " + e); 
331              return; 
332          } 
333          File file = new File(fileName = name); 
334          try { 
335              if (AudioSystem.write(audioInputStream, fileType, file) == -1) { 
336                  throw new IOException("Problems writing to file"); 
337              } 
338          } catch (Exception ex) { 
339              reportStatus(ex.toString()); 
340          } 
341      } 
342   
343      private void reportStatus(String msg) { 
344          if ((errStr = msg) != null) { 
345              System.out.println(errStr); 
346          } 
347      } 
348   
349      /** 
350       * Write data to the OutputChannel. 
351       */ 
352      public class Playback implements Runnable { 
353          SourceDataLine line; 
354          Thread thread; 
355   
356          public void start() { 
357              errStr = null; 
358              thread = new Thread(this); 
359              thread.setName("Playback"); 
360              thread.start(); 
361          } 
362   
363          public void stop() { 
364              thread = null; 
365          } 
366   
367          private void shutDown(String message) { 
368              if ((errStr = message) != null) { 
369                  System.err.println(errStr); 
370              } 
371              if (thread != null) { 
372                  thread = null; 
373                  captB.setEnabled(true); 
374                  pausB.setEnabled(false); 
375                  playB.setText("Play"); 
376              } 
377          } 
378   
379          public void run() { 
380              // reload the file if loaded by file 
381              if (file != null) { 
382                  createAudioInputStream(file, false); 
383              } 
384   
385              // make sure we have something to play 
386              if (audioInputStream == null) { 
387                  shutDown("No loaded audio to play back"); 
388                  return; 
389              } 
390              // reset to the beginnning of the stream 
391              try { 
392                  audioInputStream.reset(); 
393              } catch (Exception e) { 
394                  shutDown("Unable to reset the stream\n" + e); 
395                  return; 
396              } 
397   
398              // get an AudioInputStream of the desired format for playback 
399              AudioFormat format = formatControls.getFormat(); 
400              AudioInputStream playbackInputStream = AudioSystem.getAudioInputStream(format, audioInputStream); 
401              if (playbackInputStream == null) { 
402                  shutDown("Unable to convert stream of format " + audioInputStream + " to format " + format); 
403                  return; 
404              } 
405   
406              // define the required attributes for our line, 
407              // and make sure a compatible line is supported. 
408   
409              DataLine.Info info = new DataLine.Info(SourceDataLine.class, 
410                      format); 
411              if (!AudioSystem.isLineSupported(info)) { 
412                  shutDown("Line matching " + info + " not supported."); 
413                  return; 
414              } 
415   
416              // get and open the source data line for playback. 
417   
418              try { 
419                  line = (SourceDataLine) AudioSystem.getLine(info); 
420                  line.open(format, bufSize); 
421              } catch (LineUnavailableException ex) { 
422                  shutDown("Unable to open the line: " + ex); 
423                  return; 
424              } 
425   
426              // play back the captured audio data 
427   
428              int frameSizeInBytes = format.getFrameSize(); 
429              int bufferLengthInFrames = line.getBufferSize() / 8; 
430              int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes; 
431              byte[] data = new byte[bufferLengthInBytes]; 
432              int numBytesRead = 0; 
433   
434              // start the source data line 
435              line.start(); 
436              while (thread != null) { 
437                  try { 
438                      if ((numBytesRead = playbackInputStream.read(data)) == -1) { 
439                          break; 
440                      } 
441                      int numBytesRemaining = numBytesRead; 
442                      while (numBytesRemaining > 0) { 
443                          numBytesRemaining -= line.write(data, 0, numBytesRemaining); 
444                      } 
445                  } catch (Exception e) { 
446                      shutDown("Error during playback: " + e); 
447                      break; 
448                  } 
449              } 
450              // we reached the end of the stream.  let the data play out, then 
451              // stop and close the line. 
452              if (thread != null) { 
453                  line.drain(); 
454              } 
455              line.stop(); 
456              line.close(); 
457              line = null; 
458              shutDown(null); 
459          } 
460      } // End class Playback 
461   
462      /** 
463       * Reads data from the input channel and writes to the output stream 
464       */ 
465      class Capture implements Runnable { 
466          TargetDataLine line; 
467          Thread thread; 
468   
469          public void start() { 
470              errStr = null; 
471              thread = new Thread(this); 
472              thread.setName("Capture"); 
473              thread.start(); 
474          } 
475   
476          public void stop() { 
477              thread = null; 
478          } 
479   
480          private void shutDown(String message) { 
481              if ((errStr = message) != null && thread != null) { 
482                  thread = null; 
483                  loadB.setEnabled(true); 
484                  playB.setEnabled(true); 
485                  pausB.setEnabled(false); 
486                  auB.setEnabled(true); 
487                  aiffB.setEnabled(true); 
488                  waveB.setEnabled(true); 
489                  captB.setText("Record"); 
490                  System.err.println(errStr); 
491              } 
492          } 
493   
494          public void run() { 
495              duration = 0; 
496              audioInputStream = null; 
497   
498              // define the required attributes for our line, 
499              // and make sure a compatible line is supported. 
500   
501              AudioFormat format = formatControls.getFormat(); 
502              DataLine.Info info = new DataLine.Info(TargetDataLine.class, 
503                      format); 
504              if (!AudioSystem.isLineSupported(info)) { 
505                  shutDown("Line matching " + info + " not supported."); 
506                  return; 
507              } 
508   
509              // get and open the target data line for capture. 
510   
511              try { 
512                  line = (TargetDataLine) AudioSystem.getLine(info); 
513                  line.open(format, line.getBufferSize()); 
514              } catch (LineUnavailableException ex) { 
515                  shutDown("Unable to open the line: " + ex); 
516                  return; 
517              } catch (SecurityException ex) { 
518                  shutDown(ex.toString()); 
519                  JavaSound.showInfoDialog(); 
520                  return; 
521              } catch (Exception ex) { 
522                  shutDown(ex.toString()); 
523                  return; 
524              } 
525   
526              // play back the captured audio data 
527              ByteArrayOutputStream out = new ByteArrayOutputStream(); 
528              int frameSizeInBytes = format.getFrameSize(); 
529              int bufferLengthInFrames = line.getBufferSize() / 8; 
530              int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes; 
531              byte[] data = new byte[bufferLengthInBytes]; 
532              int numBytesRead; 
533              line.start(); 
534              while (thread != null) { 
535                  if ((numBytesRead = line.read(data, 0, bufferLengthInBytes)) == -1) { 
536                      break; 
537                  } 
538                  out.write(data, 0, numBytesRead); 
539              } 
540   
541              // we reached the end of the stream.  stop and close the line. 
542              line.stop(); 
543              line.close(); 
544              line = null; 
545   
546              // stop and close the output stream 
547              try { 
548                  out.flush(); 
549                  out.close(); 
550              } catch (IOException ex) { 
551                  ex.printStackTrace(); 
552              } 
553   
554              // load bytes into the audio input stream for playback 
555   
556              byte audioBytes[] = out.toByteArray(); 
557              ByteArrayInputStream bais = new ByteArrayInputStream(audioBytes); 
558              audioInputStream = new AudioInputStream(bais, format, audioBytes.length / frameSizeInBytes); 
559              long milliseconds = (long) ((audioInputStream.getFrameLength() * 1000) / format.getFrameRate()); 
560              duration = milliseconds / 1000.0; 
561              try { 
562                  audioInputStream.reset(); 
563              } catch (Exception ex) { 
564                  ex.printStackTrace(); 
565                  return; 
566              } 
567              createWaveForm(audioBytes); 
568          } 
569      } // End class Capture 
570   
571      /** 
572       * Controls for the AudioFormat. 
573       */ 
574      class FormatControls extends JPanel { 
575          Vector groups = new Vector(); 
576          JToggleButton linrB, ulawB, alawB, rate8B, rate11B, rate16B, rate22B, rate44B; 
577          JToggleButton size8B, size16B, signB, unsignB, litB, bigB, monoB, sterB; 
578   
579          public FormatControls() { 
580              setLayout(new GridLayout(0, 1)); 
581              EmptyBorder eb = new EmptyBorder(0, 0, 0, 5); 
582              BevelBorder bb = new BevelBorder(BevelBorder.LOWERED); 
583              CompoundBorder cb = new CompoundBorder(eb, bb); 
584              setBorder(new CompoundBorder(cb, new EmptyBorder(8, 5, 5, 5))); 
585              JPanel p1 = new JPanel(); 
586              ButtonGroup encodingGroup = new ButtonGroup(); 
587              linrB = addToggleButton(p1, encodingGroup, "linear", true); 
588              ulawB = addToggleButton(p1, encodingGroup, "ulaw", false); 
589              alawB = addToggleButton(p1, encodingGroup, "alaw", false); 
590              add(p1); 
591              groups.addElement(encodingGroup); 
592              JPanel p2 = new JPanel(); 
593              JPanel p2b = new JPanel(); 
594              ButtonGroup sampleRateGroup = new ButtonGroup(); 
595              rate8B = addToggleButton(p2, sampleRateGroup, "8000", false); 
596              rate11B = addToggleButton(p2, sampleRateGroup, "11025", false); 
597              rate16B = addToggleButton(p2b, sampleRateGroup, "16000", false); 
598              rate22B = addToggleButton(p2b, sampleRateGroup, "22050", false); 
599              rate44B = addToggleButton(p2b, sampleRateGroup, "44100", true); 
600              add(p2); 
601              add(p2b); 
602              groups.addElement(sampleRateGroup); 
603              JPanel p3 = new JPanel(); 
604              ButtonGroup sampleSizeInBitsGroup = new ButtonGroup(); 
605              size8B = addToggleButton(p3, sampleSizeInBitsGroup, "8", false); 
606              size16B = addToggleButton(p3, sampleSizeInBitsGroup, "16", true); 
607              add(p3); 
608              groups.addElement(sampleSizeInBitsGroup); 
609              JPanel p4 = new JPanel(); 
610              ButtonGroup signGroup = new ButtonGroup(); 
611              signB = addToggleButton(p4, signGroup, "signed", true); 
612              unsignB = addToggleButton(p4, signGroup, "unsigned", false); 
613              add(p4); 
614              groups.addElement(signGroup); 
615              JPanel p5 = new JPanel(); 
616              ButtonGroup endianGroup = new ButtonGroup(); 
617              litB = addToggleButton(p5, endianGroup, "little endian", false); 
618              bigB = addToggleButton(p5, endianGroup, "big endian", true); 
619              add(p5); 
620              groups.addElement(endianGroup); 
621              JPanel p6 = new JPanel(); 
622              ButtonGroup channelsGroup = new ButtonGroup(); 
623              monoB = addToggleButton(p6, channelsGroup, "mono", false); 
624              sterB = addToggleButton(p6, channelsGroup, "stereo", true); 
625              add(p6); 
626              groups.addElement(channelsGroup); 
627          } 
628   
629          private JToggleButton addToggleButton(JPanel p, ButtonGroup g, 
630                                                String name, boolean state) { 
631              JToggleButton b = new JToggleButton(name, state); 
632              p.add(b); 
633              g.add(b); 
634              return b; 
635          } 
636   
637          public AudioFormat getFormat() { 
638              Vector v = new Vector(groups.size()); 
639              for (int i = 0; i < groups.size(); i++) { 
640                  ButtonGroup g = (ButtonGroup) groups.get(i); 
641                  for (Enumeration e = g.getElements(); e.hasMoreElements();) { 
642                      AbstractButton b = (AbstractButton) e.nextElement(); 
643                      if (b.isSelected()) { 
644                          v.add(b.getText()); 
645                          break; 
646                      } 
647                  } 
648              } 
649              AudioFormat.Encoding encoding = AudioFormat.Encoding.ULAW; 
650              String encString = (String) v.get(0); 
651              float rate = Float.valueOf((String) v.get(1)).floatValue(); 
652              int sampleSize = Integer.valueOf((String) v.get(2)).intValue(); 
653              String signedString = (String) v.get(3); 
654              boolean bigEndian = ((String) v.get(4)).startsWith("big"); 
655              int channels = (v.get(5)).equals("mono") ? 1 : 2; 
656              if (encString.equals("linear")) { 
657                  if (signedString.equals("signed")) { 
658                      encoding = AudioFormat.Encoding.PCM_SIGNED; 
659                  } else { 
660                      encoding = AudioFormat.Encoding.PCM_UNSIGNED; 
661                  } 
662              } else if (encString.equals("alaw")) { 
663                  encoding = AudioFormat.Encoding.ALAW; 
664              } 
665              return new AudioFormat(encoding, rate, sampleSize, 
666                      channels, (sampleSize / 8) * channels, rate, bigEndian); 
667          } 
668   
669          public void setFormat(AudioFormat format) { 
670              AudioFormat.Encoding type = format.getEncoding(); 
671              if (type == AudioFormat.Encoding.ULAW) { 
672                  ulawB.doClick(); 
673              } else if (type == AudioFormat.Encoding.ALAW) { 
674                  alawB.doClick(); 
675              } else if (type == AudioFormat.Encoding.PCM_SIGNED) { 
676                  linrB.doClick(); 
677                  signB.doClick(); 
678              } else if (type == AudioFormat.Encoding.PCM_UNSIGNED) { 
679                  linrB.doClick(); 
680                  unsignB.doClick(); 
681              } 
682              float rate = format.getFrameRate(); 
683              if (rate == 8000) { 
684                  rate8B.doClick(); 
685              } else if (rate == 11025) { 
686                  rate11B.doClick(); 
687              } else if (rate == 16000) { 
688                  rate16B.doClick(); 
689              } else if (rate == 22050) { 
690                  rate22B.doClick(); 
691              } else if (rate == 44100) { 
692                  rate44B.doClick(); 
693              } 
694              switch (format.getSampleSizeInBits()) { 
695                  case 8: 
696                      size8B.doClick(); 
697                      break; 
698                  case 16: 
699                      size16B.doClick(); 
700                      break; 
701              } 
702              if (format.isBigEndian()) { 
703                  bigB.doClick(); 
704              } else { 
705                  litB.doClick(); 
706              } 
707              if (format.getChannels() == 1) { 
708                  monoB.doClick(); 
709              } else { 
710                  sterB.doClick(); 
711              } 
712          } 
713      } // End class FormatControls 
714   
715      /** 
716       * Render a WaveForm. 
717       */ 
718      class SamplingGraph extends JPanel implements Runnable { 
719          private Thread thread; 
720          //private Font font10 = new Font("serif", Font.PLAIN, 10); 
721          private Font font12 = new Font("serif", Font.PLAIN, 12); 
722          Color jfcBlue = new Color(204, 204, 255); 
723          Color pink = new Color(255, 175, 175); 
724   
725          public SamplingGraph() { 
726              setBackground(new Color(20, 20, 20)); 
727          } 
728   
729          public void createWaveForm(byte[] ulawEncodedData) { 
730              System.out.println("WaveForm"); 
731              lines.removeAllElements();  // clear the old vector 
732              AudioFormat format = audioInputStream.getFormat(); 
733              if (ulawEncodedData == null) { 
734                  try { 
735                      ulawEncodedData = new byte[ 
736                              (int) (audioInputStream.getFrameLength() 
737                              * format.getFrameSize())]; 
738                      audioInputStream.read(ulawEncodedData); 
739                  } catch (Exception ex) { 
740                      reportStatus(ex.toString()); 
741                      return; 
742                  } 
743              } 
744              Dimension d = getSize(); 
745              int w = d.width; 
746              int h = d.height - 15; 
747              if (format.getSampleSizeInBits() == 16) { 
748                  int nlengthInSamples = ulawEncodedData.length / 2; 
749                  audioData = new int[nlengthInSamples]; 
750                  if (format.isBigEndian()) { 
751                      for (int i = 0; i < nlengthInSamples; i++) { 
752                          /* First byte is MSB (high order) */ 
753                          int MSB = (int) ulawEncodedData[2 * i]; 
754                          /* Second byte is LSB (low order) */ 
755                          int LSB = (int) ulawEncodedData[2 * i + 1]; 
756                          audioData[i] = MSB << 8 | (255 & LSB); 
757                      } 
758                  } else { 
759                      for (int i = 0; i < nlengthInSamples; i++) { 
760                          /* First byte is LSB (low order) */ 
761                          int LSB = (int) ulawEncodedData[2 * i]; 
762                          /* Second byte is MSB (high order) */ 
763                          int MSB = (int) ulawEncodedData[2 * i + 1]; 
764                          audioData[i] = MSB << 8 | (255 & LSB); 
765                      } 
766                  } 
767              } else if (format.getSampleSizeInBits() == 8) { 
768                  int nlengthInSamples = ulawEncodedData.length; 
769                  audioData = new int[nlengthInSamples]; 
770                  if (format.getEncoding().toString().startsWith("PCM_SIGN")) { 
771                      for (int i = 0; i < ulawEncodedData.length; i++) { 
772                          audioData[i] = ulawEncodedData[i]; 
773                      } 
774                  } else { 
775                      for (int i = 0; i < ulawEncodedData.length; i++) { 
776                          audioData[i] = ulawEncodedData[i] - 128; 
777                      } 
778                  } 
779              } 
780              int frames_per_pixel = ulawEncodedData.length / format.getFrameSize() / w; 
781              byte my_byte = 0; 
782              double y_last = 0; 
783              int numChannels = format.getChannels(); 
784              for (double x = 0; x < w && audioData != null; x++) { 
785                  int idx = (int) (frames_per_pixel * numChannels * x); 
786                  if (format.getSampleSizeInBits() == 8) { 
787                      my_byte = (byte) audioData[idx]; 
788                  } else { 
789                      my_byte = (byte) (128 * audioData[idx] / 32768); 
790                  } 
791                  double y_new = (double) (h * (128 - my_byte) / 256); 
792                  lines.add(new Line2D.Double(x, y_last, x, y_new)); 
793                  y_last = y_new; 
794              } 
795              repaint(); 
796          } 
797   
798          public void paint(Graphics g) { 
799              Dimension d = getSize(); 
800              int w = d.width; 
801              int h = d.height; 
802              int INFOPAD = 15; 
803              Graphics2D g2 = (Graphics2D) g; 
804              g2.setBackground(getBackground()); 
805              g2.clearRect(0, 0, w, h); 
806              g2.setColor(Color.white); 
807              g2.fillRect(0, h - INFOPAD, w, INFOPAD); 
808              if (errStr != null) { 
809                  g2.setColor(jfcBlue); 
810                  g2.setFont(new Font("serif", Font.BOLD, 18)); 
811                  g2.drawString("ERROR", 5, 20); 
812                  AttributedString as = new AttributedString(errStr); 
813                  as.addAttribute(TextAttribute.FONT, font12, 0, errStr.length()); 
814                  AttributedCharacterIterator aci = as.getIterator(); 
815                  FontRenderContext frc = g2.getFontRenderContext(); 
816                  LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc); 
817                  float x = 5, y = 25; 
818                  lbm.setPosition(0); 
819                  while (lbm.getPosition() < errStr.length()) { 
820                      TextLayout tl = lbm.nextLayout(w - x - 5); 
821                      if (!tl.isLeftToRight()) { 
822                          x = w - tl.getAdvance(); 
823                      } 
824                      tl.draw(g2, x, y += tl.getAscent()); 
825                      y += tl.getDescent() + tl.getLeading(); 
826                  } 
827              } else if (capture.thread != null) { 
828                  g2.setColor(Color.black); 
829                  g2.setFont(font12); 
830                  g2.drawString("Length: " + String.valueOf(seconds), 3, h - 4); 
831              } else { 
832                  g2.setColor(Color.black); 
833                  g2.setFont(font12); 
834                  g2.drawString("File: " + fileName + "  Length: " + String.valueOf(duration) + "  Position: " + String.valueOf(seconds), 3, h - 4); 
835                  if (audioInputStream != null) { 
836                      // .. render sampling graph .. 
837                      g2.setColor(jfcBlue); 
838                      for (int i = 1; i < lines.size(); i++) { 
839                          g2.draw((Line2D) lines.get(i)); 
840                      } 
841   
842                      // .. draw current position .. 
843                      if (seconds != 0) { 
844                          double loc = seconds / duration * w; 
845                          g2.setColor(pink); 
846                          g2.setStroke(new BasicStroke(3)); 
847                          g2.draw(new Line2D.Double(loc, 0, loc, h - INFOPAD - 2)); 
848                      } 
849                  } 
850              } 
851          } 
852   
853          public void start() { 
854              thread = new Thread(this); 
855              thread.setName("SamplingGraph"); 
856              thread.start(); 
857              seconds = 0; 
858          } 
859   
860          public void stop() { 
861              if (thread != null) { 
862                  thread.interrupt(); 
863              } 
864              thread = null; 
865          } 
866   
867          public void run() { 
868              seconds = 0; 
869              while (thread != null) { 
870                  if ((playback.line != null) && (playback.line.isOpen())) { 
871                      long milliseconds = (playback.line.getMicrosecondPosition() / 1000); 
872                      seconds = milliseconds / 1000.0; 
873                  } else if ((capture.line != null) && (capture.line.isActive())) { 
874                      long milliseconds = (capture.line.getMicrosecondPosition() / 1000); 
875                      seconds = milliseconds / 1000.0; 
876                  } 
877                  try { 
878                      Thread.sleep(100); 
879                  } catch (Exception e) { 
880                      break; 
881                  } 
882                  repaint(); 
883                  while ((capture.line != null && !capture.line.isActive()) || 
884                          (playback.line != null && !playback.line.isOpen())) { 
885                      try { 
886                          Thread.sleep(10); 
887                      } catch (Exception e) { 
888                          break; 
889                      } 
890                  } 
891              } 
892              seconds = 0; 
893              repaint(); 
894          } 
895      } // End class SamplingGraph 
896   
897      public static void main(String[] args) { 
898          CapturePlayBackPanel cpbp = new CapturePlayBackPanel(); 
899          gui.ClosableJFrame cf = new gui.ClosableJFrame(); 
900          Container c = cf.getContentPane(); 
901          c.add(cpbp); 
902          cf.setSize(400, 400); 
903          cf.show(); 
904      } 
905   
906      public static void test() { 
907          CapturePlayBackPanel capturePlayback = new CapturePlayBackPanel(); 
908          capturePlayback.open(); 
909          JFrame f = new JFrame("Capture/Playback"); 
910          f.addWindowListener(new WindowAdapter() { 
911              public void windowClosing(WindowEvent e) { 
912                  System.exit(0); 
913              } 
914          }); 
915          f.getContentPane().add("Center", capturePlayback); 
916          f.pack(); 
917          Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
918          int w = 720; 
919          int h = 340; 
920          f.setLocation(screenSize.width / 2 - w / 2, screenSize.height / 2 - h / 2); 
921          f.setSize(w, h); 
922          f.show(); 
923      } 
924   
925      public int getBufSize() { 
926          return bufSize; 
927      } 
928   
929      public FormatControls getFormatControls() { 
930          return formatControls; 
931      } 
932   
933      public Capture getCapture() { 
934          return capture; 
935      } 
936   
937      public Playback getPlayback() { 
938          return playback; 
939      } 
940   
941      public AudioInputStream getAudioInputStream() { 
942          return audioInputStream; 
943      } 
944   
945      public JButton getPlayB() { 
946          return playB; 
947      } 
948   
949      public JButton getCaptB() { 
950          return captB; 
951      } 
952   
953      public JButton getPausB() { 
954          return pausB; 
955      } 
956   
957      public JButton getLoadB() { 
958          return loadB; 
959      } 
960   
961      public JButton getAuB() { 
962          return auB; 
963      } 
964   
965      public JButton getAiffB() { 
966          return aiffB; 
967      } 
968   
969      public JButton getWaveB() { 
970          return waveB; 
971      } 
972   
973      public JTextField getTextField() { 
974          return textField; 
975      } 
976   
977      public String getFileName() { 
978          return fileName; 
979      } 
980   
981      public String getErrStr() { 
982          return errStr; 
983      } 
984   
985      public double getDuration() { 
986          return duration; 
987      } 
988   
989      public double getSeconds() { 
990          return seconds; 
991      } 
992   
993      public File getFile() { 
994          return file; 
995      } 
996   
997      public Vector getLines() { 
998          return lines; 
999      } 
1000 }