iOS多音频振荡器

时间:2014-09-08 19:45:35

标签: ios objective-c audio core-audio audiounit

刚开始使用iOS AudioUnit框架学习和测试,并在总线0中创建了一个带有渲染回调函数的多声道混音器。在回调函数中,我合成了如下声音:

OSStatus RenderTone(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const     AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList   *ioData) {
    const double amplitude = 0.5;

    iPadAudioViewController *viewController = (__bridge iPadAudioViewController *)inRefCon;

    double phase = viewController->phase;
    double phase_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;
    const int channel = 0;
    Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData;

    for (UInt32 frame = 0; frame < inNumberFrames; frame++) {
        buffer[frame] = sin(phase) * amplitude;

        phase += phase_increment;
        if (phase > 2.0 * M_PI) {
            phase -= 2.0 * M_PI;
        }
    }

    viewController->phase = phase;

    return noErr;
}

如果我想在多通道混音器的可变数量的其他总线中合成具有不同相位/频率等的更多声音,该怎么办?

我还没有在Google或iOS文档中找到有关此内容的任何信息。

希望有人能让我朝着正确的方向前进

1 个答案:

答案 0 :(得分:1)

我的答案是在C ++中,因为我没有从头开始编写ObjC,但你会明白这一点。

首先,您需要为每个信号单独复制相位和频率。将这些存储在表示正弦生成器的一个实例的类中是最有意义的。 e.g。

class SineGen
{
private:
    double frequency;
    double phase;

public:
    void Generate(Float32* pBuffer, int numFrames)
    {
        for (UInt32 frame = 0; frame < inNumberFrames; frame++) {
            buffer[frame] = sin(phase) * amplitude;

            phase += phase_increment;
            if (phase > 2.0 * M_PI) {
                phase -= 2.0 * M_PI;
            }
        }
    }
};

RenderTone函数中,您需要将每个正弦生成器运行到一个临时缓冲区中,然后按元素求和它们。最后,您需要将其分解以将其恢复到范围内。

OSStatus RenderTone(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const     AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList   *ioData) {
    const double amplitude = 0.5;

    Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData;
    Float32 *tmp1 = new Float32[inNumberFrames];
    Float32 *tmp2 = new Float32[inNumberFrames];

    viewController->sineGen1->Generate(tmp1, inNumberFrames);
    viewController->sineGen2->Generate(tmp2, inNumberFrames);

    for (UInt32 frame = 0; frame < inNumberFrames; frame++) {
        buffer[frame] = amplitude * (tmp1[frame] + tmp2[frame]) / 2.0;

    return noErr;
}