日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android录制mp3音频,Android MP3录制,波形显示,音频权限兼容与播放

發布時間:2024/3/26 Android 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android录制mp3音频,Android MP3录制,波形显示,音频权限兼容与播放 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我又來掀桌子了(ノ?益?)ノ彡┻━┻,這次是MP3錄制和顯示聲音波形的一個故事。

先看看效果┑( ̄Д  ̄)┍

2

1

MP3錄制的邏輯過程就忽略了(真的不是因為懶(。??)ノ),這里用的是開源的AndroidMP3Recorder,不過大神太忙了,表示停止維護了,錄制效果還不錯,站在巨人的肩膀上(cao xi),增加了音頻錄制的權限判斷和數據提取的邏輯。關于錄制的請戳這里傳送。

增加權限提示

在音頻相關開發的時候,經常涉及到權限的問題,而6.0以下的時候是沒有接口判斷的,如何敏感的權限,為啥子沒有呢(ノ?益?)ノ彡┻━┻,所以經常會和camera,拍攝視頻一樣,通過try這個crash來判斷吧。

如下在startRecording的時候把crash捕獲了(讓你崩潰(ノ?益?)ノ彡┻━┻),之后通過判斷int readSize = mAudioRecord.read(mPCMBuffer, 0, mBufferSize);讀出來的是,ERROR_INVALID_OPERATION ,ERROR_BAD_VALUE,的話,那么就通知你的頁面:這貨不給權限還想錄音,逗我嗎···然后退出錄制。

···

try {

mAudioRecord.startRecording();

} catch (Exception ex) {

ex.printStackTrace();

}

···

while (mIsRecording) {

int readSize = mAudioRecord.read(mPCMBuffer, 0, mBufferSize);

if (readSize == AudioRecord.ERROR_INVALID_OPERATION ||

readSize == AudioRecord.ERROR_BAD_VALUE) {

if (errorHandler != null && !sendError) {

sendError = true;

errorHandler.sendEmptyMessage(ERROR_TYPE);

mIsRecording = false;

isError = true;

}

} else {

if (readSize > 0) {

mEncodeThread.addTask(mPCMBuffer, readSize);

calculateRealVolume(mPCMBuffer, readSize);

sendData(mPCMBuffer, readSize);

} else {

if (errorHandler != null && !sendError) {

sendError = true;

errorHandler.sendEmptyMessage(ERROR_TYPE);

mIsRecording = false;

isError = true;

}

}

}

}

再采樣(這個詞看起來很高端的樣子)

其實就是音頻數據進行縮減,因為手機每次讀上來的音頻數據是比較大的,這和我們配置的錄制參數也有關系,這里使用的是44100HZ的參數,那么我們直接降頻就好了。(這波裝的可以啊~)

如下面所看到的,其實就一個for循環,首先把音頻數據的長度除了300(哈哈,一下子少了好多),之后每300個里面取出最大和最小值(音頻數據是正負數的),目前我們用的是最大值,這樣把每300個里面的最大值都存起來,就有了一個降頻后的音頻數據列表了。

private void sendData(short[] shorts, int readSize) {

if (dataList != null) {

int length = readSize / 300;

short resultMax = 0, resultMin = 0;

for (short i = 0, k = 0; i < length; i++, k += 300) {

for (short j = k, max = 0, min = 1000; j < k + 300; j++) {

if (shorts[j] > max) {

max = shorts[j];

resultMax = max;

} else if (shorts[j] < min) {

min = shorts[j];

resultMin = min;

}

}

if (dataList.size() > maxSize) {

dataList.remove(0);

}

dataList.add(resultMax);

}

}

}

根據音頻數據繪制波形

1、首先,你得有一個女····呸呸呸,你要有一個View,自定義一個View用來繪制,繪制的邏輯有這么幾個:

獲取View的大小,取的寬度,高度,還有基線。對基♂線。

生成兩張bitmap作為雙緩沖繪制,避免閃爍。(別問我為什么,你用一張試試)

對音頻數據塊的數據大小進行判斷,取的縮放系數,做縮放波形處理。

根據控件寬度,間隔系數,從基線開始繪制波形到bitmap,將這個bitmap繪制到顯示的bitmap2。

通知界面顯示將這個bitmap2 繪制到界面上。

是不是很簡單呢?是啊~確實很簡單( ̄o ̄) .那到這里就結束88咯。

咦,下面還有啊 (ˉ▽ ̄~) 切~~

這里首先通過onVisibilityChanged,在里面注冊了一個addOnPreDrawListener,在addOnPreDrawListener里面獲取到了view的大小、基線,生成兩張需要的bitmap。

@Override

protected void onVisibilityChanged(@NonNull View changedView, int visibility) {

super.onVisibilityChanged(changedView, visibility);

if (visibility == VISIBLE && mBackgroundBitmap == null) {

ViewTreeObserver vto = getViewTreeObserver();

vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

@Override

public boolean onPreDraw() {

if (getWidth() > 0 && getHeight() > 0) {

mWidthSpecSize = getWidth();

mHeightSpecSize = getHeight();

mBaseLine = mHeightSpecSize / 2;

mBackgroundBitmap = Bitmap.createBitmap(mWidthSpecSize, mHeightSpecSize, Bitmap.Config.ARGB_8888);

mBitmap = Bitmap.createBitmap(mWidthSpecSize, mHeightSpecSize, Bitmap.Config.ARGB_8888);

mBackCanVans.setBitmap(mBackgroundBitmap);

mCanvas.setBitmap(mBitmap);

ViewTreeObserver vto = getViewTreeObserver();

vto.removeOnPreDrawListener(this);

}

return true;

}

});

}

}

音頻數據是一塊一塊的list過來的,所以獲取每個塊中最大值,與當前view對比,就知道這一塊數據需要縮放的系數啦。

/**

* 根據當前塊數據來判斷縮放音頻顯示的比例

*

* @param list 音頻數據

*/

private void resolveToWaveData(ArrayList list) {

short allMax = 0;

for (Short sh : list) {

if (sh > allMax) {

allMax = sh;

}

}

int curScale = allMax / mBaseLine;

if (curScale > mScale) {

mScale = ((curScale == 0) ? 1 : curScale);

}

}

開始繪制到bitmap上啦~

首先把bitmap洗干凈drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);,然后繪制基線,接著就是for循環繪制音頻線了。

繪制以基線為軸,每個音頻數據除以縮放系數(需要考慮乘的情況?反正我bu care~),然后繪制上下的豎線,之后把這個bitmap繪制到要完整顯示的mBackgroundBitmap,最后通知界面更新(發到UI線程),然后界面把要顯示的mBackgroundBitmap貼出來。

if (mBackCanVans != null) {

//洗白白

mBackCanVans.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

mBackCanVans.drawLine(0, mBaseLine, mWidthSpecSize, mBaseLine, mPaint);

int drawBufsize = dataList.size();

//判斷大小,是否改變顯示的比例

for (int i = 0, j = 0; i < drawBufsize; i++, j += mOffset) {

Short sh = dataList.get(i);

short max = (short) (mBaseLine - sh / mScale);

short min;

if (mWaveCount == 2) {

min = (short) (sh / mScale + mBaseLine);

} else {

min = (short) (mBaseLine);

}

mBackCanVans.drawLine(j, mBaseLine, j, max, mPaint);

mBackCanVans.drawLine(j, min, j, mBaseLine, mPaint);

}

synchronized (mLock) {

mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

mCanvas.drawBitmap(mBackgroundBitmap, 0, 0, mPaint);

}

Message msg = new Message();

msg.what = 0;

handler.sendMessage(msg);

}

···

@Override

protected void onDraw(Canvas c) {

super.onDraw(c);

if (mIsDraw && mBitmap != null) {

synchronized (mLock) {

c.drawBitmap(mBitmap, 0, 0, mViewPaint);

}

}

}

音頻播放AudioPlayer

這個比較簡單,就不廢話了,真的不費話了。就是實現了一個內部定時器,不斷的獲取當前位置,誰讓MediaPlayer本來就支持播放網絡和本地,接口又豐富呢,有興趣demo見。

最后~歡迎來個人的Github

一定要來哈

總結

以上是生活随笔為你收集整理的android录制mp3音频,Android MP3录制,波形显示,音频权限兼容与播放的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 男人天堂2021| 亚洲精品午夜国产va久久成人 | 国产一区二区视频网站 | 永久免费无码av网站在线观看 | 久久精品一区二区国产 | 中文字幕第一页在线播放 | 成人看片黄a免费看视频 | 色呦呦一区二区三区 | 太久av| 免费看裸体网站视频 | 欧美激情免费在线 | 欧美日韩黄色片 | 久草资源在线观看 | 手机免费在线观看av | 日韩免费在线观看 | 国产免费一区二区三区四区五区 | 国产精品伦一区二区三区免费看 | 日本啪啪网站 | 亚洲视频精品在线观看 | 亚洲aa在线观看 | wwww日本60| 在线观看入口 | 久久66热这里只有精品 | 中文在线观看免费视频 | 国产三级免费观看 | 亚洲男人第一天堂 | 偷拍欧美亚洲 | 国产精品成人网站 | 亚洲精品久久久久久久久久 | 99这里都是精品 | 亚洲香蕉久久 | 欧美一区二区激情 | 制服丝袜先锋影音 | 一区二区在线看 | 国产亚洲区 | 伊人久久97 | 精品婷婷色一区二区三区蜜桃 | 午夜激情婷婷 | 麻豆国产在线 | 综合色88| 亚洲精品视频在线看 | 午夜精品久久久久久久99 | 韩日精品在线 | 日韩精品久久久久久久的张开腿让 | 18深夜在线观看免费视频 | 亲切的金子餐桌片段的金子 | 玖玖色资源| 污污污污污污www网站免费 | 精品一区二区三区四区五区 | 精品国产三级片在线观看 | 久久99精品久久只有精品 | 日韩欧美国产精品 | 欧美熟妇一区二区 | 天堂√8在线中文 | 操碰人人 | 女女互慰揉小黄文 | 俄罗斯黄色录像 | 人人妻人人爽人人澡人人精品 | 免费一级特黄 | 亚洲无码高清精品 | 天天综合天天 | 大奶子在线观看 | 久久草av | 精品国产乱码久久久久久1区2区 | 午夜宅男网 | 日韩欧美一级在线 | 亚洲久久一区二区 | 97黄色网 | 天天av天天操 | 国产夜色精品一区二区av | 蜜臀久久99精品久久久久宅男 | 少妇熟女高潮流白浆 | 在线观看a视频 | 国产精品作爱 | h片在线免费看 | 国产精品视频免费看 | 国产视频第一页 | 色窝窝综合色窝窝久久 | 91精品在线免费观看 | 超碰天天操 | 国产91色| 国产精品毛片久久久 | 欧美 在线| 亚洲欧美综合精品久久成人 | 色999五月色 | 亚洲草逼| 久久久久久久极品 | 羞羞动漫在线观看 | 国产丝袜视频在线 | 欧美黄色a级 | 综合性色 | 麻豆成人在线视频 | 欧美性生活一区 | 99久| 黄色网址大全免费 | 成年人的天堂 | 真实的国产乱xxxx在线91 | 直接看的毛片 | 久久久无码一区二区三区 |