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

How to play a mp3 format file saved in byte[] array

Feb 6, 2011 at 7:15 PM

Hello,

I am new here. I need play a mp3 format voice from a byte[] array. I used to use MCIsendstring to play .mp3 file but could not find a way to play directly from byte[] in memory.

So I googled and finally come here. I wrote bellow function to play but got MMexception with error "AcmNotPossible calling acmStreamConvert" on waveOut.Play();

         public bool PlayByteArray(byte[] Mp3)
        {

            using (Stream ms = new MemoryStream(Mp3))
            {
                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);
                        }
                    }
                }
            }

            return true;
        }

I am using VS 2008 express edition and win7 64bit, but I have already set my project complie for x86 platform.     

Thanks for any help in advance.

Coordinator
Feb 6, 2011 at 7:24 PM

you might want to start by getting the latest NAudio code out from source control and using that instead, as it removes the need for the WaveFormatConversionStream and the BlockAlignReductionStream

Mark

Feb 6, 2011 at 9:29 PM
Edited Feb 7, 2011 at 3:52 AM

Thank you for your quick reply.

I have downloaded naudio-64823. But I still have no clue how to play it. Could you give me a simple example?

 

Feb 6, 2011 at 9:35 PM

By the way, I tried http://naudio.codeplex.com/wikipage?title=MP3 before, but no luck, I got an exception "Only PCM supported" on the line with inputStream = new WaveChannel32(mp3Reader);

Feb 6, 2011 at 9:42 PM

Now I am trying to play a test .mp3 file following the guide at http://naudio.codeplex.com/wikipage?title=MP

 


            IWavePlayer waveOutDevice;
            WaveStream mainOutputStream;


            waveOutDevice = new WasapiOut(AudioClientShareMode.Shared, 100);

            mainOutputStream = CreateInputStream("TempChx.mp3");
            waveOutDevice.Init(mainOutputStream);
            waveOutDevice.Play();


When it run on line waveOutDevice.Init(mainOutputStream);

It got error at line 

throw new ArgumentException("Not a supported encoding");

in file DmoMediaType.cs SetWaveFormat()

  public void SetWaveFormat(WaveFormat waveFormat)
        {
            majortype = MediaTypes.MEDIATYPE_Audio;
            switch (waveFormat.Encoding)
            {
                case WaveFormatEncoding.Pcm:
                    subtype = AudioMediaSubtypes.MEDIASUBTYPE_PCM;
                    bFixedSizeSamples = true;
                    break;
                case WaveFormatEncoding.IeeeFloat:
                    subtype = AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT;
                    bFixedSizeSamples = true;
                    break;
                case WaveFormatEncoding.MpegLayer3:
                    subtype = AudioMediaSubtypes.WMMEDIASUBTYPE_MP3;
                    break;
                default:
                    throw new ArgumentException("Not a supported encoding");
            }
            formattype = DmoMediaTypeGuids.FORMAT_WaveFormatEx;
            if (cbFormat < Marshal.SizeOf(waveFormat))
                throw new InvalidOperationException("Not enough memory assigned for a WaveFormat structure");
            //Debug.Assert(cbFormat >= ,"Not enough space");
            Marshal.StructureToPtr(waveFormat, pbFormat, false);
        }

Coordinator
Feb 7, 2011 at 1:19 PM
what is mainOutputStream.WaveFormat.ToString() ?
Feb 8, 2011 at 4:05 AM

It run to   default:
                    throw new ArgumentException("Not a supported encoding");

waveFormat.ToString()    "32 bit PCM: 48kHz 2 channels wBitsPerSample:32 dwChannelMask:3 subFormat:00000003-0000-0010-8000-00aa00389b71 extraSize:22"   

 

Feb 11, 2011 at 11:11 PM

After reading your demo project, I find a way to play mps in byte[]. Thank you for your great work.

public static void Play(byte[] mediacontent)
        {
            if (waveOut != null)
            {
                if (waveOut.PlaybackState == PlaybackState.Paused)
                {
                    waveOut.Play();
                    return;
                }

                if (waveOut.PlaybackState == PlaybackState.Playing)
                {
                    CloseWaveOut();
                }
            }

            // we are in a stopped state
            // TODO: only re-initialise if necessary

            try
            {
                CreateWaveOut();
            }
            catch (Exception driverCreateException)
            {
                MessageBox.Show(String.Format("{0}", driverCreateException.Message));
                return;
            }

            try
            {
                mainOutputStream = CreateInputStream(mediacontent);
            }
            catch (Exception createException)
            {
                MessageBox.Show(String.Format("{0}", createException.Message), "Error Loading Sound Byte[]");
                return;
            }


            try
            {
                waveOut.Init(mainOutputStream);
            }
            catch (Exception initException)
            {
                MessageBox.Show(String.Format("{0}", initException.Message), "Error Initializing Output");
                return;
            }

            waveOut.Play();
        }

 private static void CreateWaveOut()
        {
            CloseWaveOut();
            int latency = 150;
            waveOut = new DirectSoundOut(latency);

        }

 private static WaveStream CreateInputStream(byte[] mediacontent)
        {
            WaveChannel32 inputStream;

            Stream ms = new MemoryStream(mediacontent);

            WaveStream mp3Reader = new Mp3FileReader(ms);
           inputStream = new WaveChannel32(mp3Reader);

          
            return inputStream;
        }

May 30, 2011 at 9:32 AM

Hi wordmountain,

    I'm using your code in my project. It's work find in windows vista & 7 but in windows xp, I got a problem that I don't understand.

My application stopped by unknown causes and not responding sometime .

Do you run these code in windows xp (Play continuously or loop)?

 

Please suggestion for me if you have any solution to solve it.

Thank you.

TC