【发布时间】:2018-11-26 10:05:26
【问题描述】:
我正在开发一个 Android 应用程序,该应用程序处理一个基本上是 USB 麦克风的设备。我需要读取输入数据并进行处理。有时,我需要向设备发送数据(4 shorts * 通常为 2 的通道数),此数据不依赖于输入。
我用的是Oboe,我用来测试的所有手机都在下面使用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 中所见,我正在将回调注册到输入流。在所有双簧管示例中,回调都注册在输出流上,并且读取是阻塞的。这有重要性吗?如果不是,我需要向流中写入多少帧以避免欠载?
编辑
与此同时,我找到了欠载的来源。输出流读取的帧数量与输入流不同(事后看来这似乎是合乎逻辑的),因此写入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;
}
它是这样工作的,如果我发现任何性能问题,我会更改附加回调的流,现在我会保持这种方式。
【问题讨论】:
标签: android audio android-ndk oboe