IOS 音頻開發文件大小計算


  • 音頻基礎知識
  • 音頻文件計算大小
  • 音頻轉碼

標簽(空格分隔): 調查 IOS音頻

https://developer.apple.com/library/ios/documentation/MusicAudio/Conceptual/CoreAudioOverview/SupportedAudioFormatsMacOSX/SupportedAudioFormatsMacOSX.html

音頻基礎知識

組成

音頻文件的組成:文件格式(或者音頻容器) + 數據格式(或者音頻編碼)。

文件格式(或音頻容器)是用於形容文件本身的格式。

我們可以通過多種不同的方法為真正的音頻數據編碼。例如CAF文件便是一種文件格式,它能夠包含MP3格式,線性PCM以及其它數據格式的音頻。

數據格式(或音頻編碼)

我們將從音頻編碼開始闡述(而不是文件格式),因為編碼是最重要的環節。

線性PCM:

這是表示線性脈沖編碼調制,主要是描寫用於將模擬聲音數據轉換成數字格式的技術。簡單地說也就是未壓縮的數據。因為數據是未壓縮的,所以我們便可以最快速地播放出音頻,而如果空間不是問題的話這便是iPhone音頻的優先代碼選擇。

音頻文件計算大小


聲卡對聲音的處理質量可以用三個基本參數來衡量,即采樣頻率、采樣位數和聲道數。

采樣頻率:

是指單位時間內的采樣次數。采樣頻率越大,采樣點之間的間隔就越小,數字化后得到的聲音就越逼真,但相應的數據量就越大。聲卡一般提供11.025kHz、22.05kHz和44.1kHz等不同的采樣頻率。

采樣位數:

是記錄每次采樣值數值大小的位數。采樣位數通常有8bits或16bits兩種,采樣位數越大,所能記錄聲音的變化度就越細膩,相應的數據量就越大。

聲道數

是指處理的聲音是單聲道還是立體聲。單聲道在聲音處理過程中只有單數據流,而立體聲則需要左、右聲道的兩個數據流。顯然,立體聲的效果要好,但相應的數據量要比單聲道的數據量加倍。

聲音數據量的計算公式為:

數據量(字節/秒)= (采樣頻率(Hz)× 采樣位數(bit) × 聲道數)/ 8

單聲道的聲道數為1,立體聲的聲道數為2。

【例1】請計算對於5分鍾雙聲道、16位采樣位數、44.1kHz采樣頻率聲音的不壓縮數據量是多少?
根據公式:數據量=(采樣頻率×采樣位數×聲道數×時間)/8
得,數據量(MB)=[44.1×1000×16×2×(5×60)] /(8×1024×1024)=50.47MB
計算時要注意幾個單位的換算細節:
時間單位換算:1分=60秒
采樣頻率單位換算:1kHz=1000Hz
數據量單位換算:1MB=1024×1024=1048576B

【例2】請計算對於雙聲道立體聲、采樣頻率為44.1kHz、采樣位數為16位的激光唱盤(CD-A),用一個650MB的CD-ROM可存放多長時間的音樂?
已知音頻文件大小的計算公式如下:
文件的字節數/每秒=采樣頻率(Hz)X采樣位數(位)X聲道數/8
根據上面的公式計算一秒鍾時間內的不壓縮數據量:(44.1×1000×16×2)/8=0.168MB/s
那么,一個650MB的CD-ROM可存放的時間為:(650/0.168)/(60×60)=1.07小時。


IOS 音頻轉碼

音頻轉碼使用的框架為:AudioToolBox

內存轉碼:

使用函數: AudioConverterFillComplexBuffer
    - (void)handleAudioPackets:(const void *)inputData numberOfBytes:(UInt32)numberOfBytes numberOfPackets:(UInt32)numberOfPackets packetDescriptions:(AudioStreamPacketDescription *)packetDescriptions { if (!_audioFileStream || !_parseAudioHeader || !_decodeConverterRef) return; AudioConvertInfo convertInfo = (AudioConvertInfo){ .done = NO, .numberOfPackets = numberOfPackets, .packetDescriptions = packetDescriptions, .audioBuffer = (AudioBuffer){ .mData = (void *)inputData, .mDataByteSize = numberOfBytes, .mNumberChannels = _sourceAsbd.mChannelsPerFrame } }; AudioBufferList decodedData; decodedData.mNumberBuffers = 1; decodedData.mBuffers[0].mNumberChannels = _canonicalAsbd.mChannelsPerFrame; decodedData.mBuffers[0].mDataByteSize = _decodeBufferSize; decodedData.mBuffers[0].mData = _decodeBuffer; UInt32 ioOutputDataPackets1, ioOutputDataPackets2; OSStatus decodingStatus, encodingStatus; while (1) { ioOutputDataPackets1 = numberOfPackets; decodingStatus = AudioConverterFillComplexBuffer(_decodeConverterRef, AudioConverterCallback, (void*)&convertInfo, &ioOutputDataPackets1, &decodedData, NULL); if (decodingStatus == OS_STATUS_DONE || decodingStatus == 0) { if (ioOutputDataPackets1 > 0) { // Start encoding AudioConvertInfo encodeConvertInfo = (AudioConvertInfo){ .done = NO, .numberOfPackets = ioOutputDataPackets1, .packetDescriptions = NULL, .audioBuffer = (AudioBuffer){ .mData = decodedData.mBuffers[0].mData, .mDataByteSize = decodedData.mBuffers[0].mDataByteSize, .mNumberChannels = _canonicalAsbd.mChannelsPerFrame } }; AudioBufferList encodedData; encodedData.mNumberBuffers = 1; encodedData.mBuffers[0].mNumberChannels = _destinationAsbd.mChannelsPerFrame; encodedData.mBuffers[0].mDataByteSize = _encodeBufferSize; encodedData.mBuffers[0].mData = _encodeBuffer; while (1) { ioOutputDataPackets2 = _encodePacketsPerBuffer; encodingStatus = AudioConverterFillComplexBuffer(_encodeConverterRef, AudioConverterCallback, (void*)&encodeConvertInfo, &ioOutputDataPackets2, &encodedData, _encodePacketDescriptions); if (encodingStatus == OS_STATUS_DONE || encodingStatus == 0) { //一個buffer 轉碼成功 } else { [self failureOccurred]; return; } if (encodingStatus == OS_STATUS_DONE) { break; } } // End encoding } } else { [self failureOccurred]; return; } if (decodingStatus == OS_STATUS_DONE) { break; } } }

文件轉碼:

使用函數 ExtAudioFileRead
void startConvert(ExtAudioConverterSettings* settings){ //Determine the proper buffer size and calculate number of packets per buffer //for CBR and VBR format UInt32 sizePerBuffer = 32*1024;//32KB is a good starting point UInt32 framesPerBuffer = sizePerBuffer/sizeof(SInt16); // allocate destination buffer SInt16 *outputBuffer = (SInt16 *)malloc(sizeof(SInt16) * sizePerBuffer); while (1) { AudioBufferList outputBufferList; outputBufferList.mNumberBuffers = 1; outputBufferList.mBuffers[0].mNumberChannels = settings->outputFormat.mChannelsPerFrame; outputBufferList.mBuffers[0].mDataByteSize = sizePerBuffer; outputBufferList.mBuffers[0].mData = outputBuffer; UInt32 framesCount = framesPerBuffer; CheckError(ExtAudioFileRead(settings->inputFile, &framesCount, &outputBufferList), "ExtAudioFileRead failed"); if (framesCount==0) { printf("Done reading from input file\n"); return; } CheckError(ExtAudioFileWrite(settings->outputFile, framesCount, &outputBufferList), "ExtAudioFileWrite failed"); } }

代碼下載 http://download.csdn.net/download/qihongru1227/9326777



文/我愛水果(簡書作者)
原文鏈接:http://www.jianshu.com/p/5e5428471f48
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM