2010-11-28 35 views
7

我正試圖訪問iPhone/iPad上的音頻文件的原始數據。我有以下代碼,這是我需要的基本開始。然而,我有一個AudioBuffer後,我很難做什麼。確定核心音頻AudioBuffer中的幀數

AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:urlAsset error:nil]; 
AVAssetReaderTrackOutput *assetReaderOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:[[urlAsset tracks] objectAtIndex:0] outputSettings:nil]; 
[assetReader addOutput:assetReaderOutput]; 
[assetReader startReading]; 

CMSampleBufferRef ref; 
NSArray *outputs = assetReader.outputs; 
AVAssetReaderOutput *output = [outputs objectAtIndex:0]; 
int y = 0; 
while (ref = [output copyNextSampleBuffer]) { 
    AudioBufferList audioBufferList; 
    CMBlockBufferRef blockBuffer; 
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(ref, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer); 
    for (y=0; y<audioBufferList.mNumberBuffers; y++) { 
     AudioBuffer audioBuffer = audioBufferList.mBuffers[y]; 
     SInt16 *frames = audioBuffer.mData; 
     for(int i = 0; i < 24000; i++) { // This sometimes crashes 
      Float32 currentFrame = frames[i]/32768.0f; 
     } 
    } 
} 

從本質上講,我不知道怎麼跟多少幀,每幀緩衝區包含,所以我不能可靠地從中提取數據。我對處理原始音頻數據很陌生,所以我打開如何最好地讀取AudioBuffer結構的mData屬性的任何建議。過去我也沒有用空指針做很多事情,所以在這方面的幫助也會很棒!

+0

優秀的問題!你的問題有助於解決我的類似問題。 – user523234 2012-07-19 22:20:34

+0

你在泄漏blockBuffer – 2013-06-11 08:40:17

回答

13

audioBuffer.mDataByteSize告訴你緩衝區的大小。你知道嗎?只要事後你沒有看不到struct AudioBuffer的聲明。您應該始終查看頭文件以及文檔。

爲了使mDataByteSize有意義,您必須知道數據的格式。輸出值的計數是mDataByteSize/sizeof(outputType)。不過,你對格式似乎很困惑 - 你必須在某處指定它。首先你把它作爲一個16位有符號整數

SInt16 *frames = audioBuffer.mData

然後你把它作爲32位浮點

Float32 currentFrame = frames[i]/32768.0f

插圖中,你認爲有24000個值,當然這會如果沒有確切的24000 16位值,則會崩潰。另外,您將數據稱爲「框架」,但您真正的意思是樣本。您稱爲'currentFrame'的每個值都是音頻的一個樣本。 'Frame'通常指的是一塊樣本,例如.mData

因此,假設數據格式是32位浮點數(請注意,我不知道它是否可以是8位整數或32位固定我知道)

for(int y=0; y<audioBufferList.mNumberBuffers; y++) 
{ 
    AudioBuffer audioBuffer = audioBufferList.mBuffers[y]; 
    int bufferSize = audioBuffer.mDataByteSize/sizeof(Float32); 
    Float32 *frame = audioBuffer.mData; 
    for(int i=0; i<bufferSize; i++) { 
    Float32 currentSample = frame[i]; 
    } 
} 

請注意,sizeof(Float32)總是4,但我留下來清楚。