Подтвердить что ты не робот

Android-эмулятор, похоже, записывает аудио на 96 кГц

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

Похоже, что на эмуляторе звуковые сэмплы читаются примерно в два раза быстрее, чем на реальных устройствах. В приложении у меня виджет визуального прогресса (горизонтально движущаяся головка записи), которая перемещается примерно в два раза быстрее в эмуляторе.

Вот цикл записи:

int FREQUENCY = 44100;
int BLOCKSIZE = 110;

int bufferSize = AudioRecord.getMinBufferSize(FREQUENCY,
        AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT) * 10;

AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.CAMCORDER,
        FREQUENCY, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT,
        bufferSize);

short[] signal = new short[BLOCKSIZE * 2]; // Times two for stereo

audioRecord.startRecording();

while (!isCancelled()) {
    int bufferReadResult = audioRecord.read(signal, 0, BLOCKSIZE * 2);
    if (bufferReadResult != BLOCKSIZE * 2)
        throw new RuntimeException("Recorded less than BLOCKSIZE x 2 samples:"
                + bufferReadResult);

    // process the `signal` array here
}

audioRecord.stop();
audioRecord.release();

Источник звука установлен на "CAMCORDER" и записывается в стерео. Идея состоит в том, что если в телефоне есть несколько микрофонов, приложение будет обрабатывать данные от обоих и использовать то, что лучше SNR. Но у меня такие же проблемы, если записывать моно из AudioSource.MIC. Он считывает аудиоданные в цикле while, я предполагаю, что audioRecord.read() является блокирующим вызовом и не позволит мне дважды читать одни и те же данные.

Записанные данные выглядят ОК - буфер записи содержит 16-битные образцы PCM для двух каналов. Кажется, что цикл работает в два раза быстрее, чем на реальных устройствах. Это заставляет меня думать, что, возможно, эмулятор использует более высокую частоту дискретизации, чем указанные 44100 Гц. Если я запрошу частоту дискретизации с audioRecord.getSampleRate(), он вернет правильное значение.

Также во время записи есть несколько интересных аудиосообщений в logcat:

07-13 12:22:02.282  1187  1531 D AudioFlinger: mixer(0xf44c0000) throttle end: throttle time(154)
(...)
07-13 12:22:02.373  1187  1817 E audio_hw_generic: Error opening input stream format 1, channel_mask 0010, sample_rate 16000
07-13 12:22:02.373  1187  3036 I AudioFlinger: AudioFlinger thread 0xf3bc0000 ready to run
07-13 12:22:02.403  1187  3036 W AudioFlinger: RecordThread: buffer overflow
(...)
07-13 12:22:24.792  1187  3036 W AudioFlinger: RecordThread: buffer overflow
07-13 12:22:30.677  1187  3036 W AudioFlinger: RecordThread: buffer overflow
07-13 12:22:37.722  1187  3036 W AudioFlinger: RecordThread: buffer overflow

Я использую современные Android Studio и Android SDK, и я пробовал изображения эмуляторов с уровнями API 21-24. Моя среда для разработчиков - Ubuntu 16.04

Кто-нибудь испытал нечто подобное? Я что-то делаю неправильно в своем цикле записи?

4b9b3361

Ответ 1

Я подозреваю, что это вызвано AudioFormat.CHANNEL_IN_STEREO. Микрофон на устройстве, как правило, является монофоническим источником. Если по какой-то причине эмулятор поддерживает стерео, вы получите в два раза больше данных на эмуляторе (для обоих каналов). Чтобы убедиться в этом, попробуйте переключиться на AudioFormat.CHANNEL_IN_MONO, который гарантирован для работы на всех устройствах, и посмотрите, получаете ли вы такой же объем данных на эмулятор.