2012-03-26 1 views
5

コンピュータに適切なマイクが接続されていないかどうかを検出し、ユーザーに警告するシンプルなキャプチャ/再生スイングアプリがあります。このように、バックグラウンドスレッドで呼び出さJavaサウンドリフレッシュマイクを付けた後のラインリスト

 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回避策に類似したものを使用していますか?

UPDATE:例外をスローコード:

 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. 
+0

興味深い質問、+1。しかし、あなたは 'com.sun'パッケージでクラスを使うことの脆弱性を認識していますか?存在するJREであっても、次のバージョンで削除/移動/名前変更される可能性があります。 –

+0

確かに、これは少なくとも悪い習慣であることを認識していますが、実際は私の最後の手段でした。 Java Soundの実装上の欠陥であると考えられます。 –

+0

多くのうちの1つです。 JavaSoundは、サポートすることを目的とする限られた範囲のものには適していますが、Sunはこれをさらに発展させることはありません。 –

答えて

0

例外が役立つかもしれないスローコードを投稿。マイクを取り外すとき、あなたはまだ同様の例外を取得する可能性があります

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

注:

私はあなただけを記録し、その後データラインを取得し、マイクの存在を検出するためにPort.Infoを使用していると仮定しています存在を確認してからデータラインに録音しようとする時間の間にマイクが物理的に切断されていても、マイクロホンを接続しても問題ありません。

+0

私はほとんど同じことをしているようです。とにかく、私はコードと例外で質問を更新しました。 –

+0

ラインがそのオーディオフォーマットをサポートしていることを確認してください。ラインでサポートされているすべてのオーディオフォーマットを一覧表示するには AudioFormat adfs [] =((DataLine.Info)dataLine.getLineInfo())。getFormats(); for(AudioFormat adf:adfs){ System.out.println(adf.toString()); } – msam

+0

あなたのアイデアはあまりありません。 line =(TargetDataLine)AudioSystem。getLine(info);例外がスローされた場所なので、最初はその行を取得できません。たぶん私は十分にはっきりしていなかった:プログラムの開始前にコンピュータに接続されていれば、マイクロフォンは正常に動作する。切断が正しく検出され、「記録」ボタンが無効になります。プラグが差し込まれると再び動作します。この問題は、jvm startの前にマイクが接続されていないと発生します。この場合、たとえPort.Info.MICROPHONEが検出されたとしても、その行はまだ機能していません。 –

0

オリジナルのポストをインスピレーションとして使用して、マイクを紛失したときを検出する方法としてこれを考え出しました。それは、USBマイクが差し込まれているか、または差し込まれているかを私のシステム上で検出します。バックグラウンドスレッドループから呼び出しています。ラップトップにマイクが内蔵されているので、元の方法ではうまくいかなかったので、2番目のマイクを追加する必要がありました。

... 
//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; 
} 
関連する問題