用Python裁剪波形顶部

2024-06-12 04:05:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用Python生成音调以写入WAV文件:

def generateTone(note):
    # generates a sine wave in a note's frequency
    tone = []
    framerate = 44100
    noteLookup = {'d':293.665,'a':440,'g':391.995}
    frequency = noteLookup[note]
    for i in range(framerate):
        tone.append(math.sin(2.0*math.pi*float(frequency)*(float(i)/float(framerate))))
    return tone

然而,正如你所料,这些纯正弦波听起来不太悦耳。从我understand来看,“剪掉”这些正弦波的顶部,最好是留下平滑的角点,而不是突然切断,将显著改善这些音调的声音。我们的想法是:

clipped waves
(来源:geofex.com

话说回来,我不知道该怎么做。在

如何设置一个阈值(最好是以一种容易调整的方式)使上面产生的正弦波能够以如图所示的方式被平滑地剪裁?在


Tags: 文件indef方式mathfloatnotefrequency
1条回答
网友
1楼 · 发布于 2024-06-12 04:05:01

最简单的方法是创建一个引入“软剪裁”的映射,值是1:1线性的,直到接近阈值,然后压缩,直到达到某个更大的阈值。在

编辑:这个想法是合理的,但是实现还有一点不尽如人意。我又想了想,换了个更好的。在

目标是使从压缩开始到硬剪裁限制的平滑过渡。线性变换的斜率为1,截断信号的斜率为0。从斜率1转换为斜率0的最干净的方法是使用四分之一的正弦波,因此更新后的函数基于sin。在

from math import *

hard_limit = 32767
linear_limit = 23197  # -3 dB
clip_limit = linear_limit + int(pi/2 * (hard_limit - linear_limit))

def soft_clip(n):
    amplitude, sign = abs(n), 1 if n >= 0 else -1
    if amplitude <= linear_limit:
        return n
    if amplitude >= clip_limit:
        return hard_limit * sign
    scale = hard_limit - linear_limit
    compression = scale * sin(float(amplitude - linear_limit) / scale)
    return (linear_limit + int(compression)) * sign

下面是一个在振幅为40000的正弦波上使用上述方法的示例,背景是未夹持的版本。在

Soft clipping demo

相关问题 更多 >