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交流群
支援開源
樂於讚賞,感謝朋友們的支援和鼓勵,讓我們一起努力做一些好東西!
可以使用「微信」「支付寶」客戶端讚賞: