【问题标题】:Writing wav file gives clicking sounds写入 wav 文件会发出点击声
【发布时间】:2018-05-30 20:08:59
【问题描述】:

我有这个用于创建 wav 文件的代码:

class Note:
    def __init__(self,name,octave,duration):
        self.name = name
        self.octave = octave
        self.duration = duration

SAMPLE_RATE = 44100

wav = wave.open("starw.wav", mode="w")
wav.setparams((1, 2, SAMPLE_RATE , SAMPLE_RATE*4, 'NONE', 'noncompressed'))

def generate_sample(note,volume):
    freq = FREQUENCIES[note.octave][note.name]
    duration = note.duration
    total_samples = int(SAMPLE_RATE * duration)
    for i in range(0,total_samples):
        s = np.clip(int((volume)*math.sin(freq*math.pi*float(i)/float(SAMPLE_RATE))),-32768,32768)    
        data = struct.pack('<h',s)
        wav.writeframes(data)

    return data

for i,m in enumerate(melody):

    if i<len(melody)/5:
        generate_sample(m, 100+i*500)
    elif len(melody)/5<=i<=4*len(melody)/5:
        generate_sample(m, 8800)
    else:
        generate_sample(m, 8800-i*20)

这里的FREQUENCIES 是一个描述音符及其频率的字典。 melodyNote 对象的数组。一切正常,除了在暂停期间会产生奇怪的点击声。据我了解,它与采样率有关。但我不知道如何更改我的代码以避免暂停。这是旋律: https://drive.google.com/open?id=1e03VC90w5WF4QdU-VxrV906dl_c3UvSQ

【问题讨论】:

  • 可能是许多音符开始/结束时的咔嗒声?
  • 是的,我的意思是点击。

标签: python wav


【解决方案1】:

如果您指的是音符之间令人不快的咔嗒声:那是完全正常的。

即使在专门为生成音乐而设计的编程语言中,如果您只是将块与在整个持续时间内具有固定幅度的(正弦)波并列,就会出现这种效果。

这是一个音符结束,下一个音符开始时的示意图:

除非第一个节点意外恰好在零处结束,否则您将听到绘制在2 处的这种“跳跃”。

为了避免这种情况,您必须实现更好的音符合成。

一个简单的解决方案是平滑地提升每个音符的幅度,然后让它平滑地衰减到最后。如果您这样做,两个音符之间的过渡将如下所示:

此图由以下公式生成:

  if x > 2:
    return sin((x-2) * 60) * (1 - exp(-(x-2)**2 / 0.5))
  else:
    return sin(x * 30) * (1- exp(-(x-2)**2 / 0.5))

希望您能识别出导致上升/衰减的(1 - exp(-(x - tClick) ** 2 / smoothness))“缓和剂”因素。

但是你又一次看到音符之间的间隔似乎变大了,如果你试图让不同音符的间隔相交,这一切都会变得相当混乱和复杂,你可能会更好已经知道如何正确执行的编程语言或库。我认为Chuck manual 包含了关于如何获得越来越好发声的音符的相当详细的解释。

【讨论】:

  • 除了您提到的两种方法(淡出音符并稍微扩展它们)之外,您还可以计算下一个音符的相位,使其以与上一个音符结尾相同的幅度开始。
【解决方案2】:

如果我猜测的话,我认为这可能与音符长度有时甚至不是音符频率的倍数有关。因此,注释的sin(end_time) 有时可能会导致相对较大的值:在最坏的情况下为32768。 该频率的音量突然下降可能是您听到咔哒声/咯咯声的原因。

仅当int((volume)*math.sin(freq*math.pi*float(i)/float(SAMPLE_RATE))) 的计算结果接近0 时才终止注释,这样可以消除大部分噪音。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 2013-05-22
    • 2023-03-21
    • 2014-04-27
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    相关资源
    最近更新 更多