Я работаю над приложением для Android, работающим с устройством, которое в основном является USB-микрофоном.Мне нужно прочитать входные данные и обработать их.Иногда мне нужно отправить данные на устройство (4 short
s * количество каналов, которое обычно составляет 2), и эти данные не зависят от входа.
Я использую Гобой , и все телефоны, которые я использую для тестирования, используют AAudio внизу.
Считывающая часть работает, но когда я пытаюсь записать данные в выходной поток, я получаю следующее предупреждение в logcat
, и ничего не происходитзаписано в вывод:
W/AudioTrack: releaseBuffer() track 0x78e80a0400 disabled due to previous underrun, restarting
Вот мой обратный вызов:
oboe::DataCallbackResult
OboeEngine::onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) {
// check if there's data to write, agcData is a buffer previously allocated
// and h2iaudio::getAgc() returns true if data's available
if (h2iaudio::getAgc(this->agcData)) {
// padding the buffer
short* padPos = this->agcData+ 4 * playStream->getChannelCount();
memset(padPos, 0,
static_cast<size_t>((numFrames - 4) * playStream->getBytesPerFrame()));
// write the data
oboe::ResultWithValue<int32_t> result =
this->playStream->write(this->agcData, numFrames, 1);
if (result != oboe::Result::OK){
LOGE("Failed to create stream. Error: %s",
oboe::convertToText(result.error()));
return oboe::DataCallbackResult::Stop;
}
}else{
// if there's nothing to write, write silence
memset(this->agcData, 0,
static_cast<size_t>(numFrames * playStream->getBytesPerFrame()));
}
// data processing here
h2iaudio::processData(static_cast<short*>(audioData),
static_cast<size_t>(numFrames * oboeStream->getChannelCount()),
oboeStream->getSampleRate());
return oboe::DataCallbackResult::Continue;
}
//...
oboe::AudioStreamBuilder *OboeEngine::setupRecordingStreamParameters(
oboe::AudioStreamBuilder *builder) {
builder->setCallback(this)
->setDeviceId(this->recordingDeviceId)
->setDirection(oboe::Direction::Input)
->setSampleRate(this->sampleRate)
->setChannelCount(this->inputChannelCount)
->setFramesPerCallback(1024);
return setupCommonStreamParameters(builder);
}
Как видно из setupRecordingStreamParameters
, я регистрирую обратный вызов во входном потоке.Во всех примерах Oboe обратный вызов регистрируется в выходном потоке, и чтение блокируется.Это имеет значение?Если нет, сколько кадров мне нужно записать в поток, чтобы избежать опустошения?
РЕДАКТИРОВАТЬ Тем временем я нашел источник опустошения.Выходной поток не считывал такое же количество кадров, как входной поток (что в ретроспективе кажется логичным), поэтому запись количества кадров, заданного playStream->getFramesPerBurst()
, решает мою проблему.Вот мой новый обратный вызов:
oboe::DataCallbackResult
OboeEngine::onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) {
int framesToWrite = playStream->getFramesPerBurst();
memset(agcData, 0, static_cast<size_t>(framesToWrite *
this->playStream->getChannelCount()));
h2iaudio::getAgc(agcData);
oboe::ResultWithValue<int32_t> result =
this->playStream->write(agcData, framesToWrite, 0);
if (result != oboe::Result::OK) {
LOGE("Failed to write AGC data. Error: %s",
oboe::convertToText(result.error()));
}
// data processing here
h2iaudio::processData(static_cast<short*>(audioData),
static_cast<size_t>(numFrames * oboeStream->getChannelCount()),
oboeStream->getSampleRate());
return oboe::DataCallbackResult::Continue;
}
Он работает таким образом, я изменю, к какому потоку присоединен обратный вызов, если я обнаружу какие-либо проблемы с производительностью, сейчас я буду держать его таким образом.