xamarin.android - 如何使用 Uno Platform 在多个平台上录制音频
问题描述
我正在尝试录制音频并在之后进行处理。据我了解,没有可以用来跨不同平台访问麦克风的统一 API。我的目标是 WASM、UWP 和 Android。
我的方法是使用特定于平台的代码录制音频。
对于UWP,我可以使用此处描述的 MediaCapture 类:link。我已经实现了这部分,它工作得很好。
对于Android,它也应该是直截了当的。我可以使用 Android.Media.MediaRecorder ,如下所示:link。我不知道之后如何获取录制的音频文件。
至于WASM,我在这里完全迷失了。我想我可以使用一些 javascript 库来记录声音或 vmsg 库,如此处所述链接。但我不知道如何将记录的数据转换为 C# 代码以进行进一步处理。
是否有一些材料我应该阅读以更好地理解该主题。我是否忽略了一些重要的细节?或者有没有一种简单的方法可以在 xamarin.android 和 wasm 中录制音频?
更新:我已经使用 Android.Media.MediaRecorder 在 Android 上成功实现了音频捕获,完成录制后我可以简单地访问该文件。
解决方案
我终于可以在所有三个平台(UWP、Android、WASM)上进行录制了。这里的目标是获得具有 48 kHz 采样率、1 个通道和每个样本 16 位的原始 PCM 音频数据。
超轻量级:
全局变量:
MediaCapture audioCapture = new MediaCapture();
IRandomAccessStream buffer = new InMemoryRandomAccessStream();
录制音频:
public async Task RecordAudio(int recordingLength, uint sampleRate, uint channels, uint bitsPerSample)
{
//initialization
await audioCapture.InitializeAsync(new MediaCaptureInitializationSettings { StreamingCaptureMode = StreamingCaptureMode.Audio });
//encoding setup
MediaEncodingProfile profile = MediaEncodingProfile.CreateWav(AudioEncodingQuality.Auto);
profile.Audio = AudioEncodingProperties.CreatePcm(sampleRate, channels, bitsPerSample);
//start recording
await audioCapture.StartRecordToStreamAsync(profile, buffer);
await Task.Delay(recordingLength * 1000);
//stop recording
await audioCapture.StopRecordAsync();
}
以字节数组的形式获取 PCM 数据:
public async Task<byte[]> GetPCMData()
{
byte[] data = new byte[buffer.Size];
DataReader dataReader = new DataReader(buffer.GetInputStreamAt(0));
await dataReader.LoadAsync((uint)buffer.Size);
dataReader.ReadBytes(data);
return data;
}
ANDROID:记得先检查麦克风权限。全局变量:
byte[] buffer;
AudioRecord recorder;
int bufferLimit;
录制音频:
public async Task RecordAudio(int recordingLength, uint sampleRate, uint channels, uint bitsPerSample)
{
//initialization
// seconds * (number of bytes bytes per 1 sample) * sampleRate
bufferLimit = recordingLength * bitsPerSample/8 * sampleRate;
//encoding setup
ChannelIn channels = Parameters.Channels == 1 ? ChannelIn.Mono : ChannelIn.Stereo;
if (bitsPerSample != 16)
throw new Exception("Unsupported bits per sample value");
recorder = new AudioRecord(
AudioSource.Mic,
(int)sampleRate,
channels,
Android.Media.Encoding.Pcm16bit,
bufferLimit
);
//start recording
buffer = new byte[bufferLimit];
int totalBytesRead = 0;
recorder.StartRecording();
//record until specified amount of bytes was read
while(totalBytesRead < bufferLimit)
{
int bytesRead = recorder.Read(buffer, 0, bufferLimit);
if (bytesRead < 0)
{
throw new Exception(String.Format("Exception code: {0}", bytesRead));
}
else
{
totalBytesRead += bytesRead;
}
}
//stop recording
recorder.Stop();
recorder.Dispose();
}
以字节数组的形式获取 PCM 数据:
public async Task<byte[]> GetPCMData()
{
return buffer;
}
蜂鸣器:
我使用RecordRTC javascript 库来获取音频数据:
function record(recordingLength, sampleRate, channels) {
navigator.mediaDevices.getUserMedia({
audio: true
}).then(async function (stream) {
//initialization
let recorder = RecordRTC(stream, {
type: 'audio',
mimeType: 'audio/wav',
recorderType: StereoAudioRecorder,
sampleRate: sampleRate,
desiredSampRate: sampleRate,
numberOfAudioChannels: channels
});
//start recording
recorder.startRecording();
const sleep = m => new Promise(r => setTimeout(r, m));
await sleep(recordingLength * 1000);
recorder.stopRecording(function () {
//blob of PCM audio data that can be further processed
let blob = recorder.getBlob();
}
});
});
}
在WASM 中,我使用 blob 作为 base64 字符串从 javascript 调用 C# 代码,以在 C# 中进一步处理 PCM 音频数据的 blob(如何从 javascript 调用 C# 代码可以在 Uno Platform docs中找到)。
我知道,这不是最干净的解决方案,但它是一个可行的解决方案。
推荐阅读
- javascript - dynamodb nodejs/lambda date.now()
- c - 抑制 ld 符号未找到错误以在运行时稍后解决
- java - 如何使 JFrame 调整大小
- javascript - 有没有办法让我通过 nodejs 获取 git origin 分支代码
- sql - 我想使用 PL/SQL 更新列
- python - 预先确定放大的最佳水平
- firebase - 当我尝试在我的颤振应用程序中使用 firebase 时,它会产生错误
- python-3.x - 如何使用电报 api 在我的机器人上发送图像?
- sql - 两个字段的SQL总和
- r - 根据多列中的条件对一列中的数据进行分组 - dplyr