IOS 音頻開發文件大小計算

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

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

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

音頻基礎知識

組成

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

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

咱們能夠經過多種不一樣的方法爲真正的音頻數據編碼。例如CAF文件即是一種文件格式,它可以包含MP3格式,線性PCM以及其它數據格式的音頻。app

數據格式(或音頻編碼)

咱們將從音頻編碼開始闡述(而不是文件格式),由於編碼是最重要的環節。框架

線性PCM:

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

音頻文件計算大小


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

採樣頻率:

是指單位時間內的採樣次數。採樣頻率越大,採樣點之間的間隔就越小,數字化後獲得的聲音就越逼真,但相應的數據量就越大。聲卡通常提供11.025kHz、22.05kHz和44.1kHz等不一樣的採樣頻率。編碼

採樣位數:

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

聲道數

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

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

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

單聲道的聲道數爲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 著做權歸做者全部,轉載請聯繫做者得到受權,並標註「簡書做者」。
相關文章
相關標籤/搜索