您的位置:首页 > 移动开发 > Android开发

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.com

QQ群: 581235049(建议使用QQ群,邮箱使用较少,可能看的不及时)

本群旨在为使用我的github项目的人提供方便,如果遇到问题欢迎在群里提问。一个人的能力也有限,希望一起学习一起进步。

关注我的github,了解我的最新项目。关注我的博客,阅读我的最新文章。

欢迎加入QQ交流群



支持开源

乐于赞赏,感谢朋友们的支持和鼓励,让我们一起努力做一些好东西!

可以使用「微信」「支付宝」客户端赞赏:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息