Android:需要录制麦克风输入

发布于 2024-11-28 06:53:17 字数 261 浏览 3 评论 0原文

有没有办法在实时播放/预览过程中记录 Android 中的麦克风输入?我尝试使用 AudioRecordAudioTrack 来执行此操作,但问题是我的设备无法播放录制的音频文件。实际上,任何Android播放器应用程序都无法播放录制的音频文件。

另一方面,使用Media.Recorder 进行录音会生成一个录制好的音频文件,可以由任何播放器应用程序播放。但问题是我无法在实时录制麦克风输入时进行预览/回放。

Is there a way to record mic input in android while it is being process for playback/preview in real time? I tried to use AudioRecord and AudioTrack to do this but the problem is that my device cannot play the recorded audio file. Actually, any android player application cannot play the recorded audio file.

On the other hand, Using Media.Recorder to record generates a good recorded audio file that can be played by any player application. But the thing is that I cannot make a preview/palyback while recording the mic input in real time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暮凉 2024-12-05 06:53:17

要(几乎)实时录制和播放音频,您可以启动一个单独的线程并使用 AudioRecordAudioTrack

只是要小心反馈。如果您的设备上的扬声器开得足够大,反馈可能会很快变得非常令人讨厌。

/*
 * Thread to manage live recording/playback of voice input from the device's microphone.
 */
private class Audio extends Thread
{ 
    private boolean stopped = false;

    /**
     * Give the thread high priority so that it's not canceled unexpectedly, and start it
     */
    private Audio()
    { 
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
        start();
    }

    @Override
    public void run()
    { 
        Log.i("Audio", "Running Audio Thread");
        AudioRecord recorder = null;
        AudioTrack track = null;
        short[][]   buffers  = new short[256][160];
        int ix = 0;

        /*
         * Initialize buffer to hold continuously recorded audio data, start recording, and start
         * playback.
         */
        try
        {
            int N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);
            recorder = new AudioRecord(AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10);
            track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, 
                    AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10, AudioTrack.MODE_STREAM);
            recorder.startRecording();
            track.play();
            /*
             * Loops until something outside of this thread stops it.
             * Reads the data from the recorder and writes it to the audio track for playback.
             */
            while(!stopped)
            { 
                Log.i("Map", "Writing new data to buffer");
                short[] buffer = buffers[ix++ % buffers.length];
                N = recorder.read(buffer,0,buffer.length);
                track.write(buffer, 0, buffer.length);
            }
        }
        catch(Throwable x)
        { 
            Log.w("Audio", "Error reading voice audio", x);
        }
        /*
         * Frees the thread's resources after the loop completes so that it can be run again
         */
        finally
        { 
            recorder.stop();
            recorder.release();
            track.stop();
            track.release();
        }
    }

    /**
     * Called from outside of the thread in order to stop the recording/playback loop
     */
    private void close()
    { 
         stopped = true;
    }

}

编辑

音频并未真正录制到文件中。 AudioRecord 对象将音频编码为 16 位 PCM 数据 并将其放入缓冲区中。然后,AudioTrack 对象从该缓冲区读取数据并通过扬声器播放。 SD 卡上没有您稍后可以访问的文件。

您无法同时从 SD 卡读取和写入文件来实时播放/预览,因此必须使用缓冲区。

To record and play back audio in (almost) real time you can start a separate thread and use an AudioRecord and an AudioTrack.

Just be careful with feedback. If the speakers are turned up loud enough on your device, the feedback can get pretty nasty pretty fast.

/*
 * Thread to manage live recording/playback of voice input from the device's microphone.
 */
private class Audio extends Thread
{ 
    private boolean stopped = false;

    /**
     * Give the thread high priority so that it's not canceled unexpectedly, and start it
     */
    private Audio()
    { 
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
        start();
    }

    @Override
    public void run()
    { 
        Log.i("Audio", "Running Audio Thread");
        AudioRecord recorder = null;
        AudioTrack track = null;
        short[][]   buffers  = new short[256][160];
        int ix = 0;

        /*
         * Initialize buffer to hold continuously recorded audio data, start recording, and start
         * playback.
         */
        try
        {
            int N = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT);
            recorder = new AudioRecord(AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10);
            track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, 
                    AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, N*10, AudioTrack.MODE_STREAM);
            recorder.startRecording();
            track.play();
            /*
             * Loops until something outside of this thread stops it.
             * Reads the data from the recorder and writes it to the audio track for playback.
             */
            while(!stopped)
            { 
                Log.i("Map", "Writing new data to buffer");
                short[] buffer = buffers[ix++ % buffers.length];
                N = recorder.read(buffer,0,buffer.length);
                track.write(buffer, 0, buffer.length);
            }
        }
        catch(Throwable x)
        { 
            Log.w("Audio", "Error reading voice audio", x);
        }
        /*
         * Frees the thread's resources after the loop completes so that it can be run again
         */
        finally
        { 
            recorder.stop();
            recorder.release();
            track.stop();
            track.release();
        }
    }

    /**
     * Called from outside of the thread in order to stop the recording/playback loop
     */
    private void close()
    { 
         stopped = true;
    }

}

EDIT

The audio is not really recording to a file. The AudioRecord object encodes the audio as 16 bit PCM data and places it in a buffer. Then the AudioTrack object reads the data from that buffer and plays it through the speakers. There is no file on the SD card that you will be able to access later.

You can't read and write a file from the SD card at the same time to get playback/preview in real time, so you have to use buffers.

z祗昰~ 2024-12-05 06:53:17

需要清单中的以下权限才能正常工作:

<uses-permission android:name="android.permission.RECORD_AUDIO" ></uses-permission>

此外,不需要 2d 缓冲区数组。即使只有一个缓冲区,代码的逻辑也是有效的,如下所示:

short[] buffer = new short[160];
while (!stopped) {
    //Log.i("Map", "Writing new data to buffer");
    int n = recorder.read(buffer, 0, buffer.length);
    track.write(buffer, 0, n);
}

Following permission in manifest is required to work properly:

<uses-permission android:name="android.permission.RECORD_AUDIO" ></uses-permission>

Also, 2d buffer array is not necessary. The logic of the code is valid even with just one buffer, like this:

short[] buffer = new short[160];
while (!stopped) {
    //Log.i("Map", "Writing new data to buffer");
    int n = recorder.read(buffer, 0, buffer.length);
    track.write(buffer, 0, n);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文