我有用于创建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
是一个描述音符及其频率的字典。 melody
是Note
个对象的数组。一切都很好,除了在暂停期间产生奇怪的咔哒声。据我所知,它与采样率有关。但我不知道如何更改我的代码以避免暂停。这是旋律:
https://drive.google.com/open?id=1e03VC90w5WF4QdU-VxrV906dl_c3UvSQ
答案 0 :(得分:5)
如果你的意思是音符之间发出令人不快的咔哒声:那是完全正常的。
即使在专门用于生成音乐的编程语言中,如果您只是在整个持续时间内将块与具有固定振幅的(正弦)波并置,也会出现这种效果。
下面是一个音符结束时的样子草图,下一个音符开始:
除非第一个节点意外地在零结束,否则你会听到这个&#34;跳跃&#34;它绘制在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))
&#34; mollifier&#34;导致加速/衰减的因素。
但是你再次看到音符之间的间隙看起来变得更大,如果你试图让不同音符的音程相交,那么一切都变得相当混乱和复杂,你可能会更好使用编程语言或已经知道如何正确执行的库。我认为Chuck manual包含了一个相当详细的解释,说明如何获得越来越好的发音音符。
答案 1 :(得分:1)
如果我猜测,我认为它可能与音符长度有时甚至不是音符频率的倍数有关。因此,注释的sin(end_time)
有时会导致相对较大的值:32768
,在最坏的情况下。
该频率的音量突然下降可能是你听到的咔哒/咯咯声的原因。
仅当int((volume)*math.sin(freq*math.pi*float(i)/float(SAMPLE_RATE)))
评估为0
附近的值时,才会终止音符,这样可以消除大部分噪音。