Play audio from a stream using C#

2019-01-01 01:22发布

Is there a way in C# to play audio (for example, MP3) direcly from a System.IO.Stream that for instance was returend from a WebRequest without saving the data temporarily to the disk?


Solution with NAudio

With the help of NAudio 1.3 it is possible to:

  1. Load an MP3 file from a URL into a MemoryStream
  2. Convert MP3 data into wave data after it was completely loaded
  3. Playback the wave data using NAudio's WaveOut class

It would have been nice to be able to even play a half loaded MP3 file, but this seems to be impossible due to the NAudio library design.

And this is the function that will do the work:

    public static void PlayMp3FromUrl(string url)
    {
        using (Stream ms = new MemoryStream())
        {
            using (Stream stream = WebRequest.Create(url)
                .GetResponse().GetResponseStream())
            {
                byte[] buffer = new byte[32768];
                int read;
                while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
            }

            ms.Position = 0;
            using (WaveStream blockAlignedStream =
                new BlockAlignReductionStream(
                    WaveFormatConversionStream.CreatePcmStream(
                        new Mp3FileReader(ms))))
            {
                using (WaveOut waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
                {
                    waveOut.Init(blockAlignedStream);
                    waveOut.Play();                        
                    while (waveOut.PlaybackState == PlaybackState.Playing )                        
                    {
                        System.Threading.Thread.Sleep(100);
                    }
                }
            }
        }
    }

9条回答
残风、尘缘若梦
2楼-- · 2019-01-01 02:21

Bass can do just this. Play from Byte[] in memory or a through file delegates where you return the data, so with that you can play as soon as you have enough data to start the playback..

查看更多
路过你的时光
3楼-- · 2019-01-01 02:22

The SoundPlayer class can do this. It looks like all you have to do is set its Stream property to the stream, then call Play.

edit
I don't think it can play MP3 files though; it seems limited to .wav. I'm not certain if there's anything in the framework that can play an MP3 file directly. Everything I find about that involves either using a WMP control or interacting with DirectX.

查看更多
情到深处是孤独
4楼-- · 2019-01-01 02:23

I've always used FMOD for things like this because it's free for non-commercial use and works well.

That said, I'd gladly switch to something that's smaller (FMOD is ~300k) and open-source. Super bonus points if it's fully managed so that I can compile / merge it with my .exe and not have to take extra care to get portability to other platforms...

(FMOD does portability too but you'd obviously need different binaries for different platforms)

查看更多
登录 后发表回答