使用 AudioQueueServices 同时播放 (10+)

发布于 2024-12-04 02:45:59 字数 2024 浏览 2 评论 0原文

谁能告诉我这是如何在 iPhone 上实现的?我正在尝试制作一款可以同时播放大约 12 个声音的游戏,但我不知道如何使用 AudioQueueServices。我知道您必须初始化、添加缓冲区、播放它们并使用 AudioQueueEnqueueBufferWithParameters 来同时播放,但我不知道如何将其转换为代码。任何有这方面代码的人或者可以向我解释的人都会很棒!

如果您听说过音调网格/音调板,这正是我正在尝试做的。我知道应用程序商店中已经有一些应用程序可以执行此操作,但我不知道它是如何完成的。

太长了;需要 AudioQueueServices 同时播放 10 种以上声音的帮助。

示例:

新播放

    if (isPlaying == NO) {
err = AudioQueueNewOutput (&streamFormat, AudioEngineOutputBufferCallback, self, nil, nil, 0, &outputQueue);
if (err != noErr) NSLog(@"AudioQueueNewOutput() error: %d", err);

入队缓冲区

outputBuffersToRewrite = 3;
bufferByteSize = (sampleRate > 16000)? 2176 : 512; // 40.5 Hz : 31.25 Hz 
for (i=0; i<3; i++) {
    err = AudioQueueAllocateBuffer (outputQueue, bufferByteSize, &buffer); 
    if (err == noErr) {
        [self generateTone: buffer];
        err = AudioQueueEnqueueBuffer (outputQueue, buffer, 0, nil);
        if (err != noErr) NSLog(@"AudioQueueEnqueueBuffer() error: %d", err);
    } else {
        NSLog(@"AudioQueueAllocateBuffer() error: %d", err); 
        return;
    }
}

开始播放

isPlaying = YES;
err = AudioQueueStart(outputQueue, nil);
if (err != noErr) { NSLog(@"AudioQueueStart() error: %d", err); isPlaying= NO; return; }
} else {
NSLog (@"Error: audio is already playing back.");

设置流格式字段

BOOL isHighSampleRate = (sampleRate > 16000);
int bufferByteSize;
AudioQueueBufferRef buffer;

AudioStreamBasicDescription streamFormat;
streamFormat.mSampleRate = sampleRate;
streamFormat.mFormatID = kAudioFormatLinearPCM;
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
streamFormat.mBitsPerChannel = 16;
streamFormat.mChannelsPerFrame = 1;
streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
streamFormat.mFramesPerPacket = 1;
streamFormat.mReserved = 0;

Can anyone show me how this is done for for the iPhone? I am trying to make a game to play about 12 sounds at exactly the same time and I can't figure out how to use AudioQueueServices. I understand you have to initialize, add buffers, play them back and use AudioQueueEnqueueBufferWithParameters to get simultaneous playback, but I don't know how to turn that into code. Anyone with code on this or someone that could explain it to me would be amazing!

If you've heard of a Tone Grid/Tone Board that's exactly what I'm trying to do. I know there are a few apps in the Appstore already that do this, but I don't know how it is done.

TLDR; Need help with AudioQueueServices simultaneous playback with 10+ sounds.

Example:

New playback

    if (isPlaying == NO) {
err = AudioQueueNewOutput (&streamFormat, AudioEngineOutputBufferCallback, self, nil, nil, 0, &outputQueue);
if (err != noErr) NSLog(@"AudioQueueNewOutput() error: %d", err);

Enqueue buffers

outputBuffersToRewrite = 3;
bufferByteSize = (sampleRate > 16000)? 2176 : 512; // 40.5 Hz : 31.25 Hz 
for (i=0; i<3; i++) {
    err = AudioQueueAllocateBuffer (outputQueue, bufferByteSize, &buffer); 
    if (err == noErr) {
        [self generateTone: buffer];
        err = AudioQueueEnqueueBuffer (outputQueue, buffer, 0, nil);
        if (err != noErr) NSLog(@"AudioQueueEnqueueBuffer() error: %d", err);
    } else {
        NSLog(@"AudioQueueAllocateBuffer() error: %d", err); 
        return;
    }
}

Starting playback

isPlaying = YES;
err = AudioQueueStart(outputQueue, nil);
if (err != noErr) { NSLog(@"AudioQueueStart() error: %d", err); isPlaying= NO; return; }
} else {
NSLog (@"Error: audio is already playing back.");

Set up stream format fields

BOOL isHighSampleRate = (sampleRate > 16000);
int bufferByteSize;
AudioQueueBufferRef buffer;

AudioStreamBasicDescription streamFormat;
streamFormat.mSampleRate = sampleRate;
streamFormat.mFormatID = kAudioFormatLinearPCM;
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
streamFormat.mBitsPerChannel = 16;
streamFormat.mChannelsPerFrame = 1;
streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
streamFormat.mFramesPerPacket = 1;
streamFormat.mReserved = 0;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一百个冬季 2024-12-11 02:46:00

AudioQueue 无法同时播放多个声音。它只是从排队缓冲区中一一发送音频数据值。因此,您需要将所有想要同时播放的声音合成为一个。
你怎样才能做到呢?
如果数据没有被压缩,那并不太难。
例如,你有两种不同的声音。您可以将它们中的每一个描述为从 -1 到 1 的浮点值数组。当声音存储在文件中或排队到 audioQueue 中时,它们必须以适当的格式表示。在您的情况下(kAudioFormatLinearPCM,streamFormat.mBitsPerChannel = 16),它是两个字节的整数,每个值表示为从-32767到32767的短整型。
因此,两个声音中的每一个都是一个 Shorts 数组,当您将缓冲区放入队列时,您将用该数组的值填充它(如果声音不是来自文件并且动态生成,则该数组不存在,但值是一一计算的)。
要创建这两个音频文件的“总和”,您应该将每个新数组值构造为
两个声音数组中对应值的平均值。
即 resultSound[i​​] = sound1[i]/2 + sound2[i]/2;
对于任何数量的声音都是一样的。
例如,要生成纯谐波声音,您可以填充缓冲区,例如:

buffer[i] = sin(i * 2 * M_PI * frequency / sampleRate) * 32767;

并混合具有不同频率的两个谐波声音:

buffer[i] = sin(i * 2 * M_PI * frequency1 / sampleRate) + sin(i * 2 * M_PI * frequency2 / sampleRate) * 0.5 * 32767;

AudioQueue can't play multiple sounds simultaneously. It just sends audio data values one by one from enqueued buffer. So you need compose all sounds you want play simultaneously into single one.
How you can do it?
If data are not compressed it is not too hard.
E.g. you have two different sounds. Each of them you can describe as an array of float values from -1 to 1. When sounds stored in file or enqueued to audioQueue they must be represented in appropriate format. In your case (kAudioFormatLinearPCM, streamFormat.mBitsPerChannel = 16) it is two-bytes integers, and each value represented as short int from -32767 to 32767.
Therefore each of two sounds is an array of shorts and when you enqueue buffer you fill it with values of this array (if sound is not from file and generated dynamically this array not exists, but values are calculated one by one).
And to create "sum" of this two audio file you should construct each new array value as
average of corresponding values from two sounds array.
i.e. resultSound[i] = sound1[i]/2 + sound2[i]/2;
And all the same for any number of sounds.
E.g. to generate pure harmonic sound you fill buffer like:

buffer[i] = sin(i * 2 * M_PI * frequency / sampleRate) * 32767;

and to mix two harmonic sounds with different frequencies:

buffer[i] = sin(i * 2 * M_PI * frequency1 / sampleRate) + sin(i * 2 * M_PI * frequency2 / sampleRate) * 0.5 * 32767;
红尘作伴 2024-12-11 02:46:00

请记住,您正在处理单个音频流,因此您要么需要自己创建组合流,要么可以使用混合器单元,它可以让您为其提供多个流。请参阅 Apple 的“音频混合器 (MixerHost)”示例代码。

Remember that you're dealing with a single audio stream, so you either need to create the combined stream yourself, or you could use the mixer unit which will let you feed it multiple streams. See the "Audio Mixer (MixerHost)" sample code from Apple.

巴黎盛开的樱花 2024-12-11 02:45:59

AudioQueue可以同时播放声音。

来自苹果:

如何同时播放多个声音?

使用音频队列服务 (AudioToolbox/AudioQueue.h) 中的接口。为您要播放的每种声音创建一个音频队列对象。然后使用 AudioQueueEnqueueBufferWithParameters 函数指定每个音频队列中第一个音频缓冲区的同时开始时间。

以下限制适用于 iPhone OS 中的同步声音,具体取决于音频数据格式:

AAC、MP3和ALAC(Apple Lossless)音频:您可以同时播放多个AAC、MP3和ALAC格式的声音;播放这些格式的多种声音将需要 CPU 资源进行解码。

线性 PCM 和 IMA/ADPCM(IMA4 音频):您可以同时播放多个线性 PCM 或 IMA4 格式的声音,而无需担心 CPU 资源。

AudioQueue can play sounds at the same time.

from apple:

How do I play multiple sounds simultaneously?

Use the interfaces in Audio Queue Services (AudioToolbox/AudioQueue.h). Create one audio queue object for each sound that you want to play. Then specify simultaneous start times for the first audio buffer in each audio queue, using the AudioQueueEnqueueBufferWithParameters function.

The following limitations pertain for simultaneous sounds in iPhone OS, depending on the audio data format:

AAC, MP3, and ALAC (Apple Lossless) audio: You may play multiple AAC, MP3, and ALAC format sounds simultaneously; playback of multiple sounds of these formats will require CPU resources for decoding.

Linear PCM and IMA/ADPCM (IMA4 audio): You can play multiple linear PCM or IMA4 format sounds simultaneously without CPU resource concerns.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文