package call.debug; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import javax.sound.sampled.TargetDataLine; import javax.sound.sampled.UnsupportedAudioFileException; /** * This code reads a file to an audio stream, captures a sample to an audio * stream, plays an audio stream, and writes an audio stream to a file. These * are the basic actions that one can carry out with an audio stream, hence this * code can serve as a tutorial example for how to do these basic audio tasks. * * This code was stolen, copied, and otherwise cobbled together from the demo * sound code in Sun's sound example, JavaSoundDemo. See: * http://java.sun.com/products/java-media/sound/ and * http://java.sun.com/products/java-media/sound/samples/JavaSoundDemo/ * * If a file name is given as the command line argument, then that file is * assumed to be a *.wav file and it is opened, read, and the sound is played. * If no command line argument is given. A 20 second sound sample is captured, * played, and writen out to Capture.wav as a *.wav file. * * @author Terry E. Weymouth * * SVN Source information... $LastChangedRevision$ $LastChangedDate$ * $HeadURL$ $LastChangedBy$ */ public class TestLines_ { final int bufSize = 16384; static final String OUT_FILE = "Capture.wav"; AudioFormat selectedFormat; /** * @param args */ public static void main(String[] args) { String filename = null; if (args.length > 0) filename = args[0]; new TestLines_().go(filename); System.exit(0); } public void go(String filename) { File fileIn = null; // check for input wav file if (filename != null) { fileIn = new File(filename); if (!fileIn.exists()) { System.out.println("Supplied input file, " + filename + ", does not exist."); System.out.println("Proceeding to capture sound live..."); fileIn = null; } if (!fileIn.canRead()) { System.out.println("Supplied input file, " + filename + ", can not be read."); System.out.println("Proceeding to capture sound live..."); fileIn = null; } } // get audio -- will also set selected format selectedFormat = null; AudioInputStream captureInputStream; if (fileIn != null) captureInputStream = getAudioFromFile(fileIn); else captureInputStream = captureLiveAudio(); if (captureInputStream == null) { System.out.println("Unable to obtain audio. Quitting."); return; } if (selectedFormat == null) { System.out.println("Selected format is null (!??). Quitting."); return; } // play audio stream playback(captureInputStream); // if it was captured write it out if (fileIn == null) writeFileOut(captureInputStream); } private AudioInputStream getAudioFromFile(File file) { System.out.println("Reading audio from file " + file.getAbsolutePath()); AudioInputStream audioInputStream = null; try { audioInputStream = AudioSystem.getAudioInputStream(file); } catch (UnsupportedAudioFileException e) { e.printStackTrace(); return null; } catch (IOException e) { e.printStackTrace(); return null; } selectedFormat = audioInputStream.getFormat(); return audioInputStream; } /** * Capture 20 seconds of live audio to a ByteArrayOutputStream in any * failure case print a message and return null */ private AudioInputStream captureLiveAudio() { TargetDataLine inLine = null; // ---------------------------------------------------------------------- // initialize input line DataLine.Info info = new DataLine.Info(TargetDataLine.class, null); if (!AudioSystem.isLineSupported(info)) { System.out.println("Did not find sound input line."); System.out.println("Line matching " + info + " not supported."); return null; } selectedFormat = findBestFormat(); if (selectedFormat == null) { System.out.println("Unable to find sutable format for capture."); return null; } System.out.println("Format = " + selectedFormat); try { inLine = (TargetDataLine) AudioSystem.getLine(info); inLine.open(selectedFormat, inLine.getBufferSize()); } catch (LineUnavailableException ex) { System.out.println("Unable to open the input line: " + ex); ex.printStackTrace(); return null; } catch (SecurityException ex) { System.out.println("Security " + ex.toString()); ex.printStackTrace(); return null; } catch (Exception ex) { System.out.println("Some other exception" + ex.toString()); ex.printStackTrace(); return null; } System.out.println("Found and opened sound input line."); // ---------------------------------------------------------------------- // capture ByteArrayOutputStream captureArrayStream = new ByteArrayOutputStream(); int frameSizeInBytes = selectedFormat.getFrameSize(); int bufferLengthInFrames = inLine.getBufferSize() / 8; int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes; byte[] data = new byte[bufferLengthInBytes]; int numBytesRead; inLine.start(); System.out.println("Capturing 20 seconds of sound."); System.out.println("Start Talking...."); Long start = System.currentTimeMillis(); Long time = start; while (time < (start + 20000)) // for 20 seconds { if ((numBytesRead = inLine.read(data, 0, bufferLengthInBytes)) == -1) { break; } captureArrayStream.write(data, 0, numBytesRead); System.out.print("*"); time = System.currentTimeMillis(); } System.out.println(); System.out.println(" ...done."); // we reached the end of the stream. stop and close the line. inLine.stop(); inLine.close(); inLine = null; // stop and close the capture stream try { captureArrayStream.flush(); captureArrayStream.close(); } catch (IOException ex) { ex.printStackTrace(); } // load bytes into the audio input stream for playback byte audioBytes[] = captureArrayStream.toByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(audioBytes); AudioInputStream audioInputStream = new AudioInputStream(bais, selectedFormat, audioBytes.length / frameSizeInBytes); long milliseconds = (long) ((audioInputStream.getFrameLength() * 1000) / selectedFormat .getFrameRate()); double duration = milliseconds / 1000.0; try { audioInputStream.reset(); } catch (Exception ex) { System.out.println("Failed to reset input to start."); ex.printStackTrace(); return null; // it can't be used in this case. } System.out.println("Captured " + duration + " seconds of audio."); return audioInputStream; } private void playback(AudioInputStream streamToPlay) { SourceDataLine outLine = null; // ---------------------------------------------------------------------- // initialize output audio line AudioInputStream playbackInputStream = AudioSystem.getAudioInputStream(selectedFormat, streamToPlay); if (playbackInputStream == null) { System.out.println("Unable to convert stream of format " + streamToPlay + " to format " + selectedFormat); return; } DataLine.Info info = new DataLine.Info(SourceDataLine.class, selectedFormat); if (!AudioSystem.isLineSupported(info)) { System.out.println("Did not find sound output line."); System.out.println("Line matching " + info + " not supported."); return; } try { outLine = (SourceDataLine) AudioSystem.getLine(info); outLine.open(selectedFormat, bufSize); } catch (LineUnavailableException ex) { System.out.println("Unable to open the line: " + ex); return; } System.out.println("Found and opened sound output line."); // ---------------------------------------------------------------------- // play back the supplied or captured audio data int frameSizeInBytes = selectedFormat.getFrameSize(); int bufferLengthInFrames = outLine.getBufferSize() / 8; int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes; byte[] data = new byte[bufferLengthInBytes]; int numBytesRead = 0; System.out.println("Starting playback."); // start the source data line outLine.start(); while (true) { try { if ((numBytesRead = playbackInputStream.read(data)) == -1) { break; } int numBytesRemaining = numBytesRead; while (numBytesRemaining > 0) { numBytesRemaining -= outLine.write(data, 0, numBytesRemaining); } System.out.print("*"); } catch (Exception e) { System.out.println("Error during playback: " + e); break; } } // we reached the end of the stream. let the data play out, then // stop and close the line. outLine.drain(); outLine.stop(); outLine.close(); outLine = null; System.out.println(); System.out.println("Done with playbock."); } private void writeFileOut(AudioInputStream streamToWrite) { // ---------------------------------------------------------------------- // Write results out to a file (specified by the static varible // OUT_FILE) System.out.println("Attempting to write sound recording to file = " + OUT_FILE); File file = new File(OUT_FILE); if (file.exists()) { System.out.println("File " + OUT_FILE + " already exists."); return; } // AudioFileFormat.Type fileType = AudioFileFormat.Type.AU; // AudioFileFormat.Type fileType = AudioFileFormat.Type.AIFF; AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE; try { streamToWrite.reset(); } catch (IOException e) { System.out.println("Write to file: Failed to reset input to start."); e.printStackTrace(); } try { if (AudioSystem.write(streamToWrite, fileType, file) == -1) { System.out.println("Failed to write to audio file " + OUT_FILE); } } catch (IOException e) { System.out.println("Failed to write to audio file " + OUT_FILE); e.printStackTrace(); } System.out.println("Wrote sound to file " + OUT_FILE); } AudioFormat.Encoding[] encodings = { AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_UNSIGNED, AudioFormat.Encoding.ULAW, AudioFormat.Encoding.ALAW }; float[] rates = { 44100.0f, 22050.0f, 16000.0f, 11025.0f, 8000.0f }; int[] sampleSizes = { 16, 8 }; private AudioFormat findBestFormat() { boolean bigEndian = true; AudioFormat format; boolean works; for (int e = 0; e < encodings.length; e++) for (int r = 0; r < rates.length; r++) for (int s = 0; s < sampleSizes.length; s++) for (int channels = 1; channels < 3; channels++) { format = new AudioFormat(encodings[e], rates[r], sampleSizes[s], channels, (sampleSizes[s] / 8) * channels, rates[r], bigEndian); works = probFormat(format); if (works) return format; format = new AudioFormat(encodings[e], rates[r], sampleSizes[s], channels, (sampleSizes[s] / 8) * channels, rates[r], !bigEndian); works = probFormat(format); if (works) return format; } return null; } private boolean probFormat(AudioFormat format) { DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); if (!AudioSystem.isLineSupported(info)) { return false; } try { TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info); line.open(format, line.getBufferSize()); line.close(); return true; } catch (Throwable t) {} return false; } }