在Python中剪切波形顶部

时间:2014-04-25 05:01:59

标签: python audio

我在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 http://www.geofex.com/effxfaq/d101_02.gif

话虽如此,我不知道如何处理。

如何设置(最好是以易于调整的方式)一个阈值,在该阈值下,上面生成的正弦波将以图中所示的方式平滑地剪切?

1 个答案:

答案 0 :(得分:3)

最简单的方法是使用一个引入“软剪辑”的映射 - 这些值在它们接近阈值之前是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