背景
創(chuàng)新互聯(lián)建站是一家專注于成都網(wǎng)站制作、成都網(wǎng)站設(shè)計與策劃設(shè)計,瑞昌網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設(shè)十年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:瑞昌等地區(qū)。瑞昌做網(wǎng)站價格咨詢:13518219792
因為我的公司需要設(shè)計到app與硬件的通信,所以去年深入的研究了一下音頻各種格式的轉(zhuǎn)換,曾寫過一篇簡書,現(xiàn)在搬過來豐富下自己的blog。
首先介紹一下常用的音頻文件格式
由于App是通過AVAudioRecorder錄制音頻,默認(rèn)格式為pcm,文件比較大,所以不適合用于聊天通信的文件格式,所以最優(yōu)的選擇是轉(zhuǎn)換成amr格式
音頻格式轉(zhuǎn)換方式
.pcm-->.wav-->.amr
a)將pcm轉(zhuǎn)成wav
什么是WAV和PCM?
WAV:wav是一種無損的音頻文件格式,WAV符合 PIFF(Resource Interchange File Format)規(guī)范。所有的WAV都有一個文件頭,這個文件頭音頻流的編碼參數(shù)。WAV對音頻流的編碼沒有硬性規(guī)定,除了PCM之外,還有幾乎所有支持ACM規(guī)范的編碼都可以為WAV的音頻流進行編碼。
PCM:PCM(Pulse Code Modulation----脈碼調(diào)制錄音)。所謂PCM錄音就是將聲音等模擬信號變成符號化的脈沖列,再予以記錄。PCM信號是由[1]、[0]等符號構(gòu)成的數(shù)字信號,而未經(jīng)過任何編碼和壓縮處理。與模擬信號比,它不易受傳送系統(tǒng)的雜波及失真的影響。動態(tài)范圍寬,可得到音質(zhì)相當(dāng)好的影響效果。
簡單來說:wav是一種無損的音頻文件格式,pcm是沒有壓縮的編碼方式。
WAV和PCM的關(guān)系
WAV可以使用多種音頻編碼來壓縮其音頻流,不過我們常見的都是音頻流被PCM編碼處理的WAV,但這不表示W(wǎng)AV只能使用PCM編碼,MP3編碼同樣也可以運用在WAV中,和AVI一樣,只要安裝好了相應(yīng)的Decode,就可以欣賞這些WAV了。在Windows平臺下,基于PCM編碼的WAV是被支持得最好的音頻格式,所有音頻軟件都能完美支持,由于本身可以達到較高的音質(zhì)的要求,因此,WAV也是音樂編輯創(chuàng)作的首選格式,適合保存音樂素材。因此,基于PCM編碼的WAV被作為了一種中介的格式,常常使用在其他編碼的相互轉(zhuǎn)換之中,例如MP3轉(zhuǎn)換成WMA。
簡單來說:pcm是無損wav文件中音頻數(shù)據(jù)的一種編碼方式,但wav還可以用其它方式編碼。
這里詳細(xì)寫了pcm和wav的區(qū)別,我簡單概括成pcm少了一個wav頭描述信息。為此我從訊飛語音的sdk中移植出填寫wav頭的函數(shù)并修改了一下
// 為pcm文件寫入wav頭 + (NSData*) writeWavHead:(NSData *)audioData { long sampleRate = [[self GetAudioRecorderSettingDict][AVSampleRateKey] longValue]; long numOfChannelsKey = [[self GetAudioRecorderSettingDict][AVNumberOfChannelsKey] longValue]; Byte waveHead[44]; waveHead[0] = 'R'; waveHead[1] = 'I'; waveHead[2] = 'F'; waveHead[3] = 'F'; long totalDatalength = [audioData length] + 44; waveHead[4] = (Byte)(totalDatalength & 0xff); waveHead[5] = (Byte)((totalDatalength >> 8) & 0xff); waveHead[6] = (Byte)((totalDatalength >> 16) & 0xff); waveHead[7] = (Byte)((totalDatalength >> 24) & 0xff); waveHead[8] = 'W'; waveHead[9] = 'A'; waveHead[10] = 'V'; waveHead[11] = 'E'; waveHead[12] = 'f'; waveHead[13] = 'm'; waveHead[14] = 't'; waveHead[15] = ' '; waveHead[16] = 16; //size of 'fmt ' waveHead[17] = 0; waveHead[18] = 0; waveHead[19] = 0; waveHead[20] = 1; //format waveHead[21] = 0; waveHead[22] = numOfChannelsKey; //chanel waveHead[23] = 0; waveHead[24] = (Byte)(sampleRate & 0xff); waveHead[25] = (Byte)((sampleRate >> 8) & 0xff); waveHead[26] = (Byte)((sampleRate >> 16) & 0xff); waveHead[27] = (Byte)((sampleRate >> 24) & 0xff); long byteRate = sampleRate * 2 * (16 >> 3);; waveHead[28] = (Byte)(byteRate & 0xff); waveHead[29] = (Byte)((byteRate >> 8) & 0xff); waveHead[30] = (Byte)((byteRate >> 16) & 0xff); waveHead[31] = (Byte)((byteRate >> 24) & 0xff); waveHead[32] = 2*(16 >> 3); waveHead[33] = 0; waveHead[34] = 16; waveHead[35] = 0; waveHead[36] = 'd'; waveHead[37] = 'a'; waveHead[38] = 't'; waveHead[39] = 'a'; long totalAudiolength = [audioData length]; waveHead[40] = (Byte)(totalAudiolength & 0xff); waveHead[41] = (Byte)((totalAudiolength >> 8) & 0xff); waveHead[42] = (Byte)((totalAudiolength >> 16) & 0xff); waveHead[43] = (Byte)((totalAudiolength >> 24) & 0xff); NSMutableData *pcmData = [[NSMutableData alloc]initWithBytes:&waveHead length:sizeof(waveHead)]; [pcmData appendData:audioData]; return pcmData; // [pcmData writeToFile:kVoiceWav atomically:true]; }
同時還需把關(guān)鍵的屬性抽取出來(如:采樣率,通道數(shù)…)
//錄音格式的設(shè)置 + (NSDictionary*)GetAudioRecorderSettingDict{ NSDictionary *recordSetting = [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithFloat: 8000],AVSampleRateKey, //采樣率 [NSNumber numberWithInt: kAudioFormatLinearPCM],AVFormatIDKey, [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,//采樣位數(shù) 默認(rèn) 16 [NSNumber numberWithInt: 2], AVNumberOfChannelsKey,//通道的數(shù)目 nil]; return recordSetting; }
b)將wav轉(zhuǎn)成amr
使用VoiceConvert(by:Tang Xiaoping)庫能將wav轉(zhuǎn)成amr,后來發(fā)現(xiàn)環(huán)信的EaseUI框架中也使用了這個
反過來轉(zhuǎn)換也是差不多的
pcm<--->mp3
這個就很簡單了,用lame的框架進行轉(zhuǎn)換,這個框架網(wǎng)上資料一大堆
本人為此花了不少時間整理了一下這些文件格式的轉(zhuǎn)換方法
/** * 轉(zhuǎn)換wav到amr * * @param wavPath wav文件路徑 * @param isDelete 轉(zhuǎn)換成功后是否刪除源文件 * * @return NO 失敗 YES成功 */ + (BOOL) wav2Amr:(NSString *)wavPath isDeleteSourchFile:(BOOL)isDelete; /** * 轉(zhuǎn)換amr到wav * * @param amrPath amr文件路徑 * @param isDelete 轉(zhuǎn)換成功后是否刪除源文件 * * @return NO 失敗 YES成功 */ + (BOOL) amr2Wav:(NSString *)amrPath isDeleteSourchFile:(BOOL)isDelete; /** * 轉(zhuǎn)換pcm到mp3 * * @param pcmPath pcm文件路徑 * @param isDelete 轉(zhuǎn)換成功后是否刪除源文件 * * @return NO 失敗 YES成功 */ + (BOOL) pcm2Mp3: (NSString *)pcmPath isDeleteSourchFile:(BOOL)isDelete; /** * 轉(zhuǎn)換pcm到wav * * @param pcmPath pcm文件路徑 * @param isDelete 轉(zhuǎn)換成功后是否刪除源文件 * * @return NO 失敗 YES成功 */ + (BOOL) pcm2Wav: (NSString *)pcmPath isDeleteSourchFile:(BOOL)isDelete; /** * 轉(zhuǎn)換pcm到amr * * @param pcmPath pcm文件路徑 * @param isDelete 轉(zhuǎn)換成功后是否刪除源文件 * * @return NO 失敗 YES成功 */ + (BOOL) pcm2Amr:(NSString *)pcmPath isDeleteSourchFile:(BOOL)isDelete; /** * 為pcm文件寫入wav頭 */ + (NSData*) writeWavHead:(NSData *)audioData; void conventToMp3(NSString *pcmFile,NSString *mp3File); /** 錄音格式設(shè)置,轉(zhuǎn)換的時候需要獲取.(如:采樣率、采樣位數(shù)、通道的數(shù)目) 建議使用此設(shè)置,如有修改,則轉(zhuǎn)換amr時也要對應(yīng)修改參數(shù),比較麻煩 @returns 錄音設(shè)置 */ + (NSDictionary*)GetAudioRecorderSettingDict;
demo的下載地址https://github.com/qq631192328/PFAudio.git,如果覺得好麻煩點下星,如果有什么問題歡迎指正
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。