iOS 多个音频振荡器

标签 ios objective-c audio core-audio audiounit

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

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;
}

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

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

希望有人能指引我正确的方向

最佳答案

我的答案将是用 C++ 语言,因为我没有 ObjC 能力来从头开始编写它,但你会明白的。

首先,您需要每个信号的相位和频率的单独副本。将它们存储在代表正弦发生器的一个实例的类中是最有意义的。例如

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;
}

关于iOS 多个音频振荡器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25731980/

相关文章:

python - iOS 400 Flask + Zappa 错误请求

ios - 为什么在 VIPER 架构中双向使用协议(protocol)而不是单向使用协议(protocol)

objective-c - 在 iOS5 中使用 Twitter 框架提示登录警报?

ios - CGDataProviderCopyData 在内存中累积导致崩溃

qt - 音频可视化器帮助

windows - 如何使用 NAudio 获取当前使用 powershell 播放音频的应用程序的名称?

c# - 如何创建虚拟音频设备

objective-c - 如何提取 NSArray 的元素并将它们(parseInt)转换为整数值?

objective-c - Block 在 NSDictionary (ARC) 中被释放

objective-c - 如何隐藏iPad的软键盘