android - 实时播放来自麦克风的声音

标签 android audio real-time record audio-recording

我一直在尝试让我的应用程序记录来自麦克风的声音并(大约)实时回放,但没有成功。

我分别使用 AudioRecord 和 AudioTrack 类进行录制和播放。我尝试了不同的方法,我尝试记录传入的声音并将其写入文件并且效果很好。我还尝试在使用 AudioTrack 之后播放该文件中的声音,并且效果也很好。问题是当我尝试实时播放声音时,而不是在文件写入后读取。

代码如下:

//variables
private int audioSource = MediaRecorder.AudioSource.MIC;
private int samplingRate = 44100; /* in Hz*/
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private int bufferSize = AudioRecord.getMinBufferSize(samplingRate, channelConfig, audioFormat);
private int sampleNumBits = 16;
private int numChannels = 1;

// …

AudioRecord recorder = new AudioRecord(audioSource, samplingRate, channelConfig, audioFormat, bufferSize);
                recorder.startRecording();
                isRecording = true;

AudioTrack audioPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                        AudioFormat.ENCODING_PCM_16BIT, bufferSize, AudioTrack.MODE_STREAM);

if(audioPlayer.getPlayState() != AudioTrack.PLAYSTATE_PLAYING)
    audioPlayer.play();

//capture data and record to file
int readBytes=0, writtenBytes=0;
do{
   readBytes = recorder.read(data, 0, bufferSize);

   if(AudioRecord.ERROR_INVALID_OPERATION != readBytes){
      writtenBytes += audioPlayer.write(data, 0, readBytes);
   }
}
while(isRecording);

抛出 java.lang.IllegalStateException 的原因是“在未初始化的 AudioTrack 上调用 play()”。

但是,如果我更改 AudioTrack 初始化,例如使用 8000Hz 采样率和 8 位采样格式(而不是 16 位),它不会再抛出异常并且应用程序会运行,尽管它会产生可怕的噪音。

当我从文件播放 AudioTrack 时,AudioTrack 的初始化没有问题,我尝试了 44100 和 16 位,它工作正常,产生了正确的声音。

有什么帮助吗?

最佳答案

所有原生 Android 音频都是 encoded .你只能玩PCM实时格式,或使用特殊的 streaming编解码器,我认为这在 Android 上并不重要。

关键是,如果您想同时录制/播放音频,则必须创建自己的音频缓冲区并在其中存储原始 PCM 编码的音频样本(我不确定您是否在考虑 duh! 或者这是否在你的脑海中,所以我会尽量保持清醒,但不要咀嚼你自己的口香糖)。

PCM 是模拟信号的数字表示,其中您的音频samples是一组原始声波的“快照”。因为各种聪明的数学家和工程师都看到了尝试减少表示这些数据的位数的潜力,所以他们想出了各种 encoders .编码(压缩)信号的表示方式与原始 PCM 信号非常不同,必须对其进行解码(en-cod-er+dec-oder = codec)。除非您使用特殊算法和媒体流编解码器,否则不可能像您尝试的那样播放编码信号,因为它不是逐个样本编码,而是逐帧编码,您需要整个样本帧,如果不是完整的信号,则解码此帧。

这样做的方法是手动存储来自麦克风缓冲区的音频样本,然后手动将它们输入到输出缓冲区。您将不得不为此进行一些编码,但我相信您可以查看一些开源应用程序并在其源代码上达到顶峰(当然,除非您愿意稍后出售您的应用程序,但那是完全不同的讨论)。

如果您正在为 Android 2.3 或更高版本开发并且不太害怕在 native code 中进行编程,您可以尝试使用OpenSL ES .列出了 OpenSL ES 的 Android 特定功能 here .该平台允许您更灵活地处理音频,如果您的应用高度依赖音频处理,您可能会找到所需的内容。

关于android - 实时播放来自麦克风的声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5728454/

相关文章:

Android:自定义微调器大小问题

android - 在 Android 日期选择器中选择值后无法定位其他元素

audio - 无法播放带有声音的 AVMutableComposition

java - 如何检测音频流中特定单词的出现。

java - 我可以通过 JNI 从 Java 调用的 EPoll C 实现

ios - 同一网络中 iOS 设备之间的实时语音聊天

android - 在 TextView/EditText 中点击一个单词

android - 构建通知时出错

ios - 如何使用StreamingKit保存流音频?

c - 如何为 program.c 创建 makefile 以及如何在实时应用程序接口(interface)中编译和执行