c# - Xamarin.Android 和 RecordAudio:如何结合文件写入和其他任务
问题描述
我开发了一个Xamarin.Android 应用程序,我需要在 .wav 中录制音频文件并同时显示相关的频谱图。
我能够分别执行这2 个任务,但不能将它们组合起来。
我使用 anAudioRecord
通过麦克风录制声音:
public async Task StartRecording()
{
audioRecord = new AudioRecord(AudioSource.Mic, 44100, ChannelIn.Mono, Android.Media.Encoding.Pcm16bit, bufferSize);
if (audioRecord.State == State.Initialized)
audioRecord.StartRecording();
isRecording = true;
recordingThread = new System.Threading.Thread(new ThreadStart(
WriteAudioDataToFile
));
recordingThread.Start();
}
文件写入已完成WriteAudioDataToFile()
并且工作正常:
private void WriteAudioDataToFile()
{
byte[] data = new byte[bufferSize];
string filename = GetTempFilename();
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(filename);
}
catch (Java.IO.FileNotFoundException e)
{
}
int read = 0;
if (null != fos)
{
while (isRecording)
{
read = audioRecord.Read(data, 0, bufferSize);
if ((int)RecordStatus.ErrorInvalidOperation != read)
{
try
{
fos.Write(data);
}
catch (Java.IO.IOException e)
{
}
}
}
try
{
fos.Close();
}
catch (Java.IO.IOException e)
{
}
}
}
我想在文件写入后执行其他任务:
void OnNext()
{
short[] audioBuffer = new short[2048];
audioRecord.Read(audioBuffer, 0, audioBuffer.Length);
int[] result = new int[audioBuffer.Length];
for (int i = 0; i < audioBuffer.Length; i++)
{
result[i] = (int)audioBuffer[i];
}
samplesUpdated(this, new SamplesUpdatedEventArgs(result));
}
如果我OnNext()
从调用StartRecording()
,而不编写文件,这可以正常工作,并且我得到了频谱图的预期值:
public async Task StartRecording()
{
audioRecord = new AudioRecord(AudioSource.Mic, 44100, ChannelIn.Mono, Android.Media.Encoding.Pcm16bit, bufferSize);
if (audioRecord.State == State.Initialized)
audioRecord.StartRecording();
isRecording = true;
while (audioRecord.RecordingState == RecordState.Recording)
{
OnNext();
}
}
但由于我需要结合文件写入和其他任务,我尝试在文件写入后移动该OnNext()
方法:
private void WriteAudioDataToFile()
{
//...
try
{
fos.Write(data);
short[] dataShort = new short[bufferSize];
dataShort = Array.ConvertAll(data, d => (short)d);
int[] result = new int[dataShort.Length];
for (int i = 0; i < dataShort.Length; i++)
{
result[i] = (int)dataShort[i];
}
samplesUpdated(this, new SamplesUpdatedEventArgs(result));
}
catch (Java.IO.IOException e)
{
}
//...
}
但这根本不像预期的那样工作:
- 录制的文件似乎“损坏”:当我听到声音时,声音是“加速”的
- 我为频谱图得到的值不正确:问题似乎来自
byte[]
转换short[]
我不明白如何管理audioRecord.Read(data, 0, bufferSize)
:
- 我需要
byte[]
用于文件写入:fos.Write(data);
- 我需要
short[]
用于其他任务
=> 实现这一目标的更好方法应该是什么?
编辑:
我已经尝试过这些方法,但这并没有改变任何东西:
- 使用相同的 AudioRecord 创建第二个线程以显示频谱图
- 使用另一个 AudioRecord 创建第二个线程以显示频谱图
我还查看了 AudioRecord 停止后是否可以写入文件,但似乎也不可能......
解决方案
推荐阅读
- apache - 为 Wamp 和 Windows 上的所有虚拟主机创建 Robots.txt
- url-rewriting - 使用新方法将应用程序 Domino 9.0.1 Xpages 移植到 Domino 10
- google-cloud-dataflow - java.lang.IllegalArgumentException:使用未知视图调用 sideInput()
- yii - 限制多个用户的数据
- python - 如何使用 Python 展平这样的数组?
- php - 获取数据块以显示
- gooddata - 在 SDK 中获取上一期间/SP 上一年措施的标题?
- asp.net-core-2.1 - 具有动态配置的 HttpClientFactory
- javascript - 如何使用 C# 从网站读取字符串
- python - 未找到 pip 安装的模块 - macOS