1. 程式人生 > >RxAudio一款基於Rxjava實現的android音訊裝置通訊庫

RxAudio一款基於Rxjava實現的android音訊裝置通訊庫

RxAudio簡介

基於Rxjava實現的android音訊庫,主要用於手機和音訊裝置之間通訊,支援錄音、傳送、供電、傳送失敗自動重試(可以指定重試次數),設定接收超時、自定義編解碼,自定義配置引數等功能,使用本庫只需要關注與業務相關的自定義編解碼。

專案地址

用法介紹

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上發表部落格,敬請期待!!

聯絡方式

郵箱地址: [email protected]
QQ群: 581235049(建議使用QQ群,郵箱使用較少,可能看的不及時)
本群旨在為使用我的github專案的人提供方便,如果遇到問題歡迎在群裡提問。一個人的能力也有限,希望一起學習一起進步。
關注我的github,瞭解我的最新專案。關注我的部落格,閱讀我的最新文章。

歡迎加入QQ交流群

支援開源

樂於讚賞,感謝朋友們的支援和鼓勵,讓我們一起努力做一些好東西!
可以使用「微信」「支付寶」客戶端讚賞:
支付