Play mp3 from stream in real-time

Dec 25, 2012 at 3:24 PM
Edited Dec 25, 2012 at 5:30 PM

Hello. My english bad, sorry.

I need help with my player.

I have link "http://cs5880.userapi.com/u9002353/audios/5080e5649b40.mp3" (example)

How i can play this track in real-time?  (after 100-500ms? +-)

 

private MemoryStream ms;
private WaveOut waveOut;

It's first thread:

using (var stream = WebRequest.Create(url).GetResponse().GetResponseStream())
            {
                
                byte[] buffer = new byte[1024*64];
                int read;
                while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    var pos = ms.Position; 
                    ms.Position = ms.Length;
                    ms.Write(buffer, 0, read);
                    ms.Position = pos; 
                }

Last thread:

ms.Position = 0;
            using (var mp3FileReader = new Mp3FileReader(ms))
            using (var waveFormatConv = WaveFormatConversionStream.CreatePcmStream(mp3FileReader))
            using (var blockAlignedStream = new BlockAlignReductionStream(waveFormatConv))
            {
                waveOut = new WaveOut();
                waveOut.Init(blockAlignedStream);
                waveOut.Play();
                while (!taskWaveStop)
                {
                    Thread.Sleep(1 0);
                }
            }

 

But id3tag always in random position. If position of tag > my buffer, then i will be have random error.

What i do?

Coordinator
Dec 25, 2012 at 7:29 PM

Look at the NAudioDemo application source code. There is an example of playing a streaming MP3 file using the AcmMp3FrameDecompressor and the BufferedWaveProvider.

Mark

Coordinator
Dec 25, 2012 at 7:51 PM

Also, can I ask where you saw the sample code that uses WaveFormatConversionStream and BlockAlignReductionStream? This has not been necessary for a very long time, but it seems everyone is still using it. If possible I'd like to update the documentation that is showing the use of this.

thanks

Mark

Dec 25, 2012 at 9:45 PM

Thanks! I'll try it. 

Dec 28, 2012 at 4:20 AM

I used the code that you advised me. But i have problems again. This track "http://cs5047.userapi.com/u4714757/audios/c95bbdffbee6.mp3" is cbr.

But all frames always different.

frame = Mp3Frame.LoadFromStream(readFullyStream);
 And error - "AcmNotPossible calling acmStreamConvert"

Dec 29, 2012 at 6:10 PM
Edited Dec 29, 2012 at 7:04 PM

Please i need help. Why this code returns a random sample rate and channel? 8kHz stereo,48kHz mono,16kHz mono, 44,1kHz stereo,... ? But sound always has permanent sample rate and channel.

Track has a image, this can affect?

Dec 30, 2012 at 5:20 AM
Edited Dec 30, 2012 at 6:49 AM

I solved the problem. Just drop frames, which were randomly properties, and add those frames whose properties match more than 10 times.Maybe i someone  help with the error "AcmNotPossible calling acmStreamConvert".Sorry for bad english and bad code =)

private void StreamMP3(object state)
        {
            fullyDownloaded = false;
            var 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;
            }
            var buffer = new byte[16384*4]; // needs to be big enough to hold a decompressed frame
            const int maxMatchedFrames = 10;
            int matchedFramesCount = 0;
            int sampleRate = 44100;
            var channelMode = ChannelMode.JointStereo;
            bool matchedFramesReady = false;
            IMp3FrameDecompressor decompressor = null;
            try
            {
                using (Stream 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(100);
                        }
                        else
                        {
                            Mp3Frame frame = null;
                            try
                            {
                                frame = Mp3Frame.LoadFromStream(readFullyStream);
                                if (frame == null) 
                                    break;
                                if (!matchedFramesReady)
                                {
                                    if ((frame.SampleRate == sampleRate) && (frame.ChannelMode == channelMode))
                                    {
                                        matchedFramesCount++;
                                        if (matchedFramesCount == maxMatchedFrames)
                                        {
                                            matchedFramesReady = true;
                                        }
                                    }
                                    else
                                    {
                                        sampleRate = frame.SampleRate;
                                        channelMode = frame.ChannelMode;
                                        matchedFramesCount = 0;
                                    }
                                }
                            }
                            catch (EndOfStreamException)
                            {
                                fullyDownloaded = true;
                                break;
                            }
                            catch (WebException)
                            {
                                break;
                            }
                            if (!matchedFramesReady) continue;
                            if (decompressor == null)
                            {
                                WaveFormat waveFormat = new Mp3WaveFormat(frame.SampleRate,
                                                                          frame.ChannelMode == ChannelMode.Mono ? 1 : 2,
                                                                          frame.FrameLength, frame.BitRate);
                                decompressor = new AcmMp3FrameDecompressor(waveFormat);
                                bufferedWaveProvider = new BufferedWaveProvider(decompressor.OutputFormat);
                                bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(10);
                            }
                            int decompressed = decompressor.DecompressFrame(frame, buffer, 0);		            if (bufferedWaveProvider != null)
                            bufferedWaveProvider.AddSamples(buffer, 0, decompressed);
                        }
                    } while (playbackState != StreamingPlaybackState.Stopped);
                }
            }
            finally
            {
                if (decompressor != null)
                {
                    decompressor.Dispose();
                }
            }
        }

Coordinator
Jan 3, 2013 at 3:20 PM

ehat like are you getting the ACM not possible error on? And what are the values of MP3WaveFormat at that point?

Jan 4, 2013 at 3:33 PM

Are you sure that your stream is a mp3 stream?