Java
오디오 녹음 후 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 형식의 파일로 저장하고싶은데 어떤식으로 코드를 짜야하는지 조언 부탁드립니다!

구글링 해보면서 나온 방식들은 안드로이드 앱 제작할 때 사용하는 방식이던데 같은 방식으로 해도 상관 없는건지도 궁금합니다.

감사합니다!

댓글 1