AudioRecord и задержка AudioTrack - PullRequest
7 голосов
/ 21 марта 2011

Я пытаюсь разработать приложение, подобное iRig для Android, поэтому первым шагом является захват микрофонного входа и одновременное его воспроизведение.

У меня есть, но проблема в том, что яполучим некоторую задержку, которая сделает это непригодным для использования, и если я начну обрабатывать буфер, я боюсь, что он станет совершенно непригодным для использования.

Я использую аудиозапись и аудиотрек так:

    new Thread(new Runnable() {
        public void run() {
            while(mRunning){
                mRecorder.read(mBuffer, 0, mBufferSize);
                //Todo: Apply filters here into the buffer and then play it modified
                mPlayer.write(mBuffer, 0, mBufferSize);         
                //Log.v("MY AMP","ARA");
            }

Иинициализация таким образом:

// ==================== INITIALIZE ========================= //
public void initialize(){

    mBufferSize = AudioRecord.getMinBufferSize(mHz, 
                AudioFormat.CHANNEL_CONFIGURATION_MONO, 
                AudioFormat.ENCODING_PCM_16BIT);

    mBufferSize2 = AudioTrack.getMinBufferSize(mHz, 
                AudioFormat.CHANNEL_CONFIGURATION_MONO, 
                AudioFormat.ENCODING_PCM_16BIT);

    mBuffer = new byte[mBufferSize];

    Log.v("MY AMP","Buffer size:" + mBufferSize);

    mRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
                mHz,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT, 
                mBufferSize);

    mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC,
                mHz,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT,
                mBufferSize2, 
                AudioTrack.MODE_STREAM);    

}

знаете ли вы, как получить более быстрый ответ?Спасибо!

Ответы [ 4 ]

8 голосов
/ 02 августа 2011

Android-классы AudioTrack \ AudioRecord имеют высокую задержку из-за минимального размера буфера. Причина таких размеров буфера заключается в том, чтобы минимизировать потери, когда GC происходит по данным Google (на мой взгляд, это неправильное решение, вы можете оптимизировать собственное управление памятью).

То, что вы хотите сделать, это использовать OpenSL, который доступен с 2.3. Он содержит нативные API для потоковой передачи аудио. Вот несколько документов: http://mobilepearls.com/labs/native-android-api/opensles/index.html

1 голос
/ 16 февраля 2012

Просто мысль, но разве вы не должны читать

0 голосов
/ 30 августа 2016

Как указал mSparks, потоковая передача должна осуществляться с использованием меньшего размера чтения: вам не нужно считывать полный буфер для потоковой передачи данных!

int read = mRecorder.read(mBuffer, 0, 256); /* Or any other magic number */
if (read>0) {
    mPlayer.write(mBuffer, 0, read);  
}

Это резко уменьшит вашу задержку. Если МГц равен 44100, а вы находитесь в конфигурации MONO с 256, ваша задержка будет не менее 1000 * 256/44100 миллисекунд = ~ 5,8 мс. 256/44100 - это преобразование из выборок в секунды, поэтому умножение на 1000 дает миллисекунды. Проблемы внутренней реализации плеера. Вы не можете контролировать это из Java. Надеюсь, это кому-нибудь поможет:

0 голосов
/ 02 августа 2011

Моим первым инстинктом было предложение включить AudioTrack в статический режим, а не в потоковый режим, поскольку статический режим имеет значительно меньшую задержку.Однако статический режим больше подходит для коротких звуков, которые полностью умещаются в памяти, а не для звука, который вы захватываете откуда-то еще.Но просто как дикое предположение, что если вы установите AudioTrack в статический режим и подадите на него отдельные фрагменты входного аудио?

Если вы хотите более жесткий контроль над аудио, я бы рекомендовал взглянуть на OpenSL ES для Android.Кривая обучения будет немного круче, но вы получите гораздо более детальный контроль и меньшую задержку.

...