Save streaming data to a WAV file using NAudio

浪尽此生 提交于 2020-01-02 10:04:32

问题


I want to save the incoming stream data to a WAV file on my hard disk drive. How can I change the code below to be able to record the stream into a valid WAV file?

From the demo 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();
        }
    }
}

回答1:


I wouldn't take that particular approach to saving to disk. It's a bit too hands-on, because it has to deal with playing back at the right rate. Just buffer up the response, and then wrap it in an Mp3FileReader stream and use WaveFileWriter to write the WAV file:

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);
}

That does, of course, assume that your MP3 file's wave format is compatible with WAV and in particular, your WAV player. If it isn't, you'll need to inject and add a WaveFormatConversion stream as well.



来源:https://stackoverflow.com/questions/15441980/save-streaming-data-to-a-wav-file-using-naudio

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!