Reputation: 5302
As a follow up to my (still unsolved) previous question, GUI event not triggering consistently, I've discovered another quirk. The code below creates and plays back a .wav file:
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
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.Mixer;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class audioTest extends JFrame {
private static final long serialVersionUID = 1L;
TargetDataLine targetDataLine;
AudioCapture audCap = new AudioCapture();
public static void main(String[] args) {
new audioTest();
}
public audioTest() {
layoutTransporButtons();
getContentPane().setLayout(new FlowLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(350, 100);
setVisible(true);
}
public void layoutTransporButtons() {
final JPanel guiButtonPanel = new JPanel();
final JButton captureBtn = new JButton("Record");
final JButton stopBtn = new JButton("Stop");
final JButton playBtn = new JButton("Playback");
guiButtonPanel.setLayout(new GridLayout());
this.add(guiButtonPanel);
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
playBtn.setEnabled(true);
JRadioButton[] radioBtnArray;
AudioFileFormat.Type[] fileTypes;
// Register anonymous listeners
captureBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
captureBtn.setEnabled(false);
stopBtn.setEnabled(true);
playBtn.setEnabled(false);
// Capture input data from the microphone
audCap.captureAudio();
}
});
guiButtonPanel.add(captureBtn);
stopBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
playBtn.setEnabled(true);
audCap.stopRecordAndPlayback = true;
audCap.stopRecording();
}
});
guiButtonPanel.add(stopBtn);
playBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
stopBtn.setEnabled(true);
audCap.playAudio();
}
});
guiButtonPanel.add(playBtn);
}
class AudioCapture {
volatile boolean stopRecordAndPlayback = false;
AudioFormat audioFormat;
AudioInputStream audioInputStream;
SourceDataLine sourceDataLine;
private String wavName;
private File audioFile;
/**
* capture audio input from microphone and save as .wav file
*/
public void captureAudio() {
wavName = JOptionPane.showInputDialog(null,
"enter name of file to be recorded:");
try {
Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
// Select an available mixer
Mixer mixer = AudioSystem.getMixer(mixerInfo[1]);
// Get everything set up for capture
audioFormat = getAudioFormat();
DataLine.Info dataLineInfo = new DataLine.Info(
TargetDataLine.class, audioFormat);
// Get a TargetDataLine on the selected mixer.
targetDataLine = (TargetDataLine) mixer.getLine(dataLineInfo);
// Prepare the line for use.
targetDataLine.open(audioFormat);
targetDataLine.start();
// Create a thread to capture the microphone
Thread captureThread = new CaptureThread();
captureThread.start();
} catch (Exception e) {
System.out.println(e);
System.exit(0);
}
}
/**
* This method plays back the audio data that has
* been chosen by the user
*/
public void playAudio() {
// add file chooser
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(audioFile);
int returnVal = chooser.showOpenDialog(chooser);
// retrieve chosen file
if (returnVal == JFileChooser.APPROVE_OPTION) {
// create the file
audioFile = chooser.getSelectedFile();
}
// play chosen file
try {
audioInputStream = AudioSystem.getAudioInputStream(audioFile);
audioFormat = audioInputStream.getFormat();
DataLine.Info dataLineInfo = new DataLine.Info(
SourceDataLine.class, audioFormat);
sourceDataLine = (SourceDataLine) AudioSystem
.getLine(dataLineInfo);
// Create a thread to play back the data
new PlayThread().start();
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
/**
* This method creates and returns an AudioFormat object
*/
private AudioFormat getAudioFormat() {
float sampleRate = 44100.0F;
// 8000,11025,16000,22050,44100
int sampleSizeInBits = 16;
// 8,16
int channels = 1;
// 1,2
boolean signed = true;
// true,false
boolean bigEndian = false;
// true,false
return new AudioFormat(sampleRate, sampleSizeInBits, channels,
signed, bigEndian);
}
/**
* Inner class to capture data from microphone
*/
class CaptureThread extends Thread {
// An arbitrary-size temporary holding buffer
byte tempBuffer[] = new byte[10000];
public void run() {
// reset stopCapture to false
stopRecordAndPlayback = false;
// record as wave
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
// take user input file name and append file type
audioFile = new File(wavName + ".wav");
try {
targetDataLine.open(audioFormat);
targetDataLine.start();
while (!stopRecordAndPlayback) {
AudioSystem.write(new AudioInputStream(targetDataLine),
fileType, audioFile);
}
targetDataLine.stop();
targetDataLine.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* method to stop capture
*/
public void stopRecording() {
// targetDataLine.stop();
// targetDataLine.close();
// System.out.println("stopped");
}
/**
* Inner class to play back the data
*/
class PlayThread extends Thread {
byte tempBuffer[] = new byte[10000];
public void run() {
// reset stop button
stopRecordAndPlayback = false;
try {
sourceDataLine.open(audioFormat);
sourceDataLine.start();
int cnt;
while ((cnt = audioInputStream.read(tempBuffer, 0,
tempBuffer.length)) != -1
&& stopRecordAndPlayback == false) {
if (cnt > 0) {
sourceDataLine.write(tempBuffer, 0, cnt);
}
}
sourceDataLine.drain();
sourceDataLine.close();
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
}
}
}
I tried changing the capture part to record an .aiff file instead, which works but playback is now silent. I can find the file and play via other means and it works fine but not in this program.
The lines I changed for recording the .aiff are:
// record as aiff
AudioFileFormat.Type fileType = AudioFileFormat.Type.AIFF;
// take user input file name and append file type
audioFile = new File(wavName + ".AIFF");
Anyone know why the .wav files playback via this code but .aiff files don't?
-EDIT- I also tried using .aif as the suffix but that didn't work either. And it occurred to me that it might have something to do with the files being stored as AIFF-C audio but I couldn't find anything further on this.
Upvotes: 1
Views: 1328
Reputation: 10418
AIFF-C is a compressed audio format, so you are not supposed to send it "as is" to the audio device. You need to decompress it to PCM first.
Upvotes: 1