即时音频输入和输出 Android

Immediate Audio Input & Output Android

在我的 Android 应用程序中,我想从智能手机的麦克风中获取一些音频并立即播放,就像麦克风一样,没有延迟。我目前正在考虑使用 AudioRecordAudioTrack 类(据我所读),但我不太确定如何进行。

我在 Stack Overflow 上查看了其他一些问题,但它们并没有完全回答我想做的事情。大多数是 2012 年的。

那么如何使用这些类同时输入和输出音频?

另外: 我看过 MediaRecorder API,但根据我的阅读,这要求您将音频保存到文件中,而我没有这样做不想做。可以tweeked来满足我的要求吗?或者我最好只使用 AudioRecord?

谢谢

编辑:

下面是我根据@Pradip Pramanick 建议更新的代码:

final Thread record = new Thread(new Runnable() {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                MediaRecorder microphone = new MediaRecorder();
                microphone.setAudioSource(MediaRecorder.AudioSource.MIC);
                    microphone.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                microphone.setOutputFile(filename);
                microphone.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                try {
                    microphone.prepare();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                microphone.start();
            }
        }
    });

    final Thread play = new Thread(new Runnable() {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                player = new MediaPlayer();
                try {
                    player.setDataSource(filename);
                    player.prepare();
                    player.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    });

我收到 Illegal State Exception | Start failed: -38。但是我在 microphone.prepare 之后调用 microphone.start... 似乎是什么问题?我搜索了其他线程,这些线程说可能有其他后台应用程序使用麦克风。我搜索了我的设备:Moto X Play(第 3 代)并找到 none。 (我什至关闭了"Ok Google"语音识别,但错误不断。

错误日志:

这是显示最新错误的日志猫:

01-31 09:37:21.064 344-3339/? E/MediaPlayerService: offset error
01-31 09:37:21.065 1835-1922/com.synerflow.testapp E/MediaPlayer: Unable to create media player

01-31 09:37:21.065 1835-1922/com.synerflow.testapp I/Player: player.prepare() has failed
01-31 09:37:21.065 1835-1922/com.synerflow.testapp W/System.err: java.io.IOException: setDataSourceFD failed.: status=0x80000000

IO异常似乎在player.setDataSource(filename),文件名变量是一个字符串:Environment.getExternalStorageDirectory().getAbsolutePath() + "\voice.3gp"

据我所知,这可以通过一种非常简单的方式完成。我没试过,你试试看。我认为它会起作用:

创建两个线程,一个用于录制,一个用于播放。 假设线程是 TRecord 和 TPlay。

在 TRecord 的 运行 方法中执行此操作:

public void run(){
        MediaRecorder mRecorder = null;
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mRecorder.setOutputFile(mFileName);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            mRecorder.prepare();
        } catch (IOException e) {
            //todo
        }

        mRecorder.start();
}

TPlay 的 运行 方法是这样做的:

public void run() {
MediaPlayer   mPlayer = null;
mPlayer = new MediaPlayer();
        try {
            mPlayer.setDataSource(mFileName);
            mPlayer.prepare();
            mPlayer.start();
        } catch (IOException e) {
            //todo
        }
}

现在在 mainactivity 上简单地创建两个线程。首先启动 TRecord 线程,然后启动 Tplay。试试吧。

这里是文件扩展名的代码:

mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
 mFileName += "/audiorecordtest.3gp";

这在 Android 上实际上非常棘手。 Google 自己有很好的(但略长) video 解释问题。

他们还有 a page explaining their latency testing methods and benchmarks 用于各种设备。

本质上,stock Android 不能做 zero-latency 音频,但是没有什么能阻止硬件合作伙伴添加所需的硬件和平台扩展来做到这一点。

试试这个。我没有运行这个。

      recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
      RECORDER_SAMPLERATE, RECORDER_CHANNELS,
      RECORDER_AUDIO_ENCODING, bufferSize * BytesPerElement);

    recorder.startRecording();

    isRecording = true;

    recordingThread = new Thread(new Runnable() {

     public void run() {

      try {
          int intSize = android.media.AudioTrack.getMinBufferSize(RECORDER_SAMPLERATE,AudioFormat.CHANNEL_OUT_MONO , RECORDER_AUDIO_ENCODING);
          byte[] sData = new byte[bufferSize];
          AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, RECORDER_SAMPLERATE, AudioFormat.CHANNEL_OUT_MONO, RECORDER_AUDIO_ENCODING, intSize, AudioTrack.MODE_STREAM);
          while(isRecording){
          recorder.read(sData, 0, bufferSize);  //isRecording = false; onStop button

          if (at!=null) { 
              at.play();
              // Write the byte array to the track
              at.write(sData, 0, sData.length); 
              at.stop();
              at.release();
          }
          }
    } catch (IOException e) {
        e.printStackTrace();
    }
 }
  }, "AudioRecorder Thread");
    recordingThread.start();

你可以试试Google双簧管。

Oboe is a C++ library that makes it easy to build high-performance audio apps on Android.

Oboe 已经有一个“即时音频输入和输出 Android”的示例

LiveEffect Sample

This sample simply loops audio from the input stream to the output stream to demonstrate the usage of the 2 stream interfaces.

https://github.com/google/oboe/tree/master/samples/LiveEffect