This project has moved. For the latest updates, please go here.

Play mp3 from http source

Dec 3, 2010 at 1:57 AM

Good day !

I would like to use NAudio to stream music from a local server I have that serves mp3s over http. Currently, I don't think NAudio supportrs this as I get an exception when trying to load a downloaded stream. 

 

So far here is my code:

[...]

                mainOutputStream = CreateInputStream(track.TrackUri.OriginalString);
                waveOut = new NAudio.Wave.WasapiOut(NAudio.CoreAudioApi.AudioClientShareMode.Shared, false, 300);
                if (waveOut != null)
                {
                    waveOut.Init(mainOutputStream);
                    waveOut.Play();
                var stream = (new WebClient()).OpenRead(fileName);
[...]
And this is the portion that creates the wavestream

                WaveStream mp3Reader = new Mp3FileReader(stream);
                //WaveStream pcmStream = WaveFormatConversionStream.CreatePcmStream(mp3Reader);
                //WaveStream blockAlignedStream = new BlockAlignReductionStream(mp3Reader);
                inputStream = new WaveChannel32(mp3Reader);
                inputStream.Pan = 0;
                inputStream.Volume = 1;

Upon creating the Mp3FileReader, I get an exception stating: 
"This stream does not support seek operations."

Are there any plans to support streaming in the near future? Anybody have a working solution for this ?

Thanks!
Eric.

Coordinator
Dec 3, 2010 at 8:57 AM

hi Eric,

Please see this blog post I wrote recently about this. It is the table of content generation that causes the main issue now. I'd like to fix that in a future version of NAudio.

Mark

Jan 12, 2011 at 6:29 PM
Edited Jan 12, 2011 at 6:30 PM

There is a solution to this - Converting the non-seekable stream to a byte array. Then creating a memory stream of the byte array.
Works like a charm but dont know if there are any drawbacks or issues(I have only tried playback and it works).


Example:
....

Stream myStream = new MemoryStream(ConvertNonSeekableStreamToByteArray(myNonSeekableStream));
WaveStream mp3Reader = new Mp3FileReader(myStream);

....

static byte[] ConvertNonSeekableStreamToByteArray(Stream NonSeekableStream)
{
    MemoryStream ms = new MemoryStream();
    byte[] buffer = new byte[1024];
    int bytes;
    while ((bytes = NonSeekableStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        ms.Write(buffer, 0, bytes);
    }
    byte[] output = ms.ToArray();
    return output;
}

       
References and credits to:
http://kseesharp.blogspot.com/2009/03/c-convert-non-seekable-stream-to-byte.html
http://bytes.com/topic/c-sharp/answers/248201-convert-byte-array-stream

 

Jan 12, 2011 at 6:38 PM

Cool thanks ! 

I'll definitely give this a try. Does this first load up the entire MP3 first ? Or will stream it ? What about a seekable stream ? If all of this works, maybe we can add this to NAudio ?

 

Thanks!

Eric.

Jan 12, 2011 at 6:38 PM

It will stream it! :D

Jan 12, 2011 at 6:41 PM

Sweet thanks!

Feb 6, 2011 at 4:24 PM
Faleij wrote:

It will stream it! :D

No, it won't stream it. ConvertNonSeekableStreamToByteArray reads all the stream content to the end and writes it to the byte array before playing.

Coordinator
Feb 6, 2011 at 6:54 PM

I posted about this on my blog a while back. The MP3 reader class does read the whole way through in advance in order to accurately report length and support re-streaming. I'd like to make a genuine streaming option for it in the future, but for now you would need to customise the MP3FileReader

http://mark-dot-net.blogspot.com/2010/11/state-of-mp3-playback-support-in-naudio.html

Mark