Android Java:如何在流式传输系统音频时禁用麦克风输入?

时间:2014-07-08 09:51:03

标签: android audio microphone mute android-audiomanager

基本上,我的程序通过麦克风记录用户输入,并将其作为.pcm文件存储在sdcard /目录中。如果存在现有的,它将被覆盖。然后发送该文件进行回放和分析(主要是FFT,RMS计算)。

我添加了另一个允许程序录制系统音频的功能,因此它也可以分析用户的mp3文件。它流式传输系统音频并将其存储为.pcm文件,以便以后播放和分析。

一切运转良好。然而,有一个小问题,当程序流式传输音频时,它会捕获来自麦克风的输入,并且播放中会有噪音。我不想这样,因为它会影响分析阅读。我搜索了一个解决方案,发现我实际上可以将麦克风静音。所以现在,我想在播放mp3文件时将麦克风静音。

我找到的代码是,

  

AudioManager.setMicrophoneMute(真);

我试图实现它,但它只是崩溃了我的应用程序。这几天我试图寻找解决方案,但我似乎无法得到任何解决方案。

这是我想要在开始流式传输之前流式传输系统音频和静音麦克风的部分的代码片段。

  

//创建一个新的AudioRecord对象来记录mp3文件的音频数据             int bufferSize = AudioRecord.getMinBufferSize(frequency,channelConfiguration,audioEncoding);

      audioRecord = new AudioRecord(AudioManager.STREAM_MUSIC, 
              frequency, channelConfiguration, 
              audioEncoding, bufferSize);

      //a short array to store raw pcm data
      short[] buffer = new short[bufferSize];   
      Log.i("decoder", "The audio record created fine ready to record");

      try {
          audioManager.setMicrophoneMute(true);
      } catch (Exception e) {
          e.printStackTrace();
      }


      audioRecord.startRecording();
      isDecoding = true;

当setMicrophoneMute(true)行被try-catch包围时,程序只会在我想发送回放的录音时崩溃。错误如下:
“AudioFlinger无法创建曲目,状态:-12”
“初始化AudioTrack时出错”
“[android.media.AudioTrack]初始化AudioTrack时出现错误代码-20。”

当它没有被try-catch包围时,程序只会在我点击开始流媒体按钮时崩溃。 “解码失败”<这是捕获throwable的错误日志。

如何在流式传输系统音频时将麦克风输入静音?如果我能为您提供更多代码,请与我们联系。谢谢!

**修改 我成功地实现了我的mutemicrophone,它甚至给我一个真实的isMicrophoneMute(),然而,它没有静音,因为它仍然从麦克风录制;这是假的。

根据建议的答案,我已经创建了一个音频焦点类,如下所示:

private final Context c;

private final AudioManager.OnAudioFocusChangeListener changeListener =
    new AudioManager.OnAudioFocusChangeListener()
    {
        public void onAudioFocusChange(int focusChange)
        {
            //nothing to do
        }
    };


AudioFocus(Context context)
{
    c = context;
}


public void grabFocus()
{
    final AudioManager am = (AudioManager) c.getSystemService(Context.AUDIO_SERVICE);
    final int result = am.requestAudioFocus(changeListener,
                                            AudioManager.STREAM_MUSIC,
                                            AudioManager.AUDIOFOCUS_GAIN);
    Log.d("audiofocus","Grab audio focus: " + result);
}


public void releaseFocus()
{
    final AudioManager am = (AudioManager) c.getSystemService(Context.AUDIO_SERVICE);
    final int result = am.abandonAudioFocus(changeListener);
    Log.d("audiofocus","Abandon audio focus: " + result);
}

然后我从我的Decoder类调用该方法来请求音频焦点:

        int bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration,  audioEncoding);

        audioFocus.grabFocus();

        audioRecord = new AudioRecord(AudioManager.STREAM_MUSIC, 
                frequency, channelConfiguration, 
                audioEncoding, bufferSize);

        //a short array to store raw pcm data
        short[] buffer = new short[bufferSize];   
        Log.i("decoder", "The audio record created fine ready to record");


            audioRecord.startRecording();
            isDecoding = true;

            Log.i("decoder", "Start recording fine");

然后在按下停止解码时释放焦点:

//stops recording
public void stopDecoding(){
    isDecoding = false;
    Log.i("decoder", "Out of recording");
    audioRecord.stop();

    try {
        dos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    mp.stop();
    mp.release();
    audioFocus.releaseFocus();
}

然而,这使我的应用程序崩溃。我哪里出错了?

1 个答案:

答案 0 :(得分:0)

以下代码段请求音乐音频流上的永久音频焦点。您应该在开始播放之前立即请求音频焦点,例如当用户按下播放时。我认为这将是一种方法,而不是将输入麦克风静音。查看开发人员audio focus文档以获取更多信息

AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...

// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
                                 // Use the music stream.
                                 AudioManager.STREAM_MUSIC,
                                 // Request permanent focus.
                                 AudioManager.AUDIOFOCUS_GAIN);

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    am.registerMediaButtonEventReceiver(RemoteControlReceiver);
    // Start playback.
}