首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用AudioBufferList添加AVAssetReader?

如何使用AudioBufferList添加AVAssetReader?
EN

Stack Overflow用户
提问于 2011-04-10 23:21:05
回答 1查看 5.8K关注 0票数 3

我一直在使用AVAssetReader读取音频资产,以便以后可以使用带有AudioUnit回调的AUGraph回放音频。我让AUGraph和AudioUnit回调工作,但它从磁盘读取文件,如果文件太大,它将占用太多的内存和崩溃的应用程序。因此,我现在直接阅读资产,但规模有限。然后,我将把它作为一个双缓冲区来管理,并在需要时得到它需要的AUGraph。

(注意:我很想知道我是否可以使用,并且仍然使用带有AUGraph回调的AudioUnit,因此内存由iOS框架管理。)

我的问题是,我对C中的数组、结构和指针没有很好的理解。我需要帮助的部分是将单个AudioBufferList保存在单个AudioBuffer上,并将该数据添加到另一个AudioBufferList中,后者保存了所有以后使用的数据。我相信我需要使用memcpy,但还不清楚如何使用它,甚至不清楚如何初始化AudioBufferList。我正在使用MixerHost作为参考,这是来自苹果的示例项目,它从磁盘读取文件。

我已经上传了我的工作正在进行中,如果你想要加载它的Xcode。我已经弄清楚了我需要做的大部分事情,一旦我把数据收集到一个地方,我就可以去了。

样本项目:MyAssetReader.zip

在标头中,可以看到我将bufferList声明为指向结构的指针。

代码语言:javascript
复制
@interface MyAssetReader : NSObject {
    BOOL reading;
    signed long sampleTotal;
    Float64 totalDuration;

    AudioBufferList *bufferList; // How should this be handled?
}

然后我以这种方式分配bufferList,主要是从MixerHost借来的.

代码语言:javascript
复制
UInt32 channelCount = [asset.tracks count];

if (channelCount > 1) {
    NSLog(@"We have more than 1 channel!");
}

bufferList = (AudioBufferList *) malloc (
                                         sizeof (AudioBufferList) + sizeof (AudioBuffer) * (channelCount - 1)
                                         );

if (NULL == bufferList) {NSLog (@"*** malloc failure for allocating bufferList memory"); return;}

// initialize the mNumberBuffers member
bufferList->mNumberBuffers = channelCount;

// initialize the mBuffers member to 0
AudioBuffer emptyBuffer = {0};
size_t arrayIndex;
for (arrayIndex = 0; arrayIndex < channelCount; arrayIndex++) {
    // set up the AudioBuffer structs in the buffer list
    bufferList->mBuffers[arrayIndex] = emptyBuffer;
    bufferList->mBuffers[arrayIndex].mNumberChannels  = 1;
    // How should mData be initialized???
    bufferList->mBuffers[arrayIndex].mData            = malloc(sizeof(AudioUnitSampleType)); 
}

最后,我循环读取。

代码语言:javascript
复制
int frameCount = 0;

CMSampleBufferRef nextBuffer;
while (assetReader.status == AVAssetReaderStatusReading) {
    nextBuffer = [assetReaderOutput copyNextSampleBuffer];

    AudioBufferList  localBufferList;
    CMBlockBufferRef blockBuffer;    
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(nextBuffer, NULL, &localBufferList, sizeof(localBufferList), NULL, NULL, 
                                                            kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &blockBuffer);

    // increase the number of total bites
    bufferList->mBuffers[0].mDataByteSize += localBufferList.mBuffers[0].mDataByteSize;

    // carefully copy the data into the buffer list
    memcpy(bufferList->mBuffers[0].mData + frameCount, localBufferList.mBuffers[0].mData, sizeof(AudioUnitSampleType));

    // get information about duration and position
    //CMSampleBufferGet
    CMItemCount sampleCount = CMSampleBufferGetNumSamples(nextBuffer);
    Float64 duration = CMTimeGetSeconds(CMSampleBufferGetDuration(nextBuffer));
    Float64 presTime = CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(nextBuffer));

    if (isnan(duration)) duration = 0.0;
    if (isnan(presTime)) presTime = 0.0;

    //NSLog(@"sampleCount: %ld", sampleCount);
    //NSLog(@"duration: %f", duration);
    //NSLog(@"presTime: %f", presTime);

    self.sampleTotal += sampleCount;
    self.totalDuration += duration;
    frameCount++;

    free(nextBuffer);
}

我不确定我如何处理mDataByteSize和mData,尤其是使用memcpy。由于mData是一个空指针,这是一个额外的棘手区域。

代码语言:javascript
复制
    memcpy(bufferList->mBuffers[0].mData + frameCount, localBufferList.mBuffers[0].mData, sizeof(AudioUnitSampleType));

在这一行中,我认为它应该将值从localBufferList中的数据复制到bufferList中的位置,再加上将指针定位到应该写入数据的指针的帧数。我有几个想法,我需要改变什么,才能让它发挥作用。

  • 由于一个空指针仅为1,而不是AudioUnitSampleType指针的大小,所以我可能还需要将它乘以size of (AudioUnitSampleType)才能使memcpy到达正确的位置。
  • 我可能没有正确地使用malloc来准备mData,但是由于我不确定会有多少帧,所以我不知道如何初始化它。

目前,当我运行这个应用程序时,它用一个无效的bufferList指针结束这个函数。

感谢您帮助我更好地理解如何管理AudioBufferList。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-04-21 07:41:21

我想出了自己的答案。我决定使用一个NSMutableData对象,它允许我在调用NSMutableData以获得AudioBufferList之后,从CMSampleBufferRef中获取AudioBufferList。

代码语言:javascript
复制
        [data appendBytes:localBufferList.mBuffers[0].mData length:localBufferList.mBuffers[0].mDataByteSize];

一旦完成了read循环,我的NSMutableData对象中就有了所有的数据。然后以这种方式创建和填充AudioBufferList。

代码语言:javascript
复制
audioBufferList = (AudioBufferList *)malloc(sizeof(AudioBufferList));
if (NULL == audioBufferList) {
    NSLog (@"*** malloc failure for allocating audioBufferList memory");
    [data release];
    return;
}
audioBufferList->mNumberBuffers = 1;
audioBufferList->mBuffers[0].mNumberChannels = channelCount;
audioBufferList->mBuffers[0].mDataByteSize = [data length];
audioBufferList->mBuffers[0].mData = (AudioUnitSampleType *)malloc([data length]);
if (NULL == audioBufferList->mBuffers[0].mData) {
    NSLog (@"*** malloc failure for allocating mData memory");
    [data release];
    return;
}
memcpy(audioBufferList->mBuffers[0].mData, [data mutableBytes], [data length]);
[data release];

我希望能对如何使用malloc创建并填充结构进行一些代码回顾。我得到了一个偶然的EXC_BAD_ACCESS错误,但我还不能准确地指出错误在哪里。因为我在结构上使用malloc,所以我不应该在任何地方保留它。我确实调用"free“来释放结构中的子元素,最后,在我使用malloc的任何地方释放结构本身。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5615395

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档