ОБНОВЛЕНИЕ: эта ошибка в Android была исправлена где-то после 4.2.2 и до 5.01. На 5.01 обратные вызовы работают точно так же, как в документах говорится, что они должны.
Похоже, read
блокируется из-за некоторой близорукости разработчиков.
По сути, когда инициализируется аудиорегистратор, он выделяет своего рода кольцевой буфер, а когда ему сообщается .start()
, он начинает запись в этот буфер.
Затем, когда вызывается .read()
, он считывает до половины размера буфера (или запрошенного размера, в зависимости от того, что меньше) и возвращает.
Если он хочет прочитать 1000 образцов, а доступно только 900, он должен подождать еще 100 образцов, прежде чем вернуться. Однако, если имеется более 1000 сэмплов, он считывает их мгновенно, а затем сразу возвращает.
В идеале, они должны либо обеспечить неблокирующее чтение, чтобы возвращалось все доступное, либо предоставить способ узнать, когда доступны данные полного чтения, чтобы можно было выполнить неблокирующее чтение.
Я не думаю, что они поддерживают первое. Похоже, они пытаются поддержать второе с помощью метода обратного вызова set period, но пока я не могу получить этот обратный вызов в нужное время, чтобы выполнить быстрое неблокирующее чтение.
Я клонировал полный исходный код (8,5 Гбайт) исходного исходного кода C ++, и я пытаюсь проследить функциональность на всех уровнях, чтобы увидеть, как он должен работать.
Хитрость для неблокирования .read(0)
заключается в том, чтобы читать только тогда, когда готово полное чтение образцов. Но определить, когда это условие истинно, я еще не понял.
Список литературы:
Вот код Java для .read (), который вызывает встроенную функцию C ++:
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.4_r1/android/media/AudioRecord.java#AudioRecord.read%28java.nio.ByteBuffer%2Cint%29
Приведенный выше метод read () вызывает нативный native_read_in_direct_buffer()
, который находится в:
http://pdroid.googlecode.com/svn/android-2.3.4_r1/trunk/frameworks/base/core/jni/android_media_AudioRecord.cpp
, который вызывает или указывает на android_media_AudioRecord_readInByteArray()
, который, в свою очередь, вызывает AudioRecord.read()
в frameworks/base/media/libmedia/frameworks/base/media/libmedia/AudioRecord.cpp
(насколько я могу судить), и похоже, что в этой функции есть цикл do / while, который по существу блокирует до нужного числа считанных байтов (или половина размера буфера, в зависимости от того, что меньше.)
Я попытался сделать так, чтобы обратные вызовы работали нормально, но они, кажется, перезванивают только в тот момент, когда read () должна ждать заполнения аудио-буфера, прежде чем он сможет вернуться - так какой смысл.
Моя следующая цель - попытаться отследить исходный код обратного вызова notify, чтобы я мог точно догадаться, что и когда он должен делать.