iOS波形发生器通过AUGraph连接

时间:2014-01-24 12:43:33

标签: c++ iphone objective-c core-audio audiounit

我创建了一个连接到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为空,但不知道原因。 任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

我可以看到两个可能的错误。首先,正如@invalidname指出的那样,立体声录音可能无法在iPhone等单声道设备上运行。嗯,它可能会起作用,但如果确实如此,那么你只需要取回双单声道立体声流,那么为什么呢?您也可以将流配置为单声道工作,并节省CPU开销。

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

kAudioFormatFlagIsSignedInteger |
kAudioFormatFlagsNativeEndian |
kAudioFormatFlagIsPacked

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

编辑:在iPhone上调试音频的另一个更一般的提示 - 如果您遇到失真,剪辑或其他奇怪的效果,请从手机中获取数据有效负载并在波形编辑器中查看录制内容。能够缩小并查看单个样本将为您提供很多关于出错的线索。

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

来自link

的参考资料

答案 1 :(得分:0)

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

另请查看Core Audio Public Utility类以帮助设置格式等内容。使它变得如此简单。您设置格式的代码可以减少到一行,并且您更有信心它是正确的(虽然对我来说你的格式看起来设置正确 - 如果你想要的是交错的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);