使用 NAudio 转换为 WAV 后使用 SoundPlayer 播放 MP3
Posted
技术标签:
【中文标题】使用 NAudio 转换为 WAV 后使用 SoundPlayer 播放 MP3【英文标题】:Play MP3 using SoundPlayer after conversion to WAV using NAudio 【发布时间】:2013-01-29 11:00:45 【问题描述】:我想使用 NET 提供的System.Media.SoundPlayer 机制播放从网上下载的 MP3 文件。由于它适用于 WAV 格式,因此需要例如支持。 NAudio library - 我需要将 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 ? */
怎么做?第二个代码示例有什么问题?
【问题讨论】:
【参考方案1】:根据 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) 有什么问题。
【讨论】:
很好,很高兴你想通了。 +1 使用流媒体功能,我没有注意到 NAudio 可以做到这一点。 花括号楼梯箱很棒。 (嘿,押韵!)【参考方案2】:为什么不跳过使用 SoundPlayer 直接通过 NAudio 播放 MP3? NAudio 就是为此而设计的。只需将 MP3 下载到某个地方的临时文件中,然后使用 NAudio 播放,完成后删除临时文件。不过,我认为没有什么办法可以减少下载文件时的延迟。
http://naudio.codeplex.com/wikipage?title=MP3
【讨论】:
NAudioDemo 源代码包含一个如何播放从网络接收的流式 MP3 的演示,因此不需要临时文件。 +1 这不是一个答案,而是建设性的通知,谢谢以上是关于使用 NAudio 转换为 WAV 后使用 SoundPlayer 播放 MP3的主要内容,如果未能解决你的问题,请参考以下文章