android - AudioRecord.Read 在物理设备上运行时无限期挂起
问题描述
我正在构建一个实时处理音频的 Xamarin.Android 应用程序,因此我正在设置 AudioRecord。我让它在模拟器中工作,但是当我在设备(Galaxy S9)上运行它时,AudioRecord.Read() 调用永远不会返回。这很令人费解,因为所有的 contructor/StartRecording() 都运行良好,没有任何异常,并且 Recording 状态报告 RECORDSTATE_RECORDING。它认为它正在录制,但读取无法获取帧。此外,在模拟器上,它运行良好并且确实从缓冲区中成功读取。
这是代码。如果您想尝试,请创建一个空白 Xamarin.Android 应用并将 MainActivity.cs 内容替换为:
using Android.App;
using Android.OS;
using Android.Support.V7.App;
using Android.Media;
using Android;
using System.Threading;
using System.Linq;
using System;
namespace AndroidRecord
{
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
if (CheckSelfPermission(Manifest.Permission.RecordAudio) != Android.Content.PM.Permission.Granted)
{
throw new Exception($"need record permission");
}
StartRecording();
}
protected void OnDataUpdate(float[] data)
{
// consume thse data.
var max = data.Max(sample => sample);
System.Diagnostics.Debug.WriteLine($"{max}");
}
public void StartRecording()
{
new Thread(new ThreadStart(() =>
{
var audioSource = AudioSource.Mic;
int sampleRate = 44100;
var channelConfig = ChannelIn.Front;
var encoding = Encoding.PcmFloat;
int minBufferSize = AudioRecord.GetMinBufferSize(sampleRate, channelConfig, encoding);
AudioRecord recorder = new AudioRecord(audioSource, sampleRate, channelConfig, encoding, minBufferSize);
recorder.StartRecording();
int chunkSize = 2048;
while (true)
{
float[] data = new float[chunkSize];
int i = recorder.Read(data, 0, chunkSize, (int)(int)AudioRecordReadOptions.Blocking);
RunOnUiThread(() => OnDataUpdate(data));
}
})).Start();
}
}
到目前为止,我已经尝试过:
- AudioRecord 选项的各种组合(不同的通道配置、音频源和编码)
- 各种块大小(似乎无关紧要,因为我认为没有什么可读的)
- 将 Read() 调用更改为非阻塞并检查返回值。它不写入任何值并返回成功。
暂停调试器以查看堆栈跟踪的内容。每次我休息时,录音线程都在同一个地方,等待互操作调用:
0xFFFFFFFFFFFFFFFF in Java.Interop.NativeMethods.java_interop_jnienv_call_int_method_a 0x54 in Java.Interop.JniEnvironment.InstanceMethods.CallIntMethod 0x2C in Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualInt32Method 0x70 in Android.Media.AudioRecord.Read 0x61 in AndroidRecord.MainActivity.<StartRecording>b__2_0
我还能尝试诊断此问题或至少获得更多信息?
解决方案
我重新启动了我的设备并再次尝试,然后计算,现在它工作正常。我唯一的猜测是录音设备不知何故处于不良状态,可能是因为在上次运行时从调试器强制停止了我的应用程序。不过只是猜测。
推荐阅读
- go - go vet 警告该示例引用未知标识符,但为什么呢?
- php - 数组到字符串的转换(laravel 7)
- javascript - 无法从 excel 工作簿中读回正确的 JSON
- github-actions - GitHub Actions 表达式函数:字符串操作?
- swift - 如何修改imagePickerController(源相机)在按下“使用照片”后不关闭,直到拍摄4张照片?
- python - 如何与需要在 python 中输入的子进程交互?
- multithreading - 多处理:为什么单个线程不使用更多的 cpu?
- javascript - 内置到 exe 文件后,Electron 应用程序无法正常运行
- c# - MySqlBulkLoader 小数分隔符问题 c#
- reactjs - 如何在反应原生导航器中使用导航器传递状态