如何播放有延迟的 AudioRecord

发布于 2024-12-15 10:32:38 字数 2598 浏览 0 评论 0原文

我正在实现一个应用程序,它会重复我告诉它的一切。 我需要的是播放我在缓冲区上录制的声音,延迟一秒 这样我就会自己听,但延迟 1 秒

这是我的 Recorder 类的运行方法

public void run()
    {           
        AudioRecord recorder = null;
        int ix = 0;
        buffers = new byte[256][160];

        try
        {
            int N = AudioRecord.getMinBufferSize(44100,AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT);
            recorder = new AudioRecord(AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, N*10);               
            recorder.startRecording();
            Timer t = new Timer();              
            SeekBar barra = (SeekBar)findViewById(R.id.barraDelay);
            t.schedule(r = new Reproductor(), barra.getProgress());           

            while(!stopped)
            {                   
                byte[] buffer = buffers[ix++ % buffers.length];                 
                N = recorder.read(buffer,0,buffer.length);                  
            }
        }
        catch(Throwable x)
        {               
        }

        finally
        { 
            recorder.stop();
            recorder.release();
            recorder = null;                        
        }

这是我的播放器的运行方法:

public void run() {
        reproducir = true;

        AudioTrack track = null;            
        int jx = 0;

        try
        {
            int N = AudioRecord.getMinBufferSize(44100,AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT);               
            track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, 
                    AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, N*10, AudioTrack.MODE_STREAM);              
            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(reproducir)
            {                   
                byte[] buffer = buffers[jx++ % buffers.length];                 
                track.write(buffer, 0, buffer.length);
            }
        }
        catch(Throwable x)
        {               
        }
        /*
         * Frees the thread's resources after the loop completes so that it can be run again
         */
        finally
        {               
            track.stop();
            track.release();
            track = null;               
        }

    }

Reproductor 是一个扩展 TimerTask 并实现“运行”方法的内部类。

非常感谢!

I'm implementing an app which will repeat everything I'm telling it.
What I need is to play the sound I'm recording on a buffer just with a second of delay
So that I would be listening myself but 1 second delayed

This is my run method of the Recorder class

public void run()
    {           
        AudioRecord recorder = null;
        int ix = 0;
        buffers = new byte[256][160];

        try
        {
            int N = AudioRecord.getMinBufferSize(44100,AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT);
            recorder = new AudioRecord(AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, N*10);               
            recorder.startRecording();
            Timer t = new Timer();              
            SeekBar barra = (SeekBar)findViewById(R.id.barraDelay);
            t.schedule(r = new Reproductor(), barra.getProgress());           

            while(!stopped)
            {                   
                byte[] buffer = buffers[ix++ % buffers.length];                 
                N = recorder.read(buffer,0,buffer.length);                  
            }
        }
        catch(Throwable x)
        {               
        }

        finally
        { 
            recorder.stop();
            recorder.release();
            recorder = null;                        
        }

And this is the run one of my player:

public void run() {
        reproducir = true;

        AudioTrack track = null;            
        int jx = 0;

        try
        {
            int N = AudioRecord.getMinBufferSize(44100,AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT);               
            track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, 
                    AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, N*10, AudioTrack.MODE_STREAM);              
            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(reproducir)
            {                   
                byte[] buffer = buffers[jx++ % buffers.length];                 
                track.write(buffer, 0, buffer.length);
            }
        }
        catch(Throwable x)
        {               
        }
        /*
         * Frees the thread's resources after the loop completes so that it can be run again
         */
        finally
        {               
            track.stop();
            track.release();
            track = null;               
        }

    }

Reproductor is an inner class extending TimerTask and implementing the "run" method.

Many thanks!

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

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

发布评论

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

评论(1

纵性 2024-12-22 10:32:38

至少您应该将播放器的以下行更改

int N = AudioRecord.getMinBufferSize(44100,AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT);               

为,

int N = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);

因为 API 需要这样做(尽管常量值是相同的)。

但这只是一个边缘点。主要的一点是,您并没有真正提出解决问题的方法,而只是提出了两种通用方法。

有效解决方案的核心是,您使用大小为 1 秒的环形缓冲区,并且在通过 AudioRecord 将新数据写入同一缓冲区之前,AudioTrack 读取其中的一个块。块,两者都具有相同的采样率。

我建议在单个线程内执行此操作。

At least you should change the following line of your player

int N = AudioRecord.getMinBufferSize(44100,AudioFormat.CHANNEL_IN_STEREO,AudioFormat.ENCODING_PCM_16BIT);               

to

int N = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);

because the API requires that (albeit the constant values are identical).

But this is only a marginal point. The main point is that you did not really present an approach to your problem, but only two generic methods.

The core of a working solution is that you use a ring buffer with a size of 1s and AudioTrack reading a block of it just ahead of writing new data via AudioRecord to the same block, both at the same sample rate.

I would suggest to do that inside a single thread.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文