通过 AUGraph 连接的 iOS 波形发生器

Posted

技术标签:

【中文标题】通过 AUGraph 连接的 iOS 波形发生器【英文标题】:iOS waveform generator connected via AUGraph 【发布时间】:2014-01-24 12:43:33 【问题描述】:

我创建了一个连接到 AUGraph 的简单波形发生器。我重用了 Apple 的一些示例代码来设置 AudiostreamBasicDescription 像这样

void    SetCanonical(UInt32 nChannels, bool interleaved)
            // note: leaves sample rate untouched

    mFormatID = kAudioFormatLinearPCM;
    int sampleSize = SizeOf32(AudioSampleType);
    mFormatFlags = kAudioFormatFlagsCanonical;
    mBitsPerChannel = 8 * sampleSize;
    mChannelsPerFrame = nChannels;
    mFramesPerPacket = 1;
    if (interleaved)
        mBytesPerPacket = mBytesPerFrame = nChannels * sampleSize;
    else 
        mBytesPerPacket = mBytesPerFrame = sampleSize;
        mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
    

在我的课堂上我称之为这个函数

mClientFormat.SetCanonical(2, true);
mClientFormat.mSampleRate = kSampleRate;

当采样率是

#define kSampleRate     44100.0f;

其他设置也取自示例代码

// output unit
CAComponentDescription output_desc(kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple);

// iPodEQ unit
CAComponentDescription eq_desc(kAudioUnitType_Effect, kAudioUnitSubType_AUiPodEQ, kAudioUnitManufacturer_Apple);

// multichannel mixer unit
CAComponentDescription mixer_desc(kAudioUnitType_Mixer, kAudioUnitSubType_MultiChannelMixer, kAudioUnitManufacturer_Apple);

一切正常,但问题是当我尝试到达第二个缓冲区时,我没有收到立体声并且我的回调函数失败(访问错误)

Float32 *bufferLeft = (Float32 *)ioData->mBuffers[0].mData;
Float32 *bufferRight = (Float32 *)ioData->mBuffers[1].mData;

// Generate the samples
for (UInt32 frame = 0; frame < inNumberFrames; frame++)

    switch (generator.soundType) 

        case 0: //Sine

            bufferLeft[frame] = sinf(thetaLeft) * amplitude;
            bufferRight[frame] = sinf(thetaRight) * amplitude;
            break;

所以看来我得到的是单声道而不是立体声。指针 bufferRight 为空,但不知道为什么。 任何帮助将不胜感激。

【问题讨论】:

碰巧我在浏览器中打开了这两个标签:SCWaveformView。也许其他人偶然发现了您的问题,只是想要一个工作波形图作为库;) 【参考方案1】:

我可以看到两个可能的错误。首先,正如@invalidname 指出的那样,立体声录音可能不适用于 iPhone 等单声道设备。好吧,它可能会起作用,但如果确实如此,那么无论如何你都会得到双单声道立体声流,那何必呢?您不妨将流配置为以单声道工作并节省自己的 CPU 开销。

第二个问题可能是你的声音失真的来源。您的流描述格式标志应该是:

kAudioFormatFlagIsSignedInteger |
kAudioFormatFlagsNativeEndian |
kAudioFormatFlagIsPacked

另外,不要忘记将 mReserved 标志设置为 0。虽然此标志的值可能会被忽略,但为了确保安全,将其显式设置为 0 并没有什么坏处。

编辑:在 iPhone 上调试音频的另一个更通用的技巧 - 如果您遇到失真、削波或其他奇怪的效果,请从手机中获取数据负载并在波形编辑器中查看录音。能够缩小并查看单个样本将为您提供很多关于问题所在的线索。

为此,您需要打开“管理器”窗口,点击您的手机,然后展开您的应用程序旁边的小箭头(在您通常卸载它的同一位置)。现在您将看到一个向下的箭头,如果您单击它,Xcode 会将数据有效负载从您的应用程序复制到硬盘上的某个位置。如果您要将录音转储到磁盘,您会在此处找到提取的文件。

来自link的参考

【讨论】:

我需要立体声,因为我为每个通道设置了不同的频率。我可以使用“AudioComponentInstance”来做到这一点,但到那时我很可能需要建立自己的均衡器,这可以通过 AUGraph 更轻松地完成。【参考方案2】:

我猜问题是您指定的是交错格式,但随后访问缓冲区就像它们在 IO 回调中是非交错的一样。 ioData->mBuffers[1] 无效,因为左右通道的所有数据都交错在 ioData->mBuffers[0].mData 中。检查 ioData->mNumberBuffers。我的猜测是它设置为 1。另外,请验证 ioData->mBuffers[0].mNumberChannels 设置为 2,这表示交错数据。

还可以查看 Core Audio 公共实用程序类,以帮助设置格式等。让它变得容易多了。您设置格式的代码可以减少到一行,并且您会更有信心它是正确的(尽管在我看来您的格式设置正确 - 如果您想要的是交错的 16 位 int):

CAStreamBasicDescription myFormat(44100.0, 2, CAStreamBasicDescription::kPCMFormatInt16, true)

Apple 曾经将这些类打包到随 Xcode 一起安装的 SDK 中,但现在您需要在此处下载它们:https://developer.apple.com/library/mac/samplecode/CoreAudioUtilityClasses/Introduction/Intro.html

无论如何,看起来最简单的解决方法就是将格式更改为非交错。所以在你的代码中:mClientFormat.SetCanonical(2, false);

【讨论】:

我试过了,好像不行。但无论如何还是谢谢。

以上是关于通过 AUGraph 连接的 iOS 波形发生器的主要内容,如果未能解决你的问题,请参考以下文章

连接节点错误 kAudioUnitErr_PropertyNotWriteable 时 AudioToolbox AUGraph 失败

基于51单片机的波形发生器

基于51单片机的波形发生器

AUGraph 正弦波损坏

AUGraph 在 iOS 上被弃用了吗?如果是这样,啥时候?

ios 5.0 中的 ios AUGraph 音高偏移