为什么没有TargetDataLine.read()在设备断开连接时抛出任何异常?

时间:2018-01-24 17:31:47

标签: java audio-recording javasound

根据文档,TargetDataLine.read()是一种阻塞方法,即调用read()块,直到它具有可读取的请求字节数。但是,如果数据行已关闭,已停止,已耗尽或已刷新,则会立即返回。

我有一个实时应用程序,可以无限期地从音频接口读取和处理数据。我的音频设备通过USB连接与计算机连接。如果在读取数据时拔下USB连接,我的应用程序将无限期地阻止read()方法而不会引发任何异常。是预期的行为还是有任何方法可以检测到物理连接已被删除?

更新1: Bellow代码段可以重现此问题。

public class TestSoundCapture {

    public TestSoundCapture() {
        new Thread(new CaptureBack()).start();
    }

    public static void main(String[] args) {
        new TestSoundCapture();
    }

    private class CaptureBack implements Runnable {

        public CaptureBack() { }

        @Override
        public void run() {
            int numBytesRead = 0;
            byte[] shortBuffer = new byte[2048];

            final TargetDataLine dataLine = getDataLine();
            dataLine.start();  // begin audio capture. 

            while (true) {
                try {
                    numBytesRead = dataLine.read(shortBuffer, 0, shortBuffer.length);
                    Thread.sleep(20);
                } 
                catch (Exception e) {
                    System.out.println("Exception: "+e.toString());
                    break;
                }
                System.out.println("Store "+numBytesRead+" in a circular buffer");
            }           

            // stop and close the line.
            dataLine.stop();
            dataLine.close();
            System.out.println("Capturing Finished!");
        } 

        private TargetDataLine getDataLine() {
            AudioFormat aFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100.0F, 16, 2, 4, 44100.0F, false);
            TargetDataLine line = null;
            DataLine.Info info = new DataLine.Info(TargetDataLine.class, aFormat);

            try {
                line = (TargetDataLine) AudioSystem.getLine(info);
                line.open(aFormat);
            } 
            catch (LineUnavailableException ex) {
            }  

            return line;
        }
    }
}

当音频设备断开连接时,后台线程卡在read()方法上。

更新2:即使我认为我不喜欢它,在尝试阅读之前,可能还有一种方法是检查available()。具体来说,调用read() iff available()返回更多或相等数量的字节,我想读取。

int counter = 0;  // counts number of consecutive failed attempt.
final int buffSize = 2048;

while (true) {
     if (counter > 3) break;   // no data available on the line.

     Thread.sleep(20);

     if (dataLine.available() < buffSize) {
         counter++;
         continue;
     }
     else {
         numBytesRead = dataLine.read(shortBuffer, 0, buffSize);
         counter = 0;
     }                        

     System.out.println("Store "+numBytesRead+" in a circular buffer");
}

0 个答案:

没有答案