Android 錄音AudioRecord

AudioRecord是安卓多媒體框架中用于錄制音頻的工具。它支持錄制原始音頻數據,即PCM數據,PCM數據不能被播放器直接播放,需要編碼壓縮成常見音頻格式才能被播放器識別。通常生成PCM文件之后可將PCM文件轉成WAV文件一般的播放器便可直接播放了。

接下來處理AudioRecord操作。

1.初始化AudioRecord

先了解幾個概念:

audioSource:音頻來源
sampleRateInHz:采樣率,以赫茲為單位。目前,只有44100Hz是保證在所有設備上都可以使用的速率(最適合人耳的),但是其他速率(例如22050、16000和11025)可能在某些設備上可以使用;如果用于語音識別的話根據不同廠商需要采用不同的采樣率
channelConfig:音頻通道的配置
audioFormat:音頻數據的格式
bufferSizeInBytes:在錄制期間寫入音頻數據的緩沖區的總大小(以字節為單位)

初始化操作:

int mBufferSize = AudioRecord.getMinBufferSize(16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT)*2;
AudioRecord mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,16000,AudioFormat.CHANNEL_IN_MONO,//雙聲道AudioFormat.ENCODING_PCM_16BIT,mBufferSize);

?2.開始錄音

 /*** 錄制pcm文件* @param pcmFilePath pcm文件路徑*/public void startRecord(String pcmFilePath) {if (isRecord) {return;}this.mPcmFilePath=pcmFilePath;isRecord = true;RecordThread recordThread = new RecordThread();mExecutorService.execute(recordThread);}class RecordThread implements Runnable {@Overridepublic void run() {mAudioRecord.startRecording();FileOutputStream fos = null;try {Log.i(TAG, "文件地址: " + mPcmFilePath);fos = new FileOutputStream(mPcmFilePath);byte[] bytes = new byte[mBufferSize];while (isRecord) {mAudioRecord.read(bytes, 0, bytes.length);fos.write(bytes, 0, bytes.length);fos.flush();}Log.i(TAG, "停止錄制");mAudioRecord.stop();fos.flush();} catch (IOException e) {e.printStackTrace();} finally {if (fos != null) {try {fos.close();} catch (IOException e) {e.printStackTrace();}}}}}

3.結束錄音

/*** 停止錄制*/public void stopRecord() {isRecord = false;}

4.將錄音生成的pcm文件轉成wav文件

/*** pcm文件轉wav文件* @param pcmFile pcm文件* @param wavFile wav文件*/public void pcm2Wav(File pcmFile, File wavFile) {if (!pcmFile.exists()){throw new RuntimeException(pcmFile.getAbsolutePath()+",there is no pcm file");}mExecutorService.execute(new PcmToWavThread(pcmFile,wavFile));}class PcmToWavThread implements Runnable {File pcmFile;File wavFile;public PcmToWavThread(File pcmFile, File wavFile) {this.pcmFile = pcmFile;this.wavFile = wavFile;}@Overridepublic void run() {if (!wavFile.exists()){try {wavFile.createNewFile();PcmToWavUtil util=new PcmToWavUtil(mSampleRate,mChannel,mFormat);util.pcmToWav(pcmFile.getAbsolutePath(),wavFile.getAbsolutePath());} catch (IOException e) {e.printStackTrace();}}}}

?pcm文成wav文件方法如下:

/*** pcm文件轉wav文件** @param inFilename 源文件路徑* @param outFilename 目標文件路徑*/public void pcmToWav(String inFilename, String outFilename) {FileInputStream in;FileOutputStream out;long totalAudioLen;//總錄音長度long totalDataLen;//總數據長度long longSampleRate = mSampleRate;int channels = mChannel == AudioFormat.CHANNEL_IN_MONO ? 1 : 2;long byteRate = 16 * mSampleRate * channels / 8;byte[] data = new byte[mBufferSize];try {in = new FileInputStream(inFilename);out = new FileOutputStream(outFilename);totalAudioLen = in.getChannel().size();totalDataLen = totalAudioLen + 36;writeWaveFileHeader(out, totalAudioLen, totalDataLen,longSampleRate, channels, byteRate);while (in.read(data) != -1) {out.write(data);out.flush();}Log.e(TAG, "pcmToWav: 停止處理");in.close();out.close();} catch (IOException e) {e.printStackTrace();}}/*** 加入wav文件頭*/private void writeWaveFileHeader(FileOutputStream out, long totalAudioLen,long totalDataLen, long longSampleRate, int channels, long byteRate)throws IOException {byte[] header = new byte[44];// RIFF/WAVE headerheader[0] = 'R';header[1] = 'I';header[2] = 'F';header[3] = 'F';header[4] = (byte) (totalDataLen & 0xff);header[5] = (byte) ((totalDataLen >> 8) & 0xff);header[6] = (byte) ((totalDataLen >> 16) & 0xff);header[7] = (byte) ((totalDataLen >> 24) & 0xff);//WAVEheader[8] = 'W';header[9] = 'A';header[10] = 'V';header[11] = 'E';// 'fmt ' chunkheader[12] = 'f';header[13] = 'm';header[14] = 't';header[15] = ' ';// 4 bytes: size of 'fmt ' chunkheader[16] = 16;header[17] = 0;header[18] = 0;header[19] = 0;// format = 1header[20] = 1;header[21] = 0;header[22] = (byte) channels;header[23] = 0;header[24] = (byte) (longSampleRate & 0xff);header[25] = (byte) ((longSampleRate >> 8) & 0xff);header[26] = (byte) ((longSampleRate >> 16) & 0xff);header[27] = (byte) ((longSampleRate >> 24) & 0xff);header[28] = (byte) (byteRate & 0xff);header[29] = (byte) ((byteRate >> 8) & 0xff);header[30] = (byte) ((byteRate >> 16) & 0xff);header[31] = (byte) ((byteRate >> 24) & 0xff);// block alignheader[32] = (byte) (2 * 16 / 8);header[33] = 0;// bits per sampleheader[34] = 16;header[35] = 0;//dataheader[36] = 'd';header[37] = 'a';header[38] = 't';header[39] = 'a';header[40] = (byte) (totalAudioLen & 0xff);header[41] = (byte) ((totalAudioLen >> 8) & 0xff);header[42] = (byte) ((totalAudioLen >> 16) & 0xff);header[43] = (byte) ((totalAudioLen >> 24) & 0xff);out.write(header, 0, 44);}

5.釋放資源

/*** 釋放資源*/public void release() {if (mAudioRecord != null) {mAudioRecord.release();}if (mExecutorService!=null){mExecutorService.shutdown();}}

至此錄音功能即可實現了,如果想要測試可以直接使用MediaPlayer方法進行錄音播放

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/17103.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/17103.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/17103.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

前端開發技巧 --判斷文本是否溢出

const isTextOverflower()>{if(element){return element.offsetWidth > element.scrollWidth}return false}實現javascript 判斷文本是否溢出

【除了知乎,大家都在逛什么?持續更新~~】

除了知乎,大家都在逛什么? 中文博客瑯琊榜 https://github.com/qianguyihao/blog-list 中文博客瑯琊榜,只收錄優質的中文獨立博客,全網最精品。已收錄博客數量:328 個博客站點。 這些博主才華橫溢,滿懷自由…

【2024最新】軟考資料大全(免費)

IT行業越來越卷,大家都在忙著搞證,你免費不搞一個? 不管有沒有用,有總比沒有好噻~ 【初級】,【中級】,【高級】 都有,而且全部免費,全部最新的!真題,論文都…

Java查看線上對象的變量值

背影 有時候線上有些配置類,想查看下配置修改是否生效,傳統的方法要通過打日志的方法,如果不想通過打日志的方法,有沒有好的方案能解決這個問題呢 解決方案 arthas 步驟 得到類加載器的hashcode sc -d com.example.MyService…

眼底項目經驗

眼底項目經驗 可解釋性不足問題眼底項目有多牛逼可解釋性不足解法數據、算力、算法都免費送不僅預測當下,還能預測未來和慢病管理整合,形成一個實時健康檢測生態 可解釋性不足問題 今天下午和騰訊眼底項目人員討論, 他們不準備做全身性的多疾種, 因為深…

LINUX環境基礎練習題(附帶答案)

🔥 交流討論:歡迎加入我們一起學習! 🔥 資源分享:耗時200小時精選的「軟件測試」資料包 🔥 教程推薦:火遍全網的《軟件測試》教程 📢歡迎點贊 👍 收藏 ?留言 &#x1…

【typescript - tsc 編譯后路徑問題/路徑別名問題】

這幾天在寫typescript,遇到個路徑依賴問題,編寫的.ts文件直接運行OK,但是編譯成.js后,運行提示 Error: Cannot find module xxx,📝記錄分析和解決過程 。 問題描述 原始文件,有index.ts 其會引…

小白不知道怎么投稿?記住這個好方法

作為一名單位信息宣傳員,我最初踏上這條道路時,滿心憧憬著通過文字傳遞我們單位的精彩瞬間,讓社會聽見我們的聲音。然而,理想與現實之間的距離,卻在一次次郵箱投稿的石沉大海中漸漸清晰。那時的我,像所有“小白”一樣,以為只要用心撰寫稿件,通過電子郵件發給各大媒體,就能收獲滿…

4 CSS的 變換、過渡與動畫

CSS3引入了變換、過渡和動畫特性,使得網頁可以呈現出豐富的視覺效果和交互體驗。通過這些新特性,開發者可以創建復雜的動畫效果,而不需要使用JavaScript。 4.1 變換(Transforms) 變換允許開發者對元素進行旋轉、縮放…

Python考試復習--day2

1.出租車計費 mile,waitmap(int,input().split(,)) if mile<3:money13wait*1 elif mile>3 and mile<15:money13(mile-3)*2.3wait*1 else:money1312*2.3(mile-15)*2.3*(10.5)wait*1 print({:.0f}.format(money)) 【知識點1】&#xff1a; map() 函數 【知識點1】&…

代碼隨想錄算法訓練營第五十一天|300.最長遞增子序列,674. 最長連續遞增序列,718. 最長重復子數組

300.最長遞增子序列 dp數組的含義為dp[i]表示字符串以第i位置為末尾的最長遞增子序列的長度。 for (int i 1; i < nums.size(); i) {for (int j 0; j < i; j) {if (nums[i] > nums[j]) dp[i] max(dp[i], dp[j] 1);}if (dp[i] > result) result dp[i]; // 取…

設計模式 20 中介者模式 Mediator Pattern

設計模式 20 中介者模式 Mediator Pattern 1.定義 中介者模式&#xff08;Mediator Pattern&#xff09;是一種行為型設計模式&#xff0c;它通過封裝對象之間的交互&#xff0c;促進對象之間的解耦合。中介者模式的核心思想是引入一個中介者對象&#xff0c;將系統中對象之間…

Vue中,點擊提交按鈕,路由多了個問號

問題 當點擊提交按鈕是路由多了問號&#xff1a; http://localhost:8100/#/ 變為 http://localhost:8100/?#/原因 路由中出現問號通常是由于某些路徑或參數處理不當造成的。在該情況下&#xff0c;是因為表單的默認行為導致的。提交表單時&#xff0c;如果沒有阻止表單的默…

React Router v6:路由管理的最新進展

React Router v6 是 React 應用程序路由管理的一個重大更新&#xff0c;它引入了許多改進和簡化&#xff0c;包括對嵌套路由的更友好處理&#xff0c;以及對鉤子函數的使用。 2500G計算機入門到高級架構師開發資料超級大禮包免費送&#xff01; 1. Routes 重構 在 v6 中&…

Kubernetes數據存儲

1. 數據存儲 容器的生命周期可能很短&#xff0c;會被頻繁地創建和銷毀。那么容器在銷毀時&#xff0c;保存在容器中的數據也會被清除。這種結果對用戶來說&#xff0c;在某些情況下是不樂意看到的。為了持久化保存容器的數據&#xff0c;kubernetes引入了Volume的概念。 Volu…

HTML-JavaWeb

目錄 1.標題排版 2.標題樣式 ?編輯 ?編輯 小結 3.超鏈接 4.正文排版 ?編輯?編輯?編輯5.正文布局 6.表格標簽 7.表單標簽 8.表單項標簽 1.標題排版 ● 圖片標簽 :< img> src:指定圖像的ur1(絕對路徑/相對路徑) width:圖像的寬度(像素/相對于父元素的百…

【AD21】文件的整理

當所有文件輸出完成后&#xff0c;需要對不同的文件去做一個整理&#xff0c;方便后續工作的交接。 在項目工程文件夾下新建名稱為BOM、SMT、PRJ、Gerber和DOC的文件夾。 BOM文件夾存放BOM表發給采購人員。SMT文件夾存放裝配圖文件和坐標文件發給貼片廠。PRJ文件夾存放工程文件…

C++基礎:多態

多態相關 多態繼承重寫父類的虛函數多態的體現,父類的引用指向子類對象的空間虛函數可以實現,也可以不實現,不實現必須要有初始值存在未定義的虛函數的類為抽象類.抽象類不能實例化對象;(animal父類不能實例化對象)如果父類中的函數非虛函數,則會調用父類中的函數//多態的體現…

匯凱金業:紙黃金和實物黃金的價格有什么區別

紙黃金和實物黃金的價格主要受到全球黃金市場行情的影響&#xff0c;二者的基礎價格并無太大差異&#xff0c;但在具體交易時&#xff0c;可能會存在一些價格上的區別&#xff0c;這些差異主要來自以下幾個方面&#xff1a; 交易費用與管理費&#xff1a;紙黃金交易通常需要支…

python xls格式轉為xlsx格式

python 兩個表格字段列名稱值&#xff0c;對比字段差異-CSDN博客 import os import win32com.clientdef xls_to_xlsx(file_path, excel):"""將指定的xls文件轉化為xlsx格式file_path: 文件路徑excel: 代表Excel應用程序"""# 打開原始文檔workbo…