(四)Android基于UDP的多客户端语音通信

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(四)Android基于UDP的多客户端语音通信相关的知识,希望对你有一定的参考价值。

参考技术A 在前三篇得基础上,这次研究了组播功能。非常感谢https://blog.csdn.net/jspping/article/details/64438515得贡献!

组播也就是通过MulticastSocket来进行开发,与DatagramSocket比较相类似,这次依然是用两个线程进行实现,发送线程MultiSendThread和接收线程MultiReceiveThread。废话不多说,开始码:

(一)MultiSendThread:

(1)初始化MuticastSocket

// 侦听的端口

try

    multicastSocket = new MulticastSocket(8082);

    // 使用D类地址,该地址为发起组播的那个ip段,即侦听10001的套接字

    address = InetAddress.getByName("239.0.0.1");

catch (IOException e)

    e.printStackTrace();



(2)初始化AudioRecord

protected LinkedList<byte[]> mRecordQueue;

int minBufferSize;

private static AcousticEchoCanceler aec;

private static AutomaticGainControl agc;

private static NoiseSuppressor nc;

AudioRecord audioRec;

byte[] buffer;

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)

private void initAudio()

    //播放的采样频率 和录制的采样频率一样

    int sampleRate = 44100;

    //和录制的一样的

    int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

    //录音用输入单声道  播放用输出单声道

    int channelConfig = AudioFormat.CHANNEL_IN_MONO;

    minBufferSize = AudioRecord.getMinBufferSize(

            sampleRate,

            channelConfig, AudioFormat.ENCODING_PCM_16BIT);

    System.out.println("****RecordMinBufferSize = " + minBufferSize);

    audioRec = new AudioRecord(

            MediaRecorder.Audiosource.MIC,

            sampleRate,

            channelConfig,

            audioFormat,

            minBufferSize);

    buffer = new byte[minBufferSize];

    if (audioRec == null)

        return;

   

    //声学回声消除器 AcousticEchoCanceler 消除了从远程捕捉到音频信号上的信号的作用

    if (AcousticEchoCanceler.isAvailable())

        aec = AcousticEchoCanceler.create(audioRec.getAudioSessionId());

        if (aec != null)

            aec.setEnabled(true);

       

   

    //自动增益控制 AutomaticGainControl 自动恢复正常捕获的信号输出

    if (AutomaticGainControl.isAvailable())

        agc = AutomaticGainControl.create(audioRec.getAudioSessionId());

        if (agc != null)

            agc.setEnabled(true);

       

   

    //噪声抑制器 NoiseSuppressor 可以消除被捕获信号的背景噪音

    if (NoiseSuppressor.isAvailable())

        nc = NoiseSuppressor.create(audioRec.getAudioSessionId());

        if (nc != null)

            nc.setEnabled(true);

       

   

    mRecordQueue = new LinkedList<byte[]>();



(3)开始录制,并实时发送出去

@Override

public void run()

    if (multicastSocket == null)

        return;

    try

        audioRec.startRecording();

        while (true)

            try

                byte[] bytes_pkg = buffer.clone();

                if (mRecordQueue.size() >= 2)

                    int length = audioRec.read(buffer, 0, minBufferSize);

                    // 组报

                    DatagramPacket datagramPacket = new DatagramPacket(buffer, length);

                    // 向组播ID,即接收group /239.0.0.1  端口 10001

                    datagramPacket.setAddress(address);

                    // 发送的端口号

                    datagramPacket.setPort(10001);

                    System.out.println("AudioRTwritePacket = " + datagramPacket.getData().toString());

                    multicastSocket.send(datagramPacket);

               

                mRecordQueue.add(bytes_pkg);

            catch (Exception e)

                // TODO Auto-generated catch block

                e.printStackTrace();

           

       

    catch (Exception e)

        e.printStackTrace();

   



(二)MultiReceiveThread

(1)初始化MulticastSocket

// 接收数据时需要指定监听的端口号

try

    multicastSocket = new MulticastSocket(10001);

    // 创建组播ID地址

    InetAddress address = InetAddress.getByName("239.0.0.1");

    // 加入地址

    multicastSocket.joinGroup(address);

catch (IOException e)

    e.printStackTrace();



(2)初始化AudioTrack

byte[] buffer;

AudioTrack audioTrk;

private void initAudioTracker()

    //扬声器播放

    int streamType = AudioManager.STREAM_MUSIC;

    //播放的采样频率 和录制的采样频率一样

    int sampleRate = 44100;

    //和录制的一样的

    int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

    //流模式

    int mode = AudioTrack.MODE_STREAM;

    //录音用输入单声道  播放用输出单声道

    int channelConfig = AudioFormat.CHANNEL_OUT_MONO;

    int recBufSize = AudioTrack.getMinBufferSize(

            sampleRate,

            channelConfig,

            audioFormat);

    System.out.println("****playRecBufSize = " + recBufSize);

    audioTrk = new AudioTrack(

            streamType,

            sampleRate,

            channelConfig,

            audioFormat,

            recBufSize,

            mode);

    audioTrk.setStereoVolume(AudioTrack.getMaxVolume(),

            AudioTrack.getMaxVolume());

    buffer = new byte[recBufSize];



(3)开始接收,并进行实时播放

@Override

public void run()

    if (multicastSocket == null)

        return;

    //从文件流读数据

    audioTrk.play();

    // 包长

    while (true)

        try

            // 数据报

            DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);

            // 接收数据,同样会进入阻塞状态

            multicastSocket.receive(datagramPacket);

          audioTrk.write(datagramPacket.getData(), 0, datagramPacket.getLength());

        catch (IOException e)

            // TODO Auto-generated catch block

            e.printStackTrace();

       

   



(三)开始测试

MultiSendThread multiSendThread;

MultiReceiverThread multiReceiverThread;

@OnClick(R.id.btnSend, R.id.btnReceive)

public void onViewClicked(View view)

    switch (view.getId())

        case R.id.btnSend:

            if (multiSendThread == null)

                multiSendThread = new MultiSendThread();

           

            new Thread(multiSendThread).start();

            break;

        case R.id.btnReceive:

            if (multiReceiverThread == null)

                multiReceiverThread = new MultiReceiverThread();

           

            new Thread(multiReceiverThread).start();

            break;

   

以上是关于(四)Android基于UDP的多客户端语音通信的主要内容,如果未能解决你的问题,请参考以下文章

大数据必学Java基础(八十二):基于UDP的网络编程

Android 基于UDP的Socket通信

android UDP通信

android自带的互联网电话(SIP协议账户)怎么设置使用?

基于udp的scoket通信

udp通信