Java Sound обновляет список линий после подключения микрофона - PullRequest
6 голосов
/ 26 марта 2012

У меня есть простое приложение Swing для захвата / воспроизведения, которое должно обнаружить, если к компьютеру не подключен соответствующий микрофон, и предупредить пользователя.После долгих раздумий я нашел единственное решение, которое позволило мне обнаружить вновь подключенный или снятый микрофон:

     com.sun.media.sound.JDK13Services.setCachingPeriod(0);

     private static boolean isMicrophoneAvailable() {
        try {
            if (!AudioSystem.isLineSupported(Port.Info.MICROPHONE)) {
                log.debug("NO MICROPHONE FOUND");
                return false;
            } else {
                log.debug("MICROPHONE FOUND");
                return true;
            }
        } catch (IllegalArgumentException e) {
            log.debug("INCONSISTENT");
        }
        return false;
    }

, вызванный в фоновом потоке, например:

   new Thread() {
       public void run() {
            while(!thisFrame.isClosed()){
                if(isMicrophoneAvailable() == true){
                     //OK
                }else{
                     //WARN
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
      }
    }).start();

Проблема заключается в том, что хотя устройство правильно определяется с использованием описанного метода, список базовых строк не обновляется.То есть, когда программа запускается, а устройство подключается позднее, при попытке записи звука выдается следующее исключение:

 java.lang.IllegalArgumentException: No line matching interface TargetDataLine supporting format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, big-endian is supported.

Есть ли способ обновить список строк AudioSystem?Может быть, что-то похожее на обходной путь JDK13Services, используемый в самом начале, чтобы избежать кэширования?

ОБНОВЛЕНИЕ: Код, который выдает исключение:

        AudioFormat format = formatControls.getDefaultFormat();
        DataLine.Info info = new DataLine.Info(TargetDataLine.class,format);
        try {
            line = (TargetDataLine) AudioSystem.getLine(info);
            line.open(format, line.getBufferSize());
        } catch (LineUnavailableException ex) {
            shutDown("No audio input device available. Please make sure that a microphone is attached to your computer");
            return;
        } catch (Exception ex) {
            log.error(ex.toString());
            shutDown(ex.toString());
            return;
        }

и Исключениесам:

 java.lang.IllegalArgumentException: No line matching interface TargetDataLine supporting format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, big-endian is supported.

Ответы [ 2 ]

1 голос
/ 19 ноября 2013

Используя оригинальный пост в качестве вдохновения, я придумал это как средство для определения, когда микрофон потерян или приобретен. Он обнаруживает (в моей системе), когда USB-микрофон подключен или отключен. Я звоню из фонового цикла. Оригинальный метод не работал для меня, так как на ноутбуке есть встроенный микрофон, поэтому мне нужно было обнаружить добавление второго микрофона.

...
//call this once somewhere to turn the caching period down for faster detection
    try
    {
        //try to set the caching period, defaults to something like 55 seconds
        com.sun.media.sound.JDK13Services.setCachingPeriod(5);
    }
    catch( Exception e)
    {
        System.err.println("exception attempting to call com.sun.media.sound.JDK13Services.setCachingPeriod->" + e);
    }
...

private int lastNumMics = -1;
private synchronized void micCheck()
{
    Line.Info[] lineInfoArray = AudioSystem.getSourceLineInfo(Port.Info.MICROPHONE);
    int numMics = lineInfoArray == null ? 0 : lineInfoArray.length;
    if( lastNumMics > -1 )
    {
        if( numMics < lastNumMics )
        {
            //MICROPHONE_LOST
        }
        else if( numMics > lastNumMics )
        {
            //MICROPHONE_GAINED
        }
    }
    lastNumMics = numMics;
}
0 голосов
/ 28 марта 2012

Размещение кода, который выдает исключение, может помочь.

Я предполагаю, что вы используете Port.Info только для обнаружения присутствия микрофона, а затем получаете Dataline для записи:

TargetDataLine dataLine = (TargetDataLine) AudioSystem.getLine(new DataLine.Info(TargetDataLine.class, audioFormat));                       
dataLine.open();
dataLine.start();               
dataLine.read(b, offset, len);

Обратите внимание, что вы все равно можете получить аналогичное исключение при отключении микрофона, если микрофон физически отключен между временем, когда вы проверяете наличие, и временем, когда вы пытаетесь получить Dataline для записи, но при подключении микрофона не должно быть проблем.

...