5

我正在为 Unity 引擎中的音频过滤器创建一个 C# 脚本。

我的问题是,在通过我的过滤器运行后,生成的音频具有一致且频繁的“点击”、“弹出”或“跳过”。听起来有点像老式收音机。
我不确定是什么原因造成的。

这是我的代码:

public float cutoff;
public float resonance;

int sampleRate;

void Start()
{
    cutoff = 200;
    resonance = 1;

    sampleRate = AudioSettings.outputSampleRate;
}

void OnAudioFilterRead(float[] data, int channels)
{
    float c = 2 * Mathf.PI * cutoff/sampleRate;
    float r = 1 / resonance;

    float v0 = 0;
    float v1 = 0;

    for (int i = 0; i < data.Length; i++)
    {
        v0 =  (1 - r * c) * v0  -  (c) * v1  + (c) * data[i];
        v1 =  (1 - r * c) * v1  +  (c) * v0;

        data[i] = v1;
    }
}

这是OnAudioFilterRead()的文档。
这是我得到原始低通代码的地方。

随着截止值接近其最大值 (127),咔嗒声和爆破声变得更安静。

我对音频编程相当​​陌生,这可能很明显,所以我不确定是什么原因造成的。
比我更有知识的人可以解释我做错了什么吗?

谢谢!

4

2 回答 2

3

点击和弹出的常见原因(按“常见”顺序)是:

  • 缓冲区长度错误(您与缓冲区重叠或未能将其填充到边界)
  • 您的样本正在裁剪,并且您没有按应有的方式处理它 - 例如,您正在计算shorts 中的所有内容,并且不关心包装值
  • 您的 DSP 算法表现不佳
  • 您的算法由于某种原因太慢,并且音频样本未及时交付,导致音频间隙

一种很好的调试技术是尝试缩小问题的原因,例如,直接在处理音频的例程中插入 PCM 转储。这样,您将知道例程的输出是否正常,并能够相应地集中调试工作。

于 2012-10-20T16:55:03.663 回答
3

我已经解决了。我的 c 和 r 变量需要在调用 OnAudioFilterRead() 的过程中保持不变。让他们成员修复它。这是我完整的工作代码:

using UnityEngine;
using System.Collections;
using System;

public class LowPassFilter : MonoBehaviour {

    public float cutoff;
    public float resonance;

    const float CUTOFF_MAX = 128.0f;
    const float CUTOFF_MIN = 0.0f;
    const float RESONANCE_MAX = 128.0f;
    const float RESONANCE_MIN = 0.0f;

    float c;
    float r;
    float v0;
    float v1;

    int sampleRate;

    void Start()
    {
        cutoff = 20.0f;
        resonance = 0.0f;

        c = 0.0f;
        r = 0.0f;
        v0 = 0.0f;
        v1 = 0.0f;

        sampleRate = AudioSettings.outputSampleRate;
    }

    void OnAudioFilterRead(float[] data, int channels)
    {
        cutoff = Mathf.Clamp(cutoff, CUTOFF_MIN, CUTOFF_MAX);
        resonance = Mathf.Clamp(resonance, RESONANCE_MIN, RESONANCE_MAX);

        c = Mathf.Pow(0.5f, (128.0f - cutoff) / 16.0f);
        r = Mathf.Pow(0.5f, (resonance + 24.0f) / 16.0f);

        for (int i = 0; i < data.Length; i++)
        {
            v0 =  ((1.0f - r * c) * v0)  -  (c * v1)  + (c * data[i]);
            v1 =  ((1.0f - r * c) * v1)  +  (c * v0);

            data[i] = Mathf.Clamp(v1, -1.0f, 1.0f);
        }
    }
}
于 2012-10-25T00:50:45.070 回答