我想使用NET提供的System.Media.SoundPlayer机制播放从网上下载的MP3文件。由于它适用于WAV格式,因此需要例如WAV格式的支持。 NAudio库 - 我需要将MP3转换为WAV。
我想在内存中执行所有操作,因为我需要快速调用它,但我有问题。下面我展示的代码按预期工作,但它与文件合作。相反,我需要让它仅使用内存操作。
(1)有效,但涉及磁盘操作:
public void Speak(Uri mp3FileUri)
{
using (var client = new WebClient())
{
using (var networkStream = client.OpenRead(mp3FileUri))
{
if (networkStream != null)
{
var temp = Path.GetTempPath();
var mp3File = Path.Combine(temp, "file.mp3");
var wavFile = Path.Combine(temp, "file.wav");
using (var fileStream = File.Create(mp3File))
{
networkStream.CopyTo(fileStream);
}
using (var reader = new Mp3FileReader(mp3File))
{
WaveFileWriter.CreateWaveFile(wavFile, reader);
}
using(var player = new SoundPlayer(wavFile))
{
player.Play();
}
}
}
}
}
(2)不起作用 - 没有抛出异常,但没有播放:
public void Speak(Uri mp3FileUri)
{
using (var client = new WebClient())
{
using (var networkStream = client.OpenRead(mp3FileUri))
{
if (networkStream != null)
{
var memStream = new MemoryStream();
networkStream.CopyTo(memStream);
memStream.Position = 0;
using (var reader = new Mp3FileReader(memStream))
{
var outStream = new MemoryStream();
using (var writer = new WaveFileWriter(outStream, reader.WaveFormat))
{
var num = 0L;
var buffer = new byte[reader.WaveFormat.AverageBytesPerSecond * 4];
while (true)
{
var count = reader.Read(buffer, 0, buffer.Length);
if (count != 0)
{
num += count;
if (num <= int.MaxValue)
writer.Write(buffer, 0, count);
else
throw new InvalidOperationException("Too large file or endless stream.");
}
else
break;
}
writer.Flush();
outStream.Position = 0;
using(var player = new SoundPlayer(outStream))
{
player.Play(); /* why silence ? */
}
}
}
}
}
}
}
如何处理以及第二个代码示例有什么问题?
答案 0 :(得分:2)
为什么不跳过使用SoundPlayer直接通过NAudio播放MP3? NAudio旨在实现这一目标。只需将MP3下载到某个地方的临时文件中,然后使用NAudio播放它,并在完成后删除临时文件。我不认为在下载文件时可以采取任何措施来减少延迟。
答案 1 :(得分:2)
根据Lee Harrison的回答,我已经创建了更好的替代代码。
(3)直接从WEB播放MP3文件而不转换为WAV并且不使用磁盘操作:
public void Speak(Uri mp3FileUri)
{
using (var client = new WebClient())
{
using (var networkStream = client.OpenRead(mp3FileUri))
{
if (networkStream != null)
{
using (var memStream = new MemoryStream())
{
networkStream.CopyTo(memStream);
memStream.Position = 0;
using (var waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
{
var waveEvent = new ManualResetEvent(false);
waveOut.PlaybackStopped += (sender, e) => waveEvent.Set();
waveEvent.Reset();
using (var rdr = new Mp3FileReader(memStream))
using (var waveStream = WaveFormatConversionStream.CreatePcmStream(rdr))
using (var baStream = new BlockAlignReductionStream(waveStream))
{
waveOut.Init(baStream);
waveOut.Play();
if (waveOut.PlaybackState != PlaybackState.Stopped)
{
waveEvent.WaitOne(); /* block thread for a while because I don't want async play back
(to be analogical as usage of SoundPlayer Play method) */
}
}
}
}
}
}
}
}
尽管如此(尽管这对我来说非常好),我仍然不知道样本(2)的问题是什么。