Audio 无混叠伪影的采样波形的高效生成

Audio 无混叠伪影的采样波形的高效生成,audio,signal-processing,sampling,waveform,Audio,Signal Processing,Sampling,Waveform,对于我的一个项目,我正在使用采样声音生成,我需要在不同频率下创建各种波形。当波形为正弦时,一切正常,但当波形为矩形时,就会出现问题:它听起来好像来自80年代,随着频率的增加,音符听起来就错了。在第八个八度音阶上,每个音符听起来都像是某个较低八度的随机音符 无论我是否使用以下两种方法之一,不良效果都是相同的: 生成矩形波形的纯数学方法为sample=sign(secondsPerHalfWave-(timeSeconds%secondsPerWave))其中secondsPerWave=1.0/

对于我的一个项目,我正在使用采样声音生成,我需要在不同频率下创建各种波形。当波形为正弦时,一切正常,但当波形为矩形时,就会出现问题:它听起来好像来自80年代,随着频率的增加,音符听起来就错了。在第八个八度音阶上,每个音符听起来都像是某个较低八度的随机音符

无论我是否使用以下两种方法之一,不良效果都是相同的:

  • 生成矩形波形的纯数学方法为
    sample=sign(secondsPerHalfWave-(timeSeconds%secondsPerWave))
    其中
    secondsPerWave=1.0/wavesPerSecond
    secondsPerHalfWave=secondsPerWave/2.0

  • 我比较喜欢的方法是,用线段来描述波的一个周期,并沿着这些线段进行插值。因此,矩形波形由y=1.0时x=0到x=0.5的水平线描述(与采样率和频率无关),然后是y=-1.0时x=0.5到x=1.0的另一条水平线

从我收集的资料来看,文献认为这些波形生成方法“幼稚”,导致“混叠”,这是所有不良影响的原因

当我观察生成的波形时,这一切实际上转化为每秒采样数不是每秒波数的精确倍数,因此每个波的采样数不是偶数,这反过来意味着1.0级的样本数量通常不等于-1.0级的样本数量

我在这里找到了一个特定的解决方案:它甚至包括Java的源代码,听起来确实很棒:所有不受欢迎的效果都消失了,每个音符听起来都很纯净,频率也很合适。然而,这个解决方案完全不适合我,因为它在计算上非常昂贵。(即使在我用比Java内置函数快十倍的近似值替换了
sin()
cos()
之后。)此外,当我看到生成的波形时,它们看起来非常复杂,所以我想知道它们是否可以被合理地称为矩形

所以,我的问题是: 生成周期性波形(如矩形波形)的计算效率最高的方法是什么

解决方案可能包含的示例:
  • 在我看来,以离散的时间间隔生成正确的样本值来描述声波的计算机音频问题似乎与以离散的整数x坐标生成正确的整数y坐标以绘制直线的计算机图形学问题有些关联。Bresenham直线生成算法非常高效(即使我们暂时不考虑它使用整数数学的事实),并且它通过累积某个误差项来工作,该误差项在适当的时候会导致Y坐标的起伏。是否可以使用类似的机制来计算样本值

  • 采样的工作方式被理解为在特定的、无限窄的时间点读取模拟信号的值。也许更好的方法是考虑在最后一个样本和当前样本之间读取模拟信号的整个切片的面积。这样,在矩形波形边缘之前采样1.0会对采样值产生一点影响,而在边缘之后采样-1.0相当长的时间会产生很大影响,因此自然会产生一个介于两个极值之间的点。这能解决问题吗?这样的算法存在吗?有人试过吗

  • 请注意,我在这里发布了这个问题,而不是dsp.stackexchange.com,因为我不想用荒谬的行话来回答这个问题,比如频带限制、谐波和低通滤波器、拉格朗日插值、直流补偿、,我不希望答案来自纯粹的模拟世界或纯粹的理论外层空间,也不希望有任何机会使用数字计算机得到切实有效的实现


    我是一个程序员,而不是一个声音工程师,在我的小程序员的世界里,事情很简单:我有一个样本数组,所有样本都必须在-1.0和1.0之间,并且将以一定的速率播放(每秒44100个样本)。我有算术运算和三角函数供我使用,我可以描述直线,使用简单的线性插值,我需要非常高效地生成样本,因为同时生成十几个波形以及将它们混合在一起可能不会消耗超过总CPU时间的1%。

    我不确定,但您可能对混叠的性质有一些误解。我是根据你引用的术语,并从以下引用:

    当我看到生成的 波形是指每秒采样数的值不是精确的倍数 每秒波数的值,所以每个波没有偶数 样本数,这反过来意味着 级别1.0通常不等于级别-1.0的样本数

    采样/秒和波/秒根本不必是精确的倍数!一个人可以在奈奎斯特下重放所有投球。所以我不清楚你是怎么想的

    方波的特征声音来自奇数谐波的存在,例如,对于440(A5)音符,方波声音可以通过组合440、1320、2200、3080、3960等正弦以880的增量产生。这就引出了一个问题:有多少个奇次谐波?从理论上讲,我们可以到无穷大
    int main() {
        UserData ud;
        sp_data *sp;
        sp_create(&sp);
        sp_ftbl_create(sp, &ud.ft, 2048);
        sp_osc_create(&ud.osc);
    
        sp_gen_sine(sp, ud.ft);
        sp_osc_init(sp, ud.osc, ud.ft);
        ud.osc->freq = 500;
        sp->len = 44100 * 5;
        sp_process(sp, &ud, write_osc);
    
        sp_ftbl_destroy(&ud.ft);
        sp_osc_destroy(&ud.osc);
        sp_destroy(&sp);
        return 0;
    }