如何为AudioQueue提供音频缓冲来播放音频? [英] How to provide audio buffer to AudioQueue to play audio?

查看:223
本文介绍了如何为AudioQueue提供音频缓冲来播放音频?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我正在接收LinearPCM格式的音频数据,我需要播放。
我关注iOS SpeakHere示例。但是我无法知道如何以及在哪里为 AudioQueue 提供缓冲区。

In my application, I am receiving audio data in LinearPCM format, which I need to play. I am following iOS SpeakHere example. However I cannot get how and where I should provide a buffer to AudioQueue.

任何人都可以通过 AudioQueue 向我提供在iOS中播放音频缓冲区的工作示例吗?

Can anyone provide me a working example of playing audio buffer in iOS via AudioQueue?

推荐答案

在SpeakHere示例中,使用 AudioQueue 实现播放。

In the SpeakHere example playback is achieved using AudioQueue.

AudioQueue 的设置中,指定了一个函数,当队列需要更多数据时将调用该函数。

In the set up of AudioQueue, a function is specified that will be called when the queue wants more data.

你可以在这个方法中看到:

You can see that in this method:

void AQPlayer::SetupNewQueue() 

这是指定回调函数的行:

Here's the line that specifies the callback function:

    XThrowIfError(AudioQueueNewOutput(&mDataFormat, AQPlayer::AQBufferCallback, this, 
                                    CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &mQueue), "AudioQueueNew failed");

如果你看一下 AQPlayer :: AQBufferCallback ,你会看到它从哪里获取数据。在此示例中,数据已写入磁盘上的文件。如果你想节省内存,或者音频文件可能非常大,这是一个很好的解决方案。

If you take a look at AQPlayer::AQBufferCallback, you'll see where it gets the data from. In this example, the data has been written out to a file on disk. That's a good solution if you want to save memory, or if there's a possibility the audio file could be quite large.

无论如何,看看 AQPlayer :: AQBufferCallback ,您将看到对函数 AudioFileReadPackets 的调用。这就是从磁盘上的文件中读取音频数据包的内容。它直接读入 AudioQueue 将使用的缓冲区:

Anyway, looking at AQPlayer::AQBufferCallback, you'll see a call to a function AudioFileReadPackets. That's what reads in the audio packets from the file on disk. It reads them straight into the buffer that AudioQueue will use:

    OSStatus result = AudioFileReadPackets(THIS->GetAudioFileID(), false, &numBytes, inCompleteAQBuffer->mPacketDescriptions, THIS->GetCurrentPacket(), &nPackets, 
                                       inCompleteAQBuffer->mAudioData);

该缓冲区为 inCompleteAQBuffer-> mAudioData

最后,回调函数必须按如下方式将缓冲区入队:

Finally, the callback function must enqueue the buffer as follows:

if (nPackets > 0) {
    inCompleteAQBuffer->mAudioDataByteSize = numBytes;      
    inCompleteAQBuffer->mPacketDescriptionCount = nPackets;     
    AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, 0, NULL);
    THIS->mCurrentPacket = (THIS->GetCurrentPacket() + nPackets);
} 

首先请注意,我们必须检查是否有一些数据包要播放。它还必须指定缓冲区中有多少字节。

Note first that it has to check that we have some packets to play. It also has to specify how many bytes are in the buffer.

然后,这一行在这里:

THIS->mCurrentPacket = (THIS->GetCurrentPacket() + nPackets);

这可以跟踪我们音频缓冲区中整体的位置。换句话说,当从文件中复制更多数据时,我们需要将 mCurrentPacket 转发到下一个副本将数据放在正确的位置。

That keeps a track of where we are overall in our audio buffer. In other words, as more data is copied in from the file, we need to position the mCurrentPacket forward to that the next copy puts data in the correct place.

这篇关于如何为AudioQueue提供音频缓冲来播放音频?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆