Как воспроизвести AudioRecord с некоторой задержкой - PullRequest
5 голосов
/ 15 ноября 2011

Я реализую приложение, которое будет повторять все, что я говорю.Мне нужно воспроизвести звук, который я записываю, в буфере только с секундной задержкой, чтобы я сам слушал, но с задержкой в ​​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 и реализующий метод run.

Большое спасибо!

1 Ответ

0 голосов
/ 17 января 2013

По крайней мере, вы должны изменить следующую строку вашего плеера

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 с и AudioTrackчтение его блока перед записью новых данных через AudioRecord в один и тот же блок, оба с одинаковой частотой дискретизации.

Я бы предложил сделать это внутри одного потока.

...