Android 双簧管/音频播放流中的欠音速

Android 双簧管/音频播放流中的欠音速,android,audio,android-ndk,oboe,Android,Audio,Android Ndk,Oboe,我正在开发一个安卓应用程序,该应用程序处理的设备基本上是一个USB麦克风。我需要读取输入数据并进行处理。有时,我需要向设备发送数据(4shorts*通道数,通常为2个),并且该数据不依赖于输入 我正在使用,所有我用来测试的手机都在下面使用音频 读取部分工作正常,但当我尝试将数据写入输出流时,我在logcat中得到以下警告,并且没有向输出写入任何内容: W/AudioTrack: releaseBuffer() track 0x78e80a0400 disabled due to previou

我正在开发一个安卓应用程序,该应用程序处理的设备基本上是一个USB麦克风。我需要读取输入数据并进行处理。有时,我需要向设备发送数据(4
short
s*通道数,通常为2个),并且该数据不依赖于输入

我正在使用,所有我用来测试的手机都在下面使用音频

读取部分工作正常,但当我尝试将数据写入输出流时,我在
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);
}
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;
}
它是这样工作的,如果我注意到任何性能问题,我将更改哪个流附加了回调,现在我将保持这种方式

有时,我需要向设备发送数据

您始终需要将数据写入输出。一般来说,你至少需要写numframe,也许更多。如果没有任何有效的数据要发送,则写入零。 警告:在else块中,您正在调用memset(),但没有写入流

->setFramesPerCallback(1024)

你特别需要1024吗?那是FFT吗?如果没有,那么如果没有指定FramesPerCallback,AAudio可以更好地优化回调

在所有的双簧管示例中,回调都在输出流上注册, 读数被阻塞了。这有重要意义吗

实际上,读取是非阻塞的。任何没有回调的流都应该是非阻塞的。使用timeoutNanos=0

如果您想要低延迟,那么为回调使用输出流是很重要的。这是因为输出流只能为回调提供低延迟模式,而不能为direct write()提供低延迟模式。但是输入流可以通过回调和read()提供低延迟

一旦流稳定,您就可以在每个回调中读取或写入相同数量的帧。但在它稳定之前,您可能需要读取或写入额外的帧

对于输出回调,您应该将输入排空一段时间,使其接近于空

使用输入回调函数,您应该填充输出一段时间,使其运行接近满

写入(此->agcData,numFrames,1)


您的1纳秒超时非常小。但双簧管仍然会阻塞。对于非阻塞模式,您应该使用timeoutNanos值0。

根据双簧管文档,在onAudioReady回调期间,您必须将精确的numFrames帧直接写入*audioData指向的缓冲区。您不必调用双簧管“写入”函数,而是自己填充缓冲区

不确定getAgc()函数是如何工作的,但也许可以将指针audioData作为参数赋予该函数,以避免将数据从一个缓冲区复制到另一个缓冲区。 如果您确实需要onAudioReady回调来请求相同数量的帧,那么在构建音频流时,您必须使用以下方法设置该数字:

oboe::AudioStreamBuilder::setFramesPerCallback(int framesPerCallback)
在这里看看在onAudioReady回调期间不应该做的事情,您会发现双簧管写入函数是被禁止的:

谢谢!1024帧目前是一种任意数,但我们使用的数据处理算法在处理少量数据时无法正常工作。1ns超时只是我忘记删除的一个测试,但它无法与0一起工作。