制定振荡器波形代码并创建新的波形

发布于 2025-01-03 22:10:24 字数 1354 浏览 1 评论 0原文

我想编写一些在我的音调生成器应用程序中生成振荡器波形类型的代码。本例中的波是正弦波,有人可以告诉我代码是如何工作的吗,因为我想在将来制作自定义波类型以及方形、锯齿和三角形类型。

OSStatus RenderTone(
    void *inRefCon, 
    AudioUnitRenderActionFlags  *ioActionFlags, 
    const AudioTimeStamp        *inTimeStamp, 
    UInt32                      inBusNumber, 
    UInt32                      inNumberFrames, 
    AudioBufferList             *ioData)

{
    // Fixed amplitude is good enough for our purposes
    const double amplitude = 0.25;

    // Get the tone parameters out of the view controller
    ToneGeneratorViewController *viewController =
        (ToneGeneratorViewController *)inRefCon;
    double theta = viewController->theta;
    double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;

    // This is a mono tone generator so we only need the first buffer
    const int channel = 0;
    Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData;

     // Generate the samples
     for (UInt32 frame = 0; frame < inNumberFrames; frame++) 
    {
        buffer[frame] = sin(theta) * amplitude;

        theta += theta_increment;
        if (theta > 2.0 * M_PI)
        {
             theta -= 2.0 * M_PI;
        } 
    }

    // Store the theta back in the view controller
    viewController->theta = theta;

    return noErr;

}

I want to work out a bit of code that generates the oscillator wave-type in my tone generator app. The one in this example is a sine-wave, can someone tell me how the code works, as i want to in the future make custom wave-types and square, sawtooth and triangle types.

OSStatus RenderTone(
    void *inRefCon, 
    AudioUnitRenderActionFlags  *ioActionFlags, 
    const AudioTimeStamp        *inTimeStamp, 
    UInt32                      inBusNumber, 
    UInt32                      inNumberFrames, 
    AudioBufferList             *ioData)

{
    // Fixed amplitude is good enough for our purposes
    const double amplitude = 0.25;

    // Get the tone parameters out of the view controller
    ToneGeneratorViewController *viewController =
        (ToneGeneratorViewController *)inRefCon;
    double theta = viewController->theta;
    double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;

    // This is a mono tone generator so we only need the first buffer
    const int channel = 0;
    Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData;

     // Generate the samples
     for (UInt32 frame = 0; frame < inNumberFrames; frame++) 
    {
        buffer[frame] = sin(theta) * amplitude;

        theta += theta_increment;
        if (theta > 2.0 * M_PI)
        {
             theta -= 2.0 * M_PI;
        } 
    }

    // Store the theta back in the view controller
    viewController->theta = theta;

    return noErr;

}

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

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

发布评论

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

评论(2

红玫瑰 2025-01-10 22:10:24

正在生成实际的正弦波样本,并填充下面代码片段中的缓冲区

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

    theta += theta_increment;
    if (theta > 2.0 * M_PI)
    {
         theta -= 2.0 * M_PI;
    } 
}

在分配 buffer[frame] 的行中,您正在调用 sin(theta) * 振幅code>,并且对于 for 循环的每次迭代,您都会根据频率和采样率将 theta 增加一些有限的步长,通过

double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;

这本质上是除以 >2.0 * PI * 频率 by你的采样率。

在循环 for 循环时增加 theta 变量基本上是一次推进一个样本的时间步,直到缓冲区已满(即 frame == iNumberFrames< /代码>)。

如果您想生成除正弦波之外的其他波,只需将以下行替换为其他函数:

buffer[frame] = sin(theta) * amplitude;

也就是说,例如,您想要收敛为三角波的无限傅里叶级数中的前三项;然后你可能会得到以下内容......

buffer[frame] = (8 / pow(M_PI,2)) * (sin(theta) - sin(3*theta)/9 + sin(5*theta)/25);

The actual sine wave samples are being generated and are populating the buffer in the snippet below

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

    theta += theta_increment;
    if (theta > 2.0 * M_PI)
    {
         theta -= 2.0 * M_PI;
    } 
}

In the line where buffer[frame] is being assigned, you are calling sin(theta) * amplitude, and for each iteration of the for loop, you are incrementing theta by some finite step size based on your frequency and sample rate, via

double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;

Which is essentially dividing 2.0 * PI * frequency by your sample rate.

Incrementing the theta variable while looping through the for loop is basically advancing the time step one sample at a time until your buffer is full (i.e. frame == iNumberFrames).

If you wanted to generate something other than a sine wave, you would simply replace the following line with some other function:

buffer[frame] = sin(theta) * amplitude;

I.e. let's say, for example, you wanted the first three terms in the infinite Fourier series that converges to a triangle wave; you might then have the following instead...

buffer[frame] = (8 / pow(M_PI,2)) * (sin(theta) - sin(3*theta)/9 + sin(5*theta)/25);
丑丑阿 2025-01-10 22:10:24

要产生所需的波形,您需要将 sin() 函数替换为产生所需波形的函数。

您也许能够在带有图形示例的函数表中找到此函数,或者您可能必须创建自己的函数。创建函数近似的方法有很多,包括多项式、傅立叶级数、带或不带插值的查表、递归等。但这本身就是一个大主题(许多教科书等)

To produce your desired waveform, you need to replace the sin() function with a function that produces your desired wave shape.

You might be able to find this function in a table of functions with graphical examples, or you might have to create your function. The are lots of ways to create a functional approximation, including polynomial, Fourier series, table lookup with or without interpolation, recursions, and etc. But that is a big subject on its own (many textbooks, etc.)

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