2013-03-15 107 views
2

我想将传入的流数据保存到我的硬盘驱动器上的WAV文件。如何更改下面的代码以便能够将流录制到有效的WAV文件中?使用NAudio将流数据保存到WAV文件

从演示here

private void StreamMP3(object state) 
{ 
    this.fullyDownloaded = false; 
    string url = (string)state; 
    webRequest = (HttpWebRequest)WebRequest.Create(url); 
    HttpWebResponse resp = null; 
    try 
    { 
     resp = (HttpWebResponse)webRequest.GetResponse(); 
    } 
    catch(WebException e) 
    { 
     if (e.Status != WebExceptionStatus.RequestCanceled) 
     { 
      ShowError(e.Message); 
     } 
     return; 
    } 
    byte[] buffer = new byte[16384 * 4]; // Needs to be big enough to hold a decompressed frame 

    IMp3FrameDecompressor decompressor = null; 
    try 
    { 
     using (var responseStream = resp.GetResponseStream()) 
     { 
      var readFullyStream = new ReadFullyStream(responseStream); 
      do 
      { 
       if (bufferedWaveProvider != null && 
        bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes < 
         bufferedWaveProvider.WaveFormat.AverageBytesPerSecond/4) 
       { 
        Debug.WriteLine("Buffer getting full, taking a break"); 
        Thread.Sleep(500); 
       } 
       else 
       { 
        Mp3Frame frame = null; 
        try 
        { 
         frame = Mp3Frame.LoadFromStream(readFullyStream); 
        } 
        catch (EndOfStreamException) 
        { 
         this.fullyDownloaded = true; 

         // Reached the end of the MP3 file/stream 
         break; 
        } 
        catch (WebException) 
        { 
         // Probably we have aborted download from the GUI thread 
         break; 
        } 
        if (decompressor == null) 
        { 
         // I don't think these details matter too much - just help ACM select the right codec. 
         // However, the buffered provider doesn't know what sample rate it is working at 
         // until we have a frame. 
         WaveFormat waveFormat = new Mp3WaveFormat(
                frame.SampleRate, 
                frame.ChannelMode == ChannelMode.Mono ? 1 : 2, 
                frame.FrameLength, 
                frame.BitRate); 
         decompressor = new AcmMp3FrameDecompressor(waveFormat); 
         this.bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat); 
         this.bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(20); // Allow us to get well ahead of ourselves 
         //this.bufferedWaveProvider.BufferedDuration = 250; 
        } 
        int decompressed = decompressor.DecompressFrame(frame, buffer, 0); 
        //Debug.WriteLine(String.Format("Decompressed a frame {0}", decompressed)); 
        bufferedWaveProvider.AddSamples(buffer, 0, decompressed); 
       } 

      } while (playbackState != StreamingPlaybackState.Stopped); 

      Debug.WriteLine("Exiting"); 
      // I was doing this in a finally block, but for some reason 
      // we are hanging on response stream .Dispose, so we never get there. 
      decompressor.Dispose(); 
     } 
    } 
    finally 
    { 
     if (decompressor != null) 
     { 
      decompressor.Dispose(); 
     } 
    } 
} 

回答

2

我不会采取特定的方法来保存到磁盘。这有点太实际了,因为它必须以正确的速度回放。只是缓冲了反应,然后在Mp3FileReader流包裹再用WaveFileWriter写的WAV文件:

MemoryStream mp3Buffered = new MemoryStream(); 
using (var responseStream = resp.GetResponseStream()) 
{ 
    byte[] buffer = new byte[65536]; 
    int bytesRead = responseStream.Read(buffer, 0, buffer.Length); 
    while (bytesRead > 0) 
    { 
     mp3Buffered.Write(buffer, 0, bytesRead); 
     bytesRead = responseStream.Read(buffer, 0, buffer.Length); 
    } 
} 

mp3Buffered.Position = 0; 
using (var mp3Stream = new Mp3FileReader(mp3Buffered)) 
{  
    WaveFileWriter.CreateWaveFile("file.wav", mp3Stream); 
} 

这不,当然,假设你的MP3文件的波形格式是WAV,特别是兼容,你的WAV播放器。如果不是,则还需要注入并添加WaveFormatConversion流。

+0

嗨,mp3Stream没有一个方法称为CopyTo !! – lebhero 2013-03-15 21:18:00

+0

我想你使用的是.NET 3.5或更早的版本。实际上有一个更简单的方法,无论如何,我编辑了答案。 – MattW 2013-03-15 21:21:27

+0

感谢马特你的帮助,仍然,有没有办法编辑上面的代码,以便将流文件保存为有效的wav?... 代码返回一个异常:此流不支持查找操作。这正是你告诉我的.. – lebhero 2013-03-15 21:26:38