Буфер Android AudioRecord начинается с нуля перед значимыми значениями - PullRequest
0 голосов
/ 19 февраля 2019

Я пытаюсь записать около 500 кадров, используя AudioRecord, но похоже, что буфер AudioRecord изначально частично заполняется числом 0, прежде чем захватывать значимые значения.

Мне пришлось прочитать первые 10000 кадров, используямассив, чтобы получить фактические значения.

AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
        44100,
        AudioFormat.CHANNEL_IN_MONO,
        AudioFormat.ENCODING_PCM_16BIT,
        2*44100);
audioRecord.startRecording();
audioRecord.read(new short[10000], 0, 10000); // have to include this to remove redundant values
audioRecord.read(audio, 0, 500);
audioRecord.stop();

Если я опущу третью строку, я получу 500 нулей.Это решение не изящное, и мне нужно знать, делаю ли я что-то не так.Также важно отметить, что перед вызовом методов read() state равен STATE_INITIALIZED, а recordingState равен RECORDSTATE_RECORDING, а также методы read() возвращают ровно столько кадров, сколько онидолжен читать, так что проблем нет.

1 Ответ

0 голосов
/ 20 февраля 2019

Вы используете AudioRecord правильно.Похоже, проблема в том, что на микрофоне какая-то AGC;как вы заметили, значения, считанные из буфера, постепенно увеличиваются в течение первых нескольких мс.Вероятно, это аппаратная AGC, возможно, добавленная производителем, чтобы предотвратить резкую «трещину» в начале каждой новой записи.

В качестве отступления: у меня есть старый RAZR с AGC, который настолько агрессивен,если вы щелкнете пальцами рядом с микрофоном, он замолчит на целую секунду, а затем медленно исчезнет.

Одним из решений этой проблемы является просто оставить запись AudioRecord на длительный срок.основа.Затем, когда вы решите, что вам нужно захватить свои 500 кадров, они уже будут «подогреты», и значения должны быть в натуральную величину.

РЕДАКТИРОВАТЬ

Я только что провёл модульное тестирование, и кажется, что AudioRecord не перезаписывает данные во внутреннем буфере, если вы пренебрегаете чтением достаточно быстро.Или, по крайней мере, не совсем понятно, что происходит с этими данными.Итак, необходимо более сложное решение.

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

Если вы просто используете буфер 500 кадров при каждом чтении, то когда придет время, вы можете просто получить копиюэтого буфера, который будет достаточно близок к «самой последней возможной» поточной передаче данных с микрофона.Это предполагает, что вы читали достаточно быстро, так что ваше следующее чтение заблокировалось бы.

Я говорю «достаточно близко», потому что аудиоданные помещаются в буфер кусками размером getMinBufferSize()/2, если я правильно помню, иэто также предел разрешения OnRecordPositionUpdateListener.Итак, вы будете где-то близко к концу, но трудно точно сказать, насколько близко.

...