簡體   English   中英

與ExtAudioFileRead播放.caf音頻文件不同步

[英]Playing .caf audio file with ExtAudioFileRead is not sync

我的應用程序對來自麥克風輸入的音頻進行了大量數據處理。 為了獲得“演示模式”,我想基於本地.caf音頻文件執行相同的操作。 我設法得到了音頻文件。 現在,我嘗試使用ExtAudioFileRead讀取.caf文件,然后進行數據處理。

void readFile()
{
OSStatus err = noErr;

// Audio file
NSURL *path = [[NSBundle mainBundle] URLForResource:@"output" withExtension:@"caf"];
ExtAudioFileOpenURL((__bridge CFURLRef)path, &audio->audiofile);
assert(audio->audiofile);

// File's format.
AudioStreamBasicDescription fileFormat;
UInt32 size = sizeof(fileFormat);
err = ExtAudioFileGetProperty(audio->audiofile, kExtAudioFileProperty_FileDataFormat, &size, &fileFormat);

// tell the ExtAudioFile API what format we want samples back in
//bzero(&audio->clientFormat, sizeof(audio->clientFormat));
audio->clientFormat.mSampleRate         = SampleRate;
audio->clientFormat.mFormatID           = kAudioFormatLinearPCM;
audio->clientFormat.mFormatFlags        = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audio->clientFormat.mFramesPerPacket    = 1;
audio->clientFormat.mChannelsPerFrame   = 1;
audio->clientFormat.mBitsPerChannel     = 16;//sizeof(AudioSampleType) * 8;
audio->clientFormat.mBytesPerPacket     = 2 * audio->clientFormat.mChannelsPerFrame;
audio->clientFormat.mBytesPerFrame      = 2 * audio->clientFormat.mChannelsPerFrame;
err = ExtAudioFileSetProperty(audio->audiofile, kExtAudioFileProperty_ClientDataFormat, sizeof(audio->clientFormat), &audio->clientFormat);

// find out how many frames we need to read
SInt64 numFrames = 0;
size = sizeof(numFrames);
err = ExtAudioFileGetProperty(audio->audiofile, kExtAudioFileProperty_FileLengthFrames, &size, &numFrames);

// create the buffers for reading in data
AudioBufferList *bufferList = malloc(sizeof(AudioBufferList) + sizeof(AudioBuffer) * (audio->clientFormat.mChannelsPerFrame - 1));
bufferList->mNumberBuffers = audio->clientFormat.mChannelsPerFrame;
for (int ii=0; ii < bufferList->mNumberBuffers; ++ii)
{
    bufferList->mBuffers[ii].mDataByteSize = sizeof(float) * (int)numFrames;
    bufferList->mBuffers[ii].mNumberChannels = 1;
    bufferList->mBuffers[ii].mData = malloc(bufferList->mBuffers[ii].mDataByteSize);
}

UInt32 maxReadFrames = 1024;
UInt32 rFrames = (UInt32)numFrames;
while(rFrames > 0)
{
    UInt32 framesToRead = (maxReadFrames > rFrames) ? rFrames : maxReadFrames;
    err = ExtAudioFileRead(audio->audiofile, &framesToRead, bufferList);
    [audio processAudio:bufferList];
    if (rFrames % SampleRate == 0)
        [audio realtimeUpdate:nil];
    rFrames = rFrames - maxReadFrames;
}

// Close the file
ExtAudioFileDispose(audio->audiofile);

// destroy the buffers
for (int ii=0; ii < bufferList->mNumberBuffers; ++ii)
{
    free(bufferList->mBuffers[ii].mData);
}
free(bufferList);
bufferList = NULL;
}

顯然有些事情我不理解,或者ExtAudioFileRead我做錯了,因為該代碼根本無法工作。 我有兩個主要問題:

  1. 該文件即刻播放。 我的意思是44'100個樣本顯然不等於1秒。 我的3分鍾音頻文件處理過程在幾秒鍾內就完成了...
  2. 在處理過程中,我需要更新UI。 所以我在processaudiorealtimeUpdate有一些dispatch_sync。 ExtAudioFileRead似乎並沒有真正意識到這一點,它凍結了。 感謝您的幫助。

您編寫的代碼只是從文件中讀取示例,然后調用processAudio。 這將盡快完成。 一旦processAudio完成,將讀取下一批樣本,並再次調用processAudio。 您不應該假設從音頻文件中進行讀取(這是一個低水平且無阻塞的os調用)需要花費與音頻播放相同的時間。 如果要根據采樣率處理文件中的音頻,則可能應該使用AUFilePlayer音頻單元。 這樣可以以正確的速度播放文件,並且您可以使用回調以實時音頻時間處理樣本,而不是“盡可能快”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM