3

我正在使用 Android 双簧管库在音乐游戏中获得高性能音频。

在资产文件夹中,我有 2 个 .raw 文件(48000Hz 16 位 PCM wav 和大约 60kB)std_kit_sn.raw std_kit_ht.raw

这些作为 SoundRecordings 加载到内存中并添加到混音器中。kSampleRateHz 为 48000:

stdSN= SoundRecording::loadFromAssets(mAssetManager, "std_kit_sn.raw");
stdHT= SoundRecording::loadFromAssets(mAssetManager, "std_kit_ht.raw");
mMixer.addTrack(stdSN);
mMixer.addTrack(stdFT);

// Create a builder
AudioStreamBuilder builder;
builder.setFormat(AudioFormat::I16);
builder.setChannelCount(1);
builder.setSampleRate(kSampleRateHz);
builder.setCallback(this);
builder.setPerformanceMode(PerformanceMode::LowLatency);
builder.setSharingMode(SharingMode::Exclusive);
LOGD("After creating a builder");

// Open stream
Result result = builder.openStream(&mAudioStream);
if (result != Result::OK){
    LOGE("Failed to open stream. Error: %s", convertToText(result));
}
LOGD("After openstream");

// Reduce stream latency by setting the buffer size to a multiple of the burst size
mAudioStream->setBufferSizeInFrames(mAudioStream->getFramesPerBurst() * 2);

// Start the stream
result = mAudioStream->requestStart();
if (result != Result::OK){
    LOGE("Failed to start stream. Error: %s", convertToText(result));
}
LOGD("After starting stream");

它们被适当地调用以在需要的时间使用标准代码(根据 Google 教程):

stdSN->setPlaying(true);
stdHT->setPlaying(true); //Nasty Sound

音频回调是标准的(根据谷歌教程):

DataCallbackResult SoundFunctions::onAudioReady(AudioStream *mAudioStream, void *audioData, int32_t numFrames) {

    // Play the stream
    mMixer.renderAudio(static_cast<int16_t*>(audioData), numFrames);
    return DataCallbackResult::Continue;

}

std_kit_sn.raw 播放良好。但是 std_kit_ht.raw 有一个令人讨厌的失真。两者都以低延迟播放。为什么一个播放得很好,而另一个有令人讨厌的失真?

4

1 回答 1

1

我加载了您的示例项目,我相信您听到的失真是由声音混合过程中的削波/环绕引起的。

Mixer样本中的对象是一个求和混合器。它只是将每个轨道的值相加并输出 sum

您需要添加一些代码来减少每个音轨的音量以避免超出限制int16_t(尽管欢迎您在双簧管项目上提交错误,我将尝试在即将发布的版本中添加它)。如果超出此限制,您将得到导致失真的环绕。

此外,您的应用程序经过硬编码以 22050 帧/秒的速度运行。这将导致大多数移动设备的延迟不理想,因为流被迫上采样到音频设备的本机帧速率。更好的方法是在打开流时不定义采样率 - 这将为您提供当前音频设备的最佳帧速率 - 然后在源文件上使用重新采样器以该帧速率提供音频。

于 2018-12-27T18:07:37.173 回答