Playing live audio from DatagramSocket

Hi,

I was wondering about how I would go about playing live audio from a DatagramSocket. Currently I am sending live microphone data to a server, which is then sending it back to the client. My issue is that I'm not sure how to play the returned audio. This may seem like a weird thing to do, but the reason I'm doing this is because later on in my project I will be broadcasting the same audio data from the server to multiple clients, and I need them to all be able to play it without an issue.

    public void JoinChat() {

        new Thread(() => {

            int minBufSize = AudioTrack.GetMinBufferSize(44100, ChannelOut.Mono, Encoding.Pcm16bit);
            DatagramSocket socket = new DatagramSocket();
            byte[] buffer = new byte[minBufSize];
            DatagramPacket packet;
            InetAddress destination = InetAddress.GetByName(serverAddress);
            recorder = new AudioRecord(AudioSource.Mic, 44100, ChannelIn.Mono, Encoding.Pcm16bit, minBufSize * 10);

            recorder.StartRecording();

            while (status) {

                minBufSize = recorder.Read(buffer, 0, buffer.Length);
                packet = new DatagramPacket(buffer, buffer.Length, destination, port);

                socket.Send(packet);

                //This is the section where I'd like to read the audio data being sent back from the server and then play it through the speakers.

            }

        }).Start();

    }

Answers

  • BillyLiuBillyLiu Member, Xamarin Team Xamurai

    @Technerder

    My issue is that I'm not sure how to play the returned audio.

    First, get the data from the server.

    packet = new DatagramPacket(buf, buf.length);
    socket.receive(packet);
    var data = packet.getData();
    

    Next, convert it to an audio file such as .mp3. Then you could play it with MediaPlayer or something else.
    Please check the following links for more information:
    https://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html
    https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/android-audio
    https://stackoverflow.com/questions/1972027/android-playing-mp3-from-byte

  • TechnerderTechnerder Member ✭✭

    Current I'm trying this but on the C# Side, GetCacheDir() and GetFD() are not valid methods.

    Java Code (For Server):

    package com.thing;
    
    import java.io.ByteArrayInputStream;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    
    import javax.sound.sampled.AudioFormat;
    import javax.sound.sampled.AudioInputStream;
    import javax.sound.sampled.AudioSystem;
    import javax.sound.sampled.DataLine;
    import javax.sound.sampled.FloatControl;
    import javax.sound.sampled.LineUnavailableException;
    import javax.sound.sampled.SourceDataLine;
    
    public class Server {
    
        public static AudioInputStream ais;
        private static AudioFormat format = new AudioFormat(44100, 16, 1, true, false);
    
        @SuppressWarnings("resource")
        public static void main(String args[]) throws Exception {
    
            DatagramSocket serverSocket = new DatagramSocket(50005);
            byte[] receiveData = new byte[64000];
    
            while (true) {
    
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                serverSocket.receive(receivePacket);
                ByteArrayInputStream baiss = new ByteArrayInputStream(receivePacket.getData());
                ais = new AudioInputStream(baiss, format, receivePacket.getLength());
    
                new Thread(() -> {
    
                    try {
    
                        toSpeaker(receivePacket.getData());
    
                    } catch (LineUnavailableException e) {
    
                        e.printStackTrace();
    
                    }
    
                }).start();
    
            }
    
        }
    
        public static void toSpeaker(byte soundbytes[]) throws LineUnavailableException {
    
            DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, format);
            SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
    
            sourceDataLine.open(format);
    
            FloatControl volumeControl = (FloatControl) sourceDataLine.getControl(FloatControl.Type.MASTER_GAIN);
            volumeControl.setValue(6.0f);
    
            sourceDataLine.start();
            sourceDataLine.open(format);
            sourceDataLine.start();
    
            sourceDataLine.write(soundbytes, 0, soundbytes.length);
            sourceDataLine.drain();
            sourceDataLine.close();
    
        }
    
    }
    

    C# Code (For app):

    using System;
    using Android.App;
    using Android.OS;
    using Android.Widget;
    using Android.Support.V7.App;
    using Java.Net;
    using Android.Media;
    using System.Threading;
    using Android.Support.V4.App;
    using Android;
    using Android.Content.PM;
    using Android.Net.Rtp;
    using Java.IO;
    
    namespace AudioChat {
    
        [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
        public class MainActivity : AppCompatActivity {
    
            public byte[] buffer;
            private Button button;
            private int port = 50005;
            private AudioRecord recorder;
            private Boolean status = true;
            public static DatagramSocket socket;
            private String serverAddress = "192.168.1.18";
    
            protected override void OnCreate(Bundle savedInstanceState) {
    
                base.OnCreate(savedInstanceState);
                SetContentView(Resource.Layout.activity_main);
    
                button = FindViewById<Button>(Resource.Id.button);
    
                button.Click += ToggleJoin;
    
                if (Android.Support.V4.Content.ContextCompat.CheckSelfPermission(this, Manifest.Permission.RecordAudio) != (int)Permission.Granted) {
    
                    ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.RecordAudio }, 1);
    
                }
    
            }
    
            public void ToggleJoin(object sender, EventArgs args) {
    
                if (button.Pressed) {
    
                    status = true;
                    JoinChat();
    
                } else {
    
                    status = false;
                    recorder.Release();
    
                }
    
            }
    
            private MediaPlayer mediaPlayer = new MediaPlayer();
    
            private void playMp3(byte[] mp3SoundByteArray) {
    
                try {
    
                    File tempMp3 = File.CreateTempFile("kurchina", "mp3", GetCacheDir());
                    tempMp3.DeleteOnExit();
                    FileOutputStream fos = new FileOutputStream(tempMp3);
                    fos.Write(mp3SoundByteArray);
                    fos.Close();
    
                    mediaPlayer.Reset();
                    FileInputStream fis = new FileInputStream(tempMp3);
                    mediaPlayer.SetDataSource(fis.GetFD());
    
                    mediaPlayer.Prepare();
                    mediaPlayer.Start();
    
                } catch (IOException ex) {
    
                    ex.PrintStackTrace();
    
                }
    
            }
    
            public void JoinChat() {
    
                new Thread(() => {
    
                    int minBufSize = AudioTrack.GetMinBufferSize(44100, ChannelOut.Mono, Encoding.Pcm16bit);
                    DatagramSocket socket = new DatagramSocket();
                    byte[] buffer = new byte[minBufSize];
                    DatagramPacket packet;
                    InetAddress destination = InetAddress.GetByName(serverAddress);
                    recorder = new AudioRecord(AudioSource.Mic, 44100, ChannelIn.Mono, Encoding.Pcm16bit, minBufSize * 10);
    
                    recorder.StartRecording();
    
                    while (status) {
    
                        minBufSize = recorder.Read(buffer, 0, buffer.Length);
                        packet = new DatagramPacket(buffer, buffer.Length, destination, port);
    
                        socket.Send(packet);
    
                        socket.Receive(packet);
                        var data = packet.GetData();
    
                        //This is the section where I'd like to read the audio data being sent back from the server and then play it through the speakers.
    
                    }
    
                }).Start();
    
            }
    
        }
    
    }
    
  • BillyLiuBillyLiu Member, Xamarin Team Xamurai

    @Technerder

    Current I'm trying this but on the C# Side, GetCacheDir() and GetFD() are not valid methods.

    Please use CacheDir and FilesDir instead.

Sign In or Register to comment.