Android P2P语音通话实现(思路探讨)

最近在在研究语音通话的实现,现在把我的实现思路记录在这里。不过,由于初次接触语音通话,所以这是一个简单的思路,也是经过google以及baidu之后的一个学习总结。

  我认为一个语音通话系统至少有四个模块。分别是PCM(Pulse Code Modulation,即 脉码编码调制)语音采集,编解码,网络传输以及语音播放。如果算上UI交互的话,就是五个模块了。

  整体流程大概是:A打电话给B,A声音通过MIC被采集成PCM原始数据,然后经过编码压缩,再通过网络(建立P2P连接)将编码后的数据传输出去;B端通过网络收到数据后进行解码处理,然后调用播放模块,进行播放数据。

  一、语音采集模块

  Android平台上的实现是通过AudioRecord接口来实现PCM数据的采集,这一步比较容易的。但需要注意的是AudioRecord接口的使用方法。构造AudioRecord 实例需要参数

public AudioRecord (int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
audioSourcethe recording source. See MediaRecorder.AudioSource for recording source definitions.
sampleRateInHzthe sample rate expressed in Hertz. 44100Hz is currently the only rate that is guaranteed to work on all devices, but other rates such as 22050, 16000, and 11025 may work on some devices.
channelConfigdescribes the configuration of the audio channels. See CHANNEL_IN_MONO and CHANNEL_IN_STEREOCHANNEL_IN_MONOis guaranteed to work on all devices.
audioFormatthe format in which the audio data is represented. See ENCODING_PCM_16BIT and ENCODING_PCM_8BIT
bufferSizeInBytesthe total size (in bytes) of the buffer where audio data is written to during the recording. New audio data can be read from this buffer in smaller chunks than this size. See getMinBufferSize(int, int, int) to determine the minimum required buffer size for the successful creation of an AudioRecord instance. Using values smaller than getMinBufferSize() will result in an initialization failure.

 

  1. audioSource:这里可以是MediaRecorder.AudioSource.MIC
  2. sampleRateInHz:录制频率,可以为8000hz或11025hz等,不同的硬件设备这个值不同
  3. channelConfig:录制通道,可以为AudioFormat.CHANNEL_IN_MONO and AudioFormat.CHANNEL_IN_STEREO. AudioFormat.CHANNEL_IN_MONO
  4. audioFormat:录制编码格式,可以为AudioFormat.ENCODING_16BIT和8BIT,其中16BIT的仿真性比8BIT好,但是需要消耗更多的电量和存储空间
  5. bufferSizeInBytes:录制缓冲大小:可以通过getMinBufferSize()方法来获取

调用AudioRecord的 read(byte[], int, int)read(short[], int, int) or read(ByteBuffer, int)方法就可以采集PCM语音数据了。

  二、语音播放

  当语音数据采集好了之后,接着可以实现语音播放模块。Android上实现PCM数据的播放也很简单,直接使用AudioTrack这个接口就行了。同样需要注意该接口的使用方法。

  AudioTrack的构造方式跟AudioRecord是对应的

public AudioTrack (int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)
streamTypethe type of the audio stream. See STREAM_VOICE_CALLSTREAM_SYSTEMSTREAM_RINGSTREAM_MUSICSTREAM_ALARM, and STREAM_NOTIFICATION.
sampleRateInHzthe sample rate expressed in Hertz.
channelConfigdescribes the configuration of the audio channels. See CHANNEL_OUT_MONO and CHANNEL_OUT_STEREO
audioFormatthe format in which the audio data is represented. See ENCODING_PCM_16BIT and ENCODING_PCM_8BIT
bufferSizeInBytesthe total size (in bytes) of the buffer where audio data is read from for playback. If using the AudioTrack in streaming mode, you can write data into this buffer in smaller chunks than this size. If using the AudioTrack in static mode, this is the maximum size of the sound that will be played for this instance. See getMinBufferSize(int, int, int) to determine the minimum required buffer size for the successful creation of an AudioTrack instance in streaming mode. Using values smaller than getMinBufferSize() will result in an initialization failure.
modestreaming or static buffer. See MODE_STATIC and MODE_STREAM

以上两个模块的实现是比较好实现的。当这两个模块实现好了,就可以实现网络上许多例子说明AudioRecord与AudioTrack用法时的“边录边播”的效果。当然这不是我的目标,只是我们可以这样测试自己的采集的数据是否正确。

  其实这个边录边播的效果如果使用扩音器的话回音是很严重的,而且噪音也很严重的,这也是一个问题!因此要进行下一步,编解码!

  三、语音编解码

  采集到的PCM数据是原始的语音数据,如果我们直接进行网络传输,那是不可取的。因此,要进行打包编码。

  编码我们需要第三方的库,目前我使用的库是speex(http://www.speex.org)。我看到许多SIP语音电话都使用到了这个库进行编解码。当然也有对这个库评价不好的说法,但我觉得作为学习还是可取的,因为speex使用起来很方便。

  speex是一个c库(当然也有java版本的,http://code.google.com/p/speexdroid/,但我还是建议使用c库,因为java版本的speex效率可能不是很高),因此我们需要用到jni。如果没有使用过jni的话,这也是一个学习的机会。可以参考sipdroid http://code.google.com/p/sipdroid/ 如果还是觉得麻烦的话可以参考这个开源项目 http://code.google.com/p/android-recorder/

  不过,我使用speex的时候,噪音是降低了,但使用扩音器的时候,还是有很大的回音,但是效果已经好很多了。从speex的官网上可以知道,最新的speex版本添加了回音以及降噪的处理,但我把回音以及降噪模块加进去的时候,没有明显的效果,所以这是我使用speex库时遇到的一个问题,目前还在研究中。知道原因的同学留个言学习一下哈。

  四、网络传输

  打包编码之后就是网络传输了。网络传输主要是使用RTP(实时传输协议)。目前我使用的库是jlibrtp库http://sourceforge.net/projects/jlibrtp/?source=directory,这是一个java版本的实现。不过,这个库有丢包的问题,以及会抛库内的一些异常。由于我没有找到更好的RTP传输的库,所以只好使用这个库了。喜欢研究的同学也可以研究一下Sipdroid的RTP实现,我也有在看,不过还没有研究透。有研究过的同学,可以留言,我们一起学习探讨一下哈。

  这个就是一个简单P2P语音通话的实现思路。不过此思路,还没有实现服务器端。所以这个思路实现只能在局域网内通话。要实现P2P通话还需要NAT打洞的技术,这也是一个难点。我觉得难点就是用来攻破的。

  对于代码:由于是公司项目,不大方便贴出,之后有时间整理一下,再贴吧。

  本文为原创博客,http://www.cnblogs.com/milospooner/archive/2012/07/13/2590950.html

转载于:https://www.cnblogs.com/MMLoveMeMM/articles/3597651.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android实现点对点语音通话可以通过以下步骤实现: 1. 采集PCM语音数据:可以使用Android的AudioRecord类的read方法来采集PCM语音数据。该方法可以将采集到的音频数据存储在一个字节数组或者ByteBuffer中。\[1\] 2. 使用Speex库进行音频编解码:Speex是一个开源的音频编解码库,可以将采集到的PCM语音数据进行压缩和解压缩。你可以使用Speex的C库,通过JNI调用来实现音频编解码。\[2\] 3. 建立网络连接:你需要建立一个点对点的网络连接,可以使用Socket或者其他网络通信方式来实现。你可以参考一些开源项目,如Sipdroid或Android Recorder,来了解如何建立网络连接。\[2\] 4. 实现音频传输:一旦建立了网络连接,你可以将编码后的音频数据通过网络传输给对方。你可以使用Socket或者其他网络通信方式来发送和接收音频数据。 5. 解码和播放音频:接收方收到音频数据后,需要进行解码和播放。你可以使用Speex库进行解码,然后使用Android的AudioTrack类来播放解码后的音频数据。 通过以上步骤,你可以实现Android的点对点语音通话功能。请注意,这只是一个简单的实现示例,实际的实现可能需要更多的细节和处理。 #### 引用[.reference_title] - *1* *2* *3* [Android P2P语音通话实现思路探讨)](https://blog.csdn.net/jingwen3699/article/details/7951492)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值