美文网首页android开发android技术Android进阶之旅
RxAudio一款基于Rxjava实现的android音频设备通

RxAudio一款基于Rxjava实现的android音频设备通

作者: zhou_you | 来源:发表于2017-06-10 14:15 被阅读459次

    github源码地址:https://github.com/zhou-you/RxAudio

    RxAudio

    基于Rxjava实现的android音频库,主要用于手机和音频设备之间通信,支持录音、发送、供电、发送失败自动重试(可以指定重试次数),设置接收超时、自定义编解码,自定义配置参数等功能,使用本库只需要关注与业务相关的自定义编解码。

    版本说明

    当前版本

    • V1.0.2 增加了耳机孔插入监听

    历史版本

    • V1.0.1 初始版本

    用法介绍

    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
        public 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交流群

    相关文章

      网友评论

        本文标题:RxAudio一款基于Rxjava实现的android音频设备通

        本文链接:https://www.haomeiwen.com/subject/udoqqxtx.html