【问题标题】:Stream Audio from internal Microphone to 3.5mm headphone jack将音频从内置麦克风流式传输到 3.5 毫米耳机插孔
【发布时间】:2026-02-24 07:45:01
【问题描述】:

我有一个简单的问题:

如何将 Android 设备变成现代麦克风? ,

我不想录制音频,我只想:

  1. 说话

  2. 音频被转发到连接扬声器的 3.5 插孔输出(无输入),例如,

谢谢。

编辑:这是我正在使用的代码,感谢所有在这里做出贡献的人,感谢 @user1917769 的工作答案,我没有任何滞后,它作为真正的麦克风设备工作正常:

 import android.media.AudioFormat;
 import android.media.AudioManager;
 import android.media.AudioRecord;
 import android.media.AudioTrack;
 import android.media.MediaRecorder;
 import android.media.MediaRecorder.AudioSource;
 import android.util.Log;

 public class TOne extends Thread {
 private Thread T1;
 private byte audiobuffer[] = new byte[20];
 public boolean Okay = true;
 public AudioRecord a;
 public AudioTrack aud;
 private static int[] mSampleRates = new int[] { 8000, 11025, 22050, 44100 };
 @Override
 public void run() {
 // TODO Auto-generated method stub
 //super.run();
int i=AudioRecord.getMinBufferSize(8000 , AudioFormat.CHANNEL_IN_MONO ,      AudioFormat.ENCODING_PCM_16BIT);
a= findAudioRecord();

if(a.getState() != AudioRecord.STATE_INITIALIZED){
   a= findAudioRecord();  
 }
  a.startRecording();
    Log.e("Play Audio" , "Start");

 aud = new AudioTrack(AudioManager.STREAM_MUSIC,8000,
         AudioFormat.CHANNEL_OUT_MONO,   AudioFormat.ENCODING_PCM_16BIT,AudioTrack.getMinBufferSize(8000,AudioFormat.CHANNEL_OUT_MONO,
     AudioFormat.ENCODING_PCM_16BIT),AudioTrack.MODE_STREAM);

 if(aud.getState() != AudioTrack.STATE_INITIALIZED){
aud = new AudioTrack(AudioManager.STREAM_MUSIC,8000,
         AudioFormat.CHANNEL_OUT_MONO,      AudioFormat.ENCODING_PCM_16BIT,AudioTrack.getMinBufferSize(8000,AudioFormat.CHANNEL_OUT_MONO,
         AudioFormat.ENCODING_PCM_16BIT),AudioTrack.MODE_STREAM);

 }
          aud.play();
         while(Okay){


                 a.read(audiobuffer,0,audiobuffer.length);

                        ////Log.e("IS_ACTIVE", "YES");
                         aud.write(audiobuffer,0,audiobuffer.length);



 }



 }


 public AudioRecord findAudioRecord() {

for (int rate : mSampleRates) {
    for (short audioFormat : new short[] { AudioFormat.ENCODING_PCM_8BIT,      AudioFormat.ENCODING_PCM_16BIT }) {
        for (short channelConfig : new short[] { AudioFormat.CHANNEL_IN_MONO,      AudioFormat.CHANNEL_IN_STEREO }) {
            try {
                Log.d("C.TAG", "Attempting rate " + rate + "Hz, bits: " + audioFormat +      ", channel: "
                        + channelConfig);
                int bufferSize = AudioRecord.getMinBufferSize(rate,      AudioFormat.CHANNEL_IN_MONO , AudioFormat.ENCODING_PCM_16BIT);

                if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
                    // check if we can instantiate and have a success
                    AudioRecord recorder = new AudioRecord(AudioSource.MIC, 8000,      channelConfig, audioFormat, bufferSize);

                    if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
                        return recorder;
                }
            } catch (Exception e) {
                Log.e("C.TAG", rate + "Exception, keep trying.",e);
            }
        }
    }
}
return null;
 }

 private void LetsPlayThatsAudio() {
// TODO Auto-generated method stub







 }


 }

但我正在考虑将其放入实现线程的服务中,以便我可以轻松启动/停止

【问题讨论】:

  • 如果您这样做,将会有一些延迟,可能长达 100 毫秒,具体取决于所使用的设备和 Android 版本。没有办法(至少对于应用程序而言)创建从音频输入到音频输出的直接环回。
  • 好的,感谢您的注意,我将尝试建议的答案...
  • 回滚第 3 方编辑 - 问题的主题是流式传输,而不是重定向,因为通常没有输入输出路径 - 必须创建,而不是重新路由。
  • 谢谢@Chris Stratton
  • 我正在为我的卡拉 OK 应用寻找一段代码,您的代码从您的声音到扬声器是否有任何延迟?我明天试试!谢谢!

标签: android audio mediarecorder


【解决方案1】:

为此,您必须先从移动麦克风录制声音,然后同时在手机上播放。对于录制工作,请在线程 1 中尝试此操作并在音频缓冲区字节数组中获取数据

        int i=AudioRecord.getMinBufferSize(8000,
        AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCO DING_PCM_16BIT);
        AudioRecord a= new AudioRecord(MediaRecorder.AudioSource.MIC,8000,
        AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT,i);
        a.startRecording();
        byte audiobuffer[]=new byte[20];
        new thread2().start();
        while(true)
        {
             a.read(audiobuffer,0,audiobuffer.length);
        }

在播放将声音输出到 3.5 毫米插孔的数据的同时尝试此代码 在线程 2 中

 AudioTrack aud= new AudioTrack(AudioManager.STREAM_MUSIC,8000,
 AudioFormat.CHANNEL_CONFIGURATION_MONO,       AudioFormat.ENCODING_PCM_16BIT,AudioTrack.getMinBufferSize(8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,
 AudioFormat.ENCODING_PCM_16BIT),AudioTrack.MODE_STREAM);
 aud.play();
while(true)
{ 
    aud.write(audiobuffer,0,audiobuffer.length);

}

【讨论】:

  • 感谢您的回答,我同意@Chris Stratton 以及使用 MediaRecorder 和 MediaPlayer 有什么区别?所以不需要将音频写入文件然后使用这种方式播放它,线程一接收音频,线程 2 播放线程一中接收到的音频
  • 只要两个调用使用相同的采样时钟,并且API下面的代码对内部缓冲是理智的,您可以顺序调用输入的读取方法和输出的写入方法在单个线程内的循环中。但是请注意,从输入到输出可能会有明显的延迟,这取决于缓冲区的大小......尝试通过它交谈(如果你能听到输出)可能会非常困难。
  • 在我编辑的代码中从 thread1 启动 thread2。两个线程将在同一个类中。它们将使用相同的字节数组类变量。除此之外,您不需要任何额外的同步。我使用了两个线程最大限度地减少播放该数据的延迟。
  • 所以我需要在同一个线程类中录制/播放?因为 aud.write(audiobuffer,0,audiobuffer.length);如果我有两个单独的线程类,将为 null 吗?
  • 很抱歉,但坚持建议使用损坏的线程可以获得 -1
最近更新 更多