Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

How would I play audio packets in MediaPlayer?

I have a function, that gets audio packets (part of a song) to a byte array. I would then like to play that byte array continiusly. I tried to save them into a temporary file, and then play that file. But because I do not receive the full song, the parts of that song have a slight delay. I checked around and might it be that the mp3 files have padding? (delay between playing files - unlike wav, that dont have it? - tried to transfer wav format, nothing happens "Unable to create mediaplayer"). Another possibility is that it doesnt happen simultaneously, like it should write to the file, while it is reading it, because now, it writes a pack, plays it and writes another pack. How would this be? I need to transfer only parts, because if I transfer more, it takes to long.
Here is my class to play on the receiving end:

public void Read()
{
    System.Threading.Tasks.Task.Run(() =>
    {
        Java.IO.File temp = Java.IO.File.CreateTempFile("temp", "wav");
        Java.IO.FileInputStream fis = new Java.IO.FileInputStream(temp);
        temp.DeleteOnExit();

        MediaPlayer player = new MediaPlayer();

        while (mmInStream.CanRead)
        {
            try
            {                   
                byte[] myReadBuffer = new byte[10000];
                Java.IO.FileOutputStream fos = new Java.IO.FileOutputStream(temp);

                mmInStream.Read(myReadBuffer, 0, myReadBuffer.Length);
                fos.Write(myReadBuffer);

                player.SetDataSource(fis.FD);
                player.Prepare();
                player.Start();

                while (true)
                {
                    if (!player.IsPlaying)
                    {
                        player.Stop();
                        player.Reset();
                        break;
                    }
                }
            }
            catch (System.IO.IOException ex)
            {
                System.Diagnostics.Debug.WriteLine("Input stream was disconnected", ex);
            }
        }
    }).ConfigureAwait(false);
}

The mmInStream is System.IO.Stream.

Answers

  • FaizalSaidaliFaizalSaidali USMember ✭✭✭

    Hi @mtsABC,
    Refer the given link, it may helps you to resolve your problem.
    https://developer.android.com/guide/topics/media/mediaplayer

  • mtsABCmtsABC Member ✭✭
    I did try to find anything usefull in that documentation, but came up empty.
  • FaizalSaidaliFaizalSaidali USMember ✭✭✭

    @mtsABC
    I haven't tried this solution. I hope it will works for you.
    I saw your another thread of How to play audio from byte. In that LandLu suggest you one method to invoke custom MediaDataSource for configuring the byte array to DataSource. You can follow that way and try currentPlayer.PrepareAsync(); and MediaPlayer.OnPreparedListener as well.
    REF: https://developer.android.com/guide/topics/media/mediaplayer#asyncprepare

  • mtsABCmtsABC Member ✭✭
    Did try that but that was for ghe whole file and if I try paying paets it give me a Unable to create superclass of MediaDataSource.
  • jezhjezh Member, Xamarin Team Xamurai

    @mtsABC
    Could you please post the full log of your error when you tried land's method?

  • mtsABCmtsABC Member ✭✭
    edited December 2019
    Here it is:
    12-01 20:54:38.887 D/AbsListView(12444): Get MotionRecognitionManager

    12-01 20:54:38.947 W/ResourceType(12444): Failure getting entry for 0x010802c9 (t=7 e=713) in package 0 (error -75)
    12-01 20:54:45.073 V/BluetoothSocket.cpp(12444): initSocketNative
    12-01 20:54:45.073 V/BluetoothSocket.cpp(12444): ...fd 53 created (RFCOMM, lm = 26)
    12-01 20:54:45.073 V/BluetoothSocket.cpp(12444): initSocketFromFdNative
    12-01 20:54:45.113 D/BluetoothUtils(12444): isSocketAllowedBySecurityPolicy start : device null
    12-01 20:54:46.364 V/BluetoothSocket.cpp(12444): connectNative
    12-01 20:54:46.424 V/BluetoothSocket.cpp(12444): ...connect(53, RFCOMM) = 0 (errno 115)
    12-01 20:54:46.484 I/Choreographer(12444): Skipped 88 frames! The application may be doing too much work on its main thread.
    12-01 20:54:51.669 V/MediaPlayer(12444): constructor
    12-01 20:54:51.679 V/MediaPlayer(12444): setListener
    12-01 20:54:51.719 W/dalvikvm(12444): Unable to resolve superclass of Lmd5c539bdc79f76d0c80e6cd44011eba829/StreamMediaDataSource; (388)
    12-01 20:54:51.719 W/dalvikvm(12444): Link of class 'Lmd5c539bdc79f76d0c80e6cd44011eba829/StreamMediaDataSource;' failed
    12-01 20:54:55.693 V/MediaPlayer(12444): constructor
    12-01 20:54:55.693 V/MediaPlayer(12444): setListener
    12-01 20:54:55.703 W/dalvikvm(12444): Unable to resolve superclass of Lmd5c539bdc79f76d0c80e6cd44011eba829/StreamMediaDataSource; (388)
    12-01 20:54:55.703 W/dalvikvm(12444): Link of class 'Lmd5c539bdc79f76d0c80e6cd44011eba829/StreamMediaDataSource;' failed
    Thread finished: <Thread Pool> #5

    Sory for this format, I posted it on my phone and cant seem to get it to code format. Will post fixed when I get home.
  • jezhjezh Member, Xamarin Team Xamurai

    According to the log you post ,it seemed that your code couldn't find the class StreamMediaDataSource .

    Have you implemented class StreamMediaDataSource ?

       public class StreamMediaDataSource : MediaDataSource{
    
         }
    
  • mtsABCmtsABC Member ✭✭

    Yes I did here it is

    `public class StreamMediaDataSource : MediaDataSource
    {
        System.IO.Stream data;
    
        public StreamMediaDataSource(System.IO.Stream Data)
        {
            data = Data;
        }
    
        public override long Size
        {
            get
            {
                return data.Length;
            }
        }
    
        public override int ReadAt(long position, byte[] buffer, int offset, int size)
        {
            data.Seek(position, System.IO.SeekOrigin.Begin);
            return data.Read(buffer, offset, size);
        }
    
        public override void Close()
        {
            if (data != null)
            {
                data.Dispose();
                data = null;
            }
        }
    
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
    
            if (data != null)
            {
                data.Dispose();
                data = null;
            }
        }
    }`
    
Sign In or Register to comment.