我正在尝试使用NAudio录制8秒的流式音频,将其存储在System.IO.MemoryStream
中,然后立即播放。为此,我运行以下代码:
using System.IO;
using NAudio.Wave;
public class AudioCapture{
static WaveFileWriter wri;
static bool stopped = false;
public AudioCapture(){
//record from loopback
IWaveIn waveIn = new WasapiLoopbackCapture();
waveIn.DataAvailable += waveIn_DataAvailable;
waveIn.RecordingStopped += waveIn_RecordingStopped;
//write loopback capture to MemoryStream
Stream sos = new MemoryStream();
wri = new WaveFileWriter(sos, waveIn.WaveFormat);
//record 8 seconds of streaming audio
waveIn.StartRecording();
System.Threading.Thread.Sleep(8000);
waveIn.StopRecording();
//flush and dispose objects
wri.Flush();
waveIn.Dispose();
wri.Dispose();
//play back recorded audio
WaveOut waveOut = new WaveOut();
WaveFileReader waveFileReader = new WaveFileReader(sos);
waveOut.Init(waveFileReader);
waveOut.Play();
}
static void waveIn_RecordingStopped(object sender, StoppedEventArgs e){
stopped = true;
}
static void waveIn_DataAvailable(object sender, WaveInEventArgs e){
if (wri != null) wri.Write(e.Buffer, 0, e.BytesRecorded);
}
}
我收到以下异常,告诉我无法读取流:
Activated Event Time Duration Thread
Exception: Exception thrown: 'System.ArgumentException' in NAudio.dll
("Stream was not readable."). Exception thrown: 'System.ArgumentException' in
NAudio.dll ("Stream was not readable.") 17.86s [17404] <No Name>
根据文档,我不太确定问题是什么,因为WaveFileWriter明确接受MemoryStream
。我缺少一些转换吗?任何帮助,将不胜感激。谢谢!
澄清:错误似乎在这一行:
WaveFileReader waveFileReader = new WaveFileReader(sos);
答案 0 :(得分:2)
WaveFileWriter
(不幸的是)设计的方式是始终处理它在处理WaveFileWriter
时写入的流。它本可以接受一些标志来控制这种行为,但事实并非如此。因此,如果您以后需要使用该流,则需要过早地处置WaveFileWriter
,或者克隆该已关闭的内存流。如果您选择不处理编写器 - 您需要将内存流回退到位置0,以便从头开始读取(在写入位置结束后):
wri.Flush();
waveIn.Dispose();
// wri.Dispose(); < too early
sos.Seek(0, SeekOrigin.Begin);
如果您想使用克隆 - 不需要快退:
wri.Flush();
waveIn.Dispose();
wri.Dispose();
sos = new MemoryStream(sos.ToArray());
克隆的缺点是它会创建整个字节数组的不必要副本(ToArray
调用)。
答案 1 :(得分:1)
在此方案中无需使用WaveFileReader
或WaveFileWriter
。只需将收到的音频写入MemoryStream
:
static void waveIn_DataAvailable(object sender, WaveInEventArgs e){
if (sos != null) sos.Write(e.Buffer, 0, e.BytesRecorded);
}
然后当你完成并准备好播放时,请回放MemoryStream
并使用RawSourceWaveStream
播放:
//play back recorded audio
var waveOut = new WaveOut();
sos.Position = 0;
var waveFileReader = new RawSourceWaveStream(sos, waveIn.WaveFormat);
waveOut.Init(waveFileReader);
waveOut.Play();