2013-03-15 109 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