如何将iPod库资源连接到音频队列服务并使用音频单元进行处理?

问题描述:

我需要处理来自iPod库的音频。读取iPod资源的唯一方法是AVAssetReader。要使用音频单元处理音频,它需要采用立体声格式,因此我有左右声道的值。但是,当我使用AVAssetReader从iPod库中读取资源时,它不允许我以立体声格式将其取出。它以交织格式出现,我不知道如何分解成左右声道。如何将iPod库资源连接到音频队列服务并使用音频单元进行处理?

去的地步,我需要去我需要做以下之一:

  1. 获取AVAssetReader给我立体声格式
  2. 的AudioBufferList交织的数据转换成非交错到获得立体声输出,我需要
  3. 发送它通过音频队列服务来获得我所需要的具有自动缓冲

我似乎被什么现有的公共API C是有限的一个do和AVAssetReader在读取iPod资源时支持的内容。你会怎么做?如何获得我需要使用音频单元进行处理的内容?

我的另一个限制是我无法一次读完整首歌曲,因为它会填满内存并使应用程序崩溃。这就是我想要使用音频队列服务的原因。如果我可以将来自iPod库的资产视为立体声格式的流,那么我的所有要求都将得到解决。

这可以完成吗?是否有任何文档,博客或文章解释如何完成这项工作?

+1

我不关注“立体声”和“交错”之间的区别。我认为你要处理的是有两个双声道音频流(交错,其中L和R是交替的),而不是两声道单声道声音。单位可以处理,但一个队列将会与一个交错流更快乐。 – invalidname 2011-06-15 21:06:56

听起来像你有几个问题堆积在那里。

当您设置AVAssetReader时,您可以传入设置字典。这里是我创造我AVAssetReaders ...

AVAssetReader* CreateAssetReaderFromSong(AVURLAsset* songURL) { 

    if([songURL.tracks count] <= 0) 
     return NULL; 


    AVAssetTrack* songTrack = [songURL.tracks objectAtIndex:0]; 

    NSDictionary* outputSettingsDict = [[NSDictionary alloc] initWithObjectsAndKeys: 

             [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey, 
             //  [NSNumber numberWithInt:AUDIO_SAMPLE_RATE],AVSampleRateKey, /*Not Supported*/ 
             //  [NSNumber numberWithInt: 2],AVNumberOfChannelsKey, /*Not Supported*/ 

             [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey, 
             [NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey, 
             [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey, 
             [NSNumber numberWithBool:NO],AVLinearPCMIsNonInterleaved, 

             nil]; 

    NSError* error = nil; 
    AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:songURL error:&error]; 

    { 
     AVAssetReaderTrackOutput* output = [[AVAssetReaderTrackOutput alloc] initWithTrack:songTrack outputSettings:outputSettingsDict]; 
     [reader addOutput:output]; 
     [output release]; 
    } 

    return reader; 
} 

至于象分裂左,右声道,你可以遍历根据您的“AVLinearPCMBitDepthKey”的数据。

因此,像这样的16位...

for (j=0; j<tBufCopy; j++, pAD+=2) {   // Fill the buffers... 
    mProcessingBuffer.Left[(tBlockUsed+j)] = ((sint32)pAD[0]); 
    mProcessingBuffer.Right[(tBlockUsed+j)] = ((sint32)pAD[1]); 
} 

现在假设你需要这个为你处理。但交错格式的数据真的很不错。您通常可以采用直接交错格式并将其传递回AudioQueue或远程I/O回调,并且它将正确播放。

为了让音频使用AudioQueue框架播放数据应遵循这一流程:

AVAssetReader - > NSData的缓冲 - > AudioQueueBuffer

然后在AudioQueue回调在那里,它要求只是更多的数据传递AudioQueueBuffer。就像...

- (void) audioQueueCallback:(AudioQueueRef)aq buffer:(AudioQueueBufferRef)buffer { 

    memcpy(buffer->mAudioData, srcData, mBufferByteSize); 
    //Setup buffer->mAudioDataSize 

    //... 

    AudioQueueEnqueueBuffer(mQueue, buffer, 0 /*CBR*/, 0 /*non compressed*/); 
}