RxAudio一款基于Rxjava实现的android音频设备通信库
2017-04-08 11:42
639 查看
RxAudio简介
基于Rxjava实现的android音频库,主要用于手机和音频设备之间通信,支持录音、发送、供电、发送失败自动重试(可以指定重试次数),设置接收超时、自定义编解码,自定义配置参数等功能,使用本库只需要关注与业务相关的自定义编解码。项目地址
https://github.com/zhou-you/RxAudio用法介绍
build.gradle设置
dependencies { compile 'com.zhouyou:rxaudio:1.0.2' }
全局初始化
全局初始化,在Application的onCreate()放在中初始化,或者是在你使用音频前进行初始化。RxAudio.init(new RxAudio.AudioConfig() .isLog(true)//是否输出日志 .receiveTimeOut(2000)//发送数据接收超时时间单位:ms .retryDelay(200)//间隔xxx ms重试 .retryCount(2)//设置重试次数,默认重试1次 .recorderConnectListener(connectListener)//录音启动监听 .audioEncoder(new CustomEncoderData())//设置编码实现,需要自己定义与业务相关的实现 .audioDecoder(new CustomDecoderData()));//设置解码实现,需要自己定义与业务相关的实现
注:
1.参数也可以不设置,但是audioEncoder()和audioDecoder()是必须设置的,不设置就不能编解码,也就无意义,也可以不使用全局设置,用Rxaudio的setAbstractDecoder和setAudioEncoder方法里设置编解码
2.每个业务都不一样需要自定义编解码实现,耳机孔设备就采用库里已经提供好的new EncoderData()和new FSKDecoderData()
设备识别
在需要监听设备插入的地方注册监听,如果是Activity就在onCreate(Bundle savedInstanceState) 中注册。//注册音频识别广播 HeadsetPlugReceiver mHeadsetPlugReceiver = HeadsetPlugReceiver.getInstance(this); mHeadsetPlugReceiver.registerHeadSetReceiver();//注册广播 mHeadsetPlugReceiver.setHeadsetJackStateLisentener(new HeadsetPlugReceiver.HeadsetJackStateLisentener() { @Override public void haveDevice() { //识别到设备插入 } @Override public void haveNoDevice() { //设备拔出 } });
在不使用的时候要取消注册,如果是Activity就在onDestroy() 中取消注册。
mHeadsetPlugReceiver.unregisterHeadSetReceiver();
注:
1.设备识别插入耳机孔设备录音功能调用RxAudio相关功能,设备拔出时停掉录音。
2.如果想要能够具备识别功能,是普通耳机(听歌)还是你的耳机孔设备,最好是插入后给3s通信,收到消息就是耳机孔设备,否则超时了就是普通耳机
接收数据
创建RxAudio对象,设置接收回调监听private RxAudio rxAudio; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); rxAudio = RxAudio.getInstance(); rxAudio.setReceiveCallBack(new IDecoderCallBack() { @Override public void callResult(DecoderResult result) { if (result.code == DecoderResult.DECODE_OK) { //解码成功 } } }); }
注:
1.接收的数据都在DecoderResult中,从DecoderResult里拿设备发送的数据。
2.setReceiveCallBack接收监听是单列模式,只能设置一次,设置第二次时会把第一次的监听覆盖掉,多个地方都需要接收的话,可以采用接收后发送event事件自己处理
3.在设置setReceiveCallBack()监听的页面,退出时需要调用mHeadsetPlugReceiver.resume()恢复设备识别监听。
发送数据
发送数据给设备,不需要监听是否接收到数据rxAudio.send(byte[] bytes);
发送数据给设备,设置监听回调
rxAudio.send(bytes, new ICallBack() { @Override public void onSuccess(byte[] recData) { } @Override public void onFailure(Throwable throwable) { } });
注:发送回调监听,在setReceiveCallBack全局监听中也可以收到消息。
音频退出
在应用退出时调用rxAudio.exitAudio();
编解码使用方式
全局设置RxAudio.init(new RxAudio.AudioConfig() .audioEncoder(new EncoderData())//设置编码实现 .audioDecoder(new FSKDecoderData()));//设置解码实现;
通过RxAudio对象设置
RxAudio rxAudio = RxAudio.getInstance(); rxAudio.setAbstractDecoder(new FSKDecoderData());//设置解码 rxAudio.setAudioEncoder(new EncoderData());//设置解码
自定义解码
本库中默认采用FSKDecoderData解码,如果需要自定义实现解码需要继承AbstractDecoder类public class CustomDecoder extends AbstractDecoder { @Override public void start() { //1.解码类启动,如果解码耗时需要开线程,那么在此处调用线程就行了,不需要你自己手动启动,框架会帮你启动 //2.如果启动不需要操作则可以空实现 } @Override public void stop() { //解码类停止,如果有线程,在这里停止,不需要外面手动停止,录音停止时会帮你停止你的线程操作 //2.如果关闭没有其它操作,可以空实现 } @Override publ f382 ic boolean isRuning() {//自己实现解码是否在运行,如果自己开了线程,可以返回当前线程的转态,外面调用isRuning() return false; } @Override public void startDecoder(int sampleRate) { //真正的开始解码了,sampleRate是录音时你设置的采样率,如果不使用不用关心 //解码前的初始化操作 } @Override public void decoderData(short[] audio_data, int bufferReadResult) throws Exception { //decoderData已经是在线程中执行了,不需要再开线程 //audio_data录音的原始信号,用于解码,每次从系统读取的buffer //bufferReadResult读取的实际长度,例如你开了1024的缓冲区,实际系统就给你了480。 } @Override public void finishDecoder() { //解码结束 } @Override public void recoderState(boolean isPause) { //是否处于暂停录音 } }
使用方式参考上面编解码使用方式,例如:
RxAudio rxAudio = RxAudio.getInstance(); rxAudio.setAbstractDecoder(new CustomDecoder());//设置解码
自定义编码
本库中默认采用EncoderData编码后发送给设备,如果需要自定义实现解码需要实现IAudioEncoder接口public class CustomEncoder implements RxAudioPlayer.IAudioEncoder{ @Override public void startEncoder(int sampleRate) { //开始编码,sampleRate编码的采样率 } @Override public byte[] encoderData(byte[] bytes) { //在这里封装你给设备发送的所有数据,按照协议发送 //把要发给设备的字节bytes重新组装,编码成设备可以识别的正玄波的byte[] return new byte[0]; } @Override public void finishEncoder() { //结束编码 } }
使用方式参考上面编解码使用方式,例如:
RxAudio rxAudio = RxAudio.getInstance(); rxAudio.setAudioEncoder(new CustomEncoder());//设置编码
其它场景使用
以上所有实现都是主要围绕RxAudio来说明,RxAudio是集合了供电、录音、发送三大模块实现,每个模块也可独立使用。供电PowerSupply类
PowerSupply mSuply = new PowerSupply.Builder() .sampleRate(44100) .channelConfig(AudioFormat.CHANNEL_CONFIGURATION_MONO) .audioFormat(AudioFormat.ENCODING_PCM_16BIT) .channel(PowerSupply.Channel.RIGHT) .powerRate(21500)//设置输出正玄波频率 .build() mSuply.start() mSuply.stop()
录音AudioRecorder类
AudioRecorder recorder = new AudioRecorder.Builder() .reate(8000) .audioEncoding(AudioFormat.ENCODING_PCM_16BIT) .audioSource(MediaRecorder.AudioSource.MIC) .channelConfiguration(AudioFormat.CHANNEL_IN_MONO) .build(); recorder.start() recorder.stop()
发送用RxAudioPlayer类
RxAudioPlayer audioPlayer = new RxAudioPlayer.Builder() .streamType(AudioManager.STREAM_MUSIC) .rate(8000) .channelConfig(AudioFormat.CHANNEL_OUT_MONO) .audioFormat(AudioFormat.ENCODING_PCM_16BIT) .channel(Channel.LEFT)//左声道通信 .build(); audioPlayer.rxSend((byte) 0x5A)//发送单个数据 audioPlayer.rxSend(new byte[])//发送数组 audioPlayer.rxSend((byte) 0x5A, 2, 100)//发送单个数据,失败重试2次,每次间隔100ms audioPlayer.rxSend(new byte[], 2, 100)//发送数组,失败重试2次,每次间隔100ms
RxAudio讲解
RxAudio是本库的一个音频入口类具有供电、接收、发送三大能。使用方式
RxAudio rxAudio = RxAudio.getInstance();功能介绍
初始化配置
RxAudio.init(AudioConfig config);
开启录音
rxAudio.startRecord();
关闭录音
rxAudio.stopRecord();
开启供电
rxAudio.startPower();
关闭供电
rxAudio.stopPower();
设置编码
rxAudio.setAudioEncoder(RxAudioPlayer.IAudioEncoder audioEncoder);
设置解码
rxAudio.setAbstractDecoder(AbstractDecoder abstractDecoder);
设置监听回调
rxAudio.setReceiveCallBack(IDecoderCallBack callBack);
设置供电频率
rxAudio.setPowerRate(int sin_rate);//默认21KHZ,不用设置
发送命令给设备,不需要响应
rxAudio.send(final byte[] datas) ;
发送命令给设备,并且等待设备回应接收数据
rxAudio.send(final byte[] datas, final ICallBack callBack)
取消发送
rxAudio.cancleSend() ;
退出音频
rxAudio.exitAudio();
自定义供电配置
PowerSupply.Builder mPowerBuilder = new PowerSupply.Builder().sampleRate(48000) .channelConfig(AudioFormat.CHANNEL_OUT_MONO) .audioFormat(AudioFormat.ENCODING_PCM_16BIT) .channel(Channel.RIGHT) .powerRate(20050);//设置输出21KHZ正玄波频率 VIVO手机不能设置成21050否则驱动不了电池 RxAudio.init(new RxAudio.AudioConfig().powerBuilder(mPowerBuilder));
自定义录音配置
AudioRecorder.Builder mRecorderBuilder = new AudioRecorder.Builder().reate(44100) .audioEncoding(AudioFormat.ENCODING_PCM_16BIT) .audioSource(MediaRecorder.AudioSource.MIC) .channelConfiguration(AudioFormat.CHANNEL_CONFIGURATION_MONO); RxAudio.init(new RxAudio.AudioConfig().recordBuilder(mRecorderBuilder));
自定义发送配置
RxAudioPlayer.Builder mAudioPlayerBuilder = new RxAudioPlayer.Builder().streamType(AudioManager.STREAM_MUSIC) .rate(8000) .channelConfig(AudioFormat.CHANNEL_OUT_MONO) .audioFormat(AudioFormat.ENCODING_PCM_16BIT) .channel(Channel.LEFT)//左声道通信 .mode(AudioTrack.MODE_STATIC); RxAudio.init(new RxAudio.AudioConfig().trackBuilder(mAudioPlayerBuilder));
RxAudio默认配置参数介绍:
//默认录音配置 mRecorderBuilder = new AudioRecorder.Builder().reate(44100)//设置采样率 .audioEncoding(AudioFormat.ENCODING_PCM_16BIT) .audioSource(MediaRecorder.AudioSource.MIC) .channelConfiguration(AudioFormat.CHANNEL_CONFIGURATION_MONO); //默认供电配置 mPowerBuilder = new PowerSupply.Builder().sampleRate(48000)//设置采样率 .channelConfig(AudioFormat.CHANNEL_OUT_MONO)//设置单声道 .audioFormat(AudioFormat.ENCODING_PCM_16BIT) .channel(Channel.RIGHT)//左声道供电 .powerRate(20050);//设置输出21KHZ正玄波频率 VIVO手机不能设置成21050否则驱动不了电池 //默认发送配置 mAudioPlayerBuilder = new RxAudioPlayer.Builder().streamType(AudioManager.STREAM_MUSIC)//设置类型 .rate(8000)//设置采样率 .channelConfig(AudioFormat.CHANNEL_OUT_MONO)//设置单声道 .audioFormat(AudioFormat.ENCODING_PCM_16BIT) .channel(Channel.LEFT)//左声道通信 .mode(AudioTrack.MODE_STATIC);
注:这些参数不需要关系,RxAudio默认已经设置了,如果需要自定义可以设置Builder.
Demo效果预览
项目应用效果预览
重点说明
本工程的Demo编解码都是空实现,因为编解码在其它app上已经商用,涉及到具体的业务通信安全,不对外开放,望理解!!!采用FSK,傅里叶FFT解码,能够兼容市场上主流手机80%以上,另外告知大家曼彻斯特的解码是行不通的(只有ios可以),勿走弯路,FFT才是正道(andoid和ios同时兼容),FFT同样也需要做兼容处理。供电说明,供电并不是真正的供电,音频设备如果想真正的供电最少需要在2.5V以上才能够稳定,ios可以输出3.5V的电压,anroid输出最好的也才在1.9V左右,很多手机只有1v左右,根本达不到供电的标注。很多希望供电是因为,如果耳机孔输出能够供电,那么耳机孔设备就不用加电池会减少很多成本。但是实际测试在android上不行的,本库中供电是当耳机孔插入时开始发送人耳听不到的21KHZ正玄波用最大振幅输出,以此来打开耳机孔设备电池的使能,耳机孔开始工作,拔出时断开使能不工作,增加耳机孔电池使用寿命。
其它
如果想深入了解基于FFT的解码以及兼容、注意事项、供电、发送等原理,后期会在CSDN上发表博客,敬请期待!!联系方式
邮箱地址: 478319399@qq.comQQ群: 581235049(建议使用QQ群,邮箱使用较少,可能看的不及时)
本群旨在为使用我的github项目的人提供方便,如果遇到问题欢迎在群里提问。一个人的能力也有限,希望一起学习一起进步。
关注我的github,了解我的最新项目。关注我的博客,阅读我的最新文章。
欢迎加入QQ交流群
支持开源
乐于赞赏,感谢朋友们的支持和鼓励,让我们一起努力做一些好东西!可以使用「微信」「支付宝」客户端赞赏:
相关文章推荐
- 基于RxJava、RxAndroid的EventBus实现
- Android消息传递之基于RxJava实现一个EventBus - RxBus
- [Android]基于RxJava、RxAndroid的EventBus实现
- 基于AOA协议实现Android设备的USB通信
- 基于AOA协议实现Android设备的USB通信
- Android基于wifi的无线HID设备实现
- 基于RxJava、RxAndroid的EventBus实现
- 基于android多媒体框架实现播放APE音频的实现
- [Android]基于RxJava、RxAndroid的EventBus实现
- 基于智能移动设备的IP电话软件的设计与实现
- Android HAL实现的三种方式(3) - 基于Manager的HAL设计
- 基于SOA的设备智能维护系统架构设计及实现
- 实现基于Android的英文电子词典
- 基于Android源码开发的来电接通振动功能实现
- Android HAL实现的三种方式(1) - 基于JNI的简单HAL设计 推荐
- Android多媒体学习十:利用AudioRecord类实现自己的音频录制程序
- 基于DirectShow获取音频视频输入设备列表
- Android HAL实现的三种方式(3) - 基于Manager的HAL设计
- Android多媒体学习八:调用Android自带的音频录制程序,实现录制
- 实现基于Android的英文电子词典