根据官方文档
Android 10(API 级别 29)及更高版本强加了一个优先级方案,可以在应用运行时在应用之间切换输入音频流。在大多数情况下,如果新应用程序获取音频输入,则先前捕获的应用程序会继续运行但会收到静音。在某些情况下,系统可以继续向两个应用程序传送音频。下面解释了各种共享场景。
除了一些特殊情况,应用程序之间不共享音频。
但是我看到很多应用程序共享音频输入而没有在上述特殊情况下。例如。Zoom,当我在通话中进行缩放并启动录音机时,两个应用程序都在获取音频,但缩放音频的强度会降低。
同样,即使其他应用程序可以访问麦克风,Omlet Arcade也能够录制麦克风音频。
这怎么可能?根据文档,这不应该被允许。
更新: 能够通过使用Oboe来实现它。但它在所有设备上并不一致。这也会导致我的直播应用出现同步问题。音频有延迟
我使用oboe来播放 ndk 库中的声音,并使用带有 Android 扩展的 OpenSL将 wav 文件解码为 PCM。解码后的带符号 16 位 PCM 存储在内存中 ( std::forward_list<int16_t>),然后通过回调将它们发送到双簧管流中。我从手机中听到的声音在音量级别上与原始 wav 文件相似,但是这种声音的“质量”却并非如此——它会爆裂和爆裂。
我猜测我以错误的顺序或格式(采样率?)在音频流中发送 PCM。如何使用 OpenSL 解码双簧管音频流?
要将文件解码为 PCM,我使用AndroidSimpleBufferQueue作为接收器,并使用AndroidFD和AAssetManager作为源:
// Loading asset
AAsset* asset = AAssetManager_open(manager, path, AASSET_MODE_UNKNOWN);
off_t start, length;
int fd = AAsset_openFileDescriptor(asset, &start, &length);
AAsset_close(asset);
// Creating audio source
SLDataLocator_AndroidFD loc_fd = { SL_DATALOCATOR_ANDROIDFD, fd, start, length };
SLDataFormat_MIME format_mime = { SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED };
SLDataSource audio_source = { &loc_fd, &format_mime }; …Run Code Online (Sandbox Code Playgroud) 我一直在尝试在我的 Flutter 应用程序中使用 Android NDK 的AssetManager类(它与Google Oboe配合使用)来访问音频文件。按照Oboe 存储库中的这个示例,我了解到他们是AssetManager这样从 Java 获取的:
JNIEXPORT void JNICALL
Java_com_google_oboe_sample_rhythmgame_MainActivity_native_1onStart(JNIEnv *env, jobject instance,
jobject jAssetManager) {
AAssetManager *assetManager = AAssetManager_fromJava(env, jAssetManager);
if (assetManager == nullptr) {
LOGE("Could not obtain the AAssetManager");
return;
}
game = std::make_unique<Game>(*assetManager);
game->start();
}
Run Code Online (Sandbox Code Playgroud)
基本上,它们通过 JNI 接口将参数jAssetManager从 Java 传递到 C++ 函数。现在我不使用 JNI,因为我使用 Flutter 和 Dart,Dart 中与 C++ 函数通信的方式是通过dart:ffi,但由于我可以创建的唯一方法AssetManager是 with AAssetManager_fromJava(env, jAssetManager),所以我需要这两个参数我找不到用 Flutter 和 Dart 替代的方法。
我做了一些研究,当我创建 Flutter FFI …
我目前正在开发一个需要低延迟音频的项目,因此我决定使用 Oboe(谷歌库)来处理它。
我已阅读该文档,但其中出现了多个问题。
首先,一旦我使用构建器模式创建流、打开流并请求流启动,我如何捕获从麦克风传入的数据?
我知道有两种方法:使用读取函数或回调。
问题:
但是,如果我使用读取函数,如何确保只要流启动就正在调用它?
如何使用回调来获取数据并进行处理?
我将在下面留下我的代码
void HelloOboeEngine::start() {
isRecording = true;
oboe::Result result = createStream();
if (result != oboe::Result::OK) {
closeStream(mRecordingStream);
}
result = mRecordingStream->requestStart();
if (result != oboe::Result::OK) {
closeStream(mRecordingStream);
}
}
oboe::Result HelloOboeEngine::createStream() {
oboe::AudioStreamBuilder builder;
return builder.setPerformanceMode(oboe::PerformanceMode::LowLatency)
->setDirection(oboe::Direction::Input)
->setFormat(mFormat)
->setFormatConversionAllowed(true)
->setChannelConversionAllowed(true)
->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::Medium)
->openStream(mRecordingStream);
}
void HelloOboeEngine::closeStream(std::shared_ptr<oboe::AudioStream> &stream) {
if (stream) {
oboe::Result result = stream->stop();
if (result != oboe::Result::OK) {
LOGW("Error stopping stream: %s", oboe::convertToText(result));
}
result = stream->close();
if (result != oboe::Result::OK) …Run Code Online (Sandbox Code Playgroud)