오디오 녹음 후 Line unavailable 예외 발생에 대한 질문과 저장에 관한 질문 드립니다!
자바로 오디오를 녹음한 후 재생하는 코드를 가져와서 공부중입니다!
실행하여 확인해보다가 Capture버튼을 눌러 녹음 후 재생한 뒤 한번더 녹음하려 Capture 버튼을 누르니 예외처리 되어 종료됩니다.
어떻게 코드를 변경해야 예외가 발생하지 않나요??
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.sound.sampled.*;
public class Capture extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
protected boolean running;
ByteArrayOutputStream out;
public Capture() {
super("Capture Sound Demo"); // Frame창 이름
setDefaultCloseOperation(EXIT_ON_CLOSE); // 창 종료방식
Container content = getContentPane(); // content를 ContentPane형식으로
final JButton capture = new JButton("Capture"); // 음성 녹음 버튼
final JButton stop = new JButton("Stop"); // 음성 녹음 멈춤 버튼
final JButton play = new JButton("Play"); // 녹음된 음성 재생 버튼
capture.setEnabled(true); // 캡처 버튼 활성화
stop.setEnabled(false); // 스탑 버튼 비활성화
play.setEnabled(false); // 재생 버튼 비활성화
ActionListener captureListener = new ActionListener() { // 캡처 이벤트 핸들러
public void actionPerformed(ActionEvent e) {
capture.setEnabled(false); // 음성 녹음동안 버튼 비활성화
stop.setEnabled(true); // 음성 녹음 멈춤 버튼 활성화
play.setEnabled(false); // 재생 버튼 비활성화
captureAudio(); // 음성 녹음 함수
}
};
capture.addActionListener(captureListener); // 캡처 버튼에 핸들러 적용
content.add(capture, BorderLayout.NORTH); // 캡처 버튼 위치
ActionListener stopListener = new ActionListener() { // 스탑 이벤트 핸들러
public void actionPerformed(ActionEvent e) {
capture.setEnabled(true); // 캡처 버튼 활성화
stop.setEnabled(false); // 스탑 버튼 비활성화
play.setEnabled(true); // 재생 버튼 활성화
running = false;
}
};
stop.addActionListener(stopListener); // 스탑 버튼에 핸들러 적용
content.add(stop, BorderLayout.CENTER); // 스탑 버튼 위치
ActionListener playListener = new ActionListener() { // 재생 이벤트 핸들러
public void actionPerformed(ActionEvent e) {
playAudio(); // 녹음 된 음성 재생
}
};
play.addActionListener(playListener); // 재생 버튼에 핸들러 적용
content.add(play, BorderLayout.SOUTH); // 재생 버튼 위치
running = true;
}
private void captureAudio() {
try {
final AudioFormat format = getFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
final TargetDataLine line = (TargetDataLine)AudioSystem.getLine(info);
line.open(format);
line.start();
Runnable runner = new Runnable() {
int bufferSize = (int)format.getSampleRate() * format.getFrameSize();
byte buffer[] = new byte[bufferSize];
public void run() {
out = new ByteArrayOutputStream();
running = true;
try {
while (running) {
int count = line.read(buffer, 0, buffer.length);
if (count > 0) {
out.write(buffer, 0, count);
}
}
out.close();
} catch (IOException e) {
System.err.println("I/O problems: " + e);
System.exit(-1);
}
}
};
Thread captureThread = new Thread(runner);
captureThread.start();
} catch (LineUnavailableException e) {
System.err.println("Line unavailable: " + e);
System.exit(-2);
}
}
private void playAudio() {
try {
byte audio[] = out.toByteArray();
InputStream input = new ByteArrayInputStream(audio);
final AudioFormat format = getFormat();
final AudioInputStream ais = new AudioInputStream(input, format, audio.length
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
final SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
line.open(format);
line.start();
Runnable runner = new Runnable() {
int bufferSize = (int) format.getSampleRate() * format.getFrameSize();
byte buffer[] = new byte[bufferSize];
public void run() {
try {
int count;
while ((count = ais.read( buffer, 0, buffer.length)) != -1) {
if (count > 0) {
line.write(buffer, 0, count);
}
}
line.drain();
line.close();
} catch (IOException e) {
System.err.println("I/O problems: " + e);
System.exit(-3);
}
}
};
Thread playThread = new Thread(runner);
playThread.start();
} catch (LineUnavailableException e) {
System.err.println("Line unavailable: " + e);
System.exit(-4);
}
}
private AudioFormat getFormat() { // AudioFormat 형식
float sampleRate = 8000; // 샘플 수
int sampleSizeInBits = 8; // 비트 당 샘플 size
int channels = 1; // 채널 수
boolean signed = true; // 부호 여부
boolean bigEndian = true; // bigEndian 여부
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}
@SuppressWarnings("deprecation")
public static void main(String args[]) {
JFrame frame = new Capture();
frame.pack();
frame.show();
}
}
또 녹음본을 wav 형식의 파일로 저장하고싶은데 어떤식으로 코드를 짜야하는지 조언 부탁드립니다!
구글링 해보면서 나온 방식들은 안드로이드 앱 제작할 때 사용하는 방식이던데 같은 방식으로 해도 상관 없는건지도 궁금합니다.
감사합니다!
예외 처리가 되었을 때 출력된 예외 처리 메시지를 댓글로 남겨주시면 한번 확인해보겠습니다.
그리고 .wav 파일로 저장하는 방법은 아래 코드를 참고해보시기 바랍니다.