gpt4 book ai didi

objective-c - 如何使用 AVAssetReader 添加到 AudioBufferList?

转载 作者:搜寻专家 更新时间:2023-10-30 20:12:06 25 4
gpt4 key购买 nike

我一直致力于使用 AVAssetReader 读取音频 Assets ,以便稍后可以使用带有 AudioUnit 回调的 AUGraph 播放音频。我有 AUGraph 和 AudioUnit 回调工作,但它从磁盘读取文件,如果文件太大,它会占用太多内存并使应用程序崩溃。因此,我改为直接阅读 Assets ,而且大小有限。然后,我会将其作为双缓冲区进行管理,并在需要时获取 AUGraph 所需的内容。

(注意:我很想知道我是否可以使用音频队列服务并仍然使用带有 AudioUnit 回调的 AUGraph,以便 iOS 框架为我管理内存。)

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

如果您想在 Xcode 中加载它,我已经上传了我正在进行的工作。我已经弄清楚完成这项工作所需的大部分内容,一旦我将所有数据收集到一个地方,我就可以开始了。

示例项目:MyAssetReader.zip

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

@interface MyAssetReader : NSObject {
BOOL reading;
signed long sampleTotal;
Float64 totalDuration;

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

然后我这样分配bufferList,主要是借鉴了MixerHost...

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));
}

最后我循环阅读。

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 是一个空指针,这是一个额外的棘手区域。

    memcpy(bufferList->mBuffers[0].mData + frameCount, localBufferList.mBuffers[0].mData, sizeof(AudioUnitSampleType));

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

  • 由于 void 指针只是 1 而不是 AudioUnitSampleType 指针的大小,我可能还需要将它乘以 sizeof(AudioUnitSampleType) 以使 memcpy 进入正确的位置
  • 我可能没有正确使用 malloc 来准备 mData,但由于我不确定会有多少帧,所以我不确定如何初始化它

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

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

最佳答案

我想出了我自己的答案。我决定使用 NSMutableData 对象,它允许我在调用 CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer 获取 AudioBufferList 后从 CMSampleBufferRef 追加字节。

        [data appendBytes:localBufferList.mBuffers[0].mData length:localBufferList.mBuffers[0].mDataByteSize];

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

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 的任何地方释放结构本身。

关于objective-c - 如何使用 AVAssetReader 添加到 AudioBufferList?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5615395/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com