Numpy 合成声音

合成声音,声音在数学上可以表示为具有特定幅度、频率和相位的正弦波。我们可以从维基百科页面http://en.wikipedia.org/wiki/Piano_key_frequencies提供的列表中随机地选择频率。这些频率值是用如下公式得到的。

合成声音段

上式中的变量n是钢琴中的琴键编号,其取值范围是1~88。幅度、持续时间和相位参数将随机选取。

具体步骤

首先将初始化随机变量,再生成正弦波,然后谱曲,最后用Matplotlib绘制生成的声音数据。

  1. 初始化。

随机变量的初始化:

  • 幅度值在200到2000之间
  • 持续时间在0.01到0.2之间
  • 用上述公式选择频率
  • 初始相位值在0到2π之间
  • NTONES = int(sys.argv[1])
amps = 2000. * numpy.random.random
  ((NTONES,)) + 200.
durations = 0.19 * numpy.random.random 
  ((NTONES,)) + 0.01
keys = numpy.random.random_integers 
  (1, 88, NTONES)
freqs = 440.0 * 2 ** ((keys - 49.)/12.)
phi = 2 * numpy.pi * numpy.random.random((NTONES,))

  1. 生成正弦波。

编写generate函数,用来生成正弦波。

def generate(freq, amp, duration, phi):
t = numpy.linspace 
   (0, duration, duration * RATE)
data = numpy.sin(2 * numpy.pi *  
   freq * t + phi) * amp


return data.astype(DTYPE)

  1. 谱曲。

生成数个声调后,我们需要谱写一段连贯的旋律。我们暂时只是把各个正弦波连接在一起。这不会生成一段好听的旋律,但可以作为一个起点,以后可以做更多的尝试。

for i in xrange(NTONES):
   newtone = generate(freqs[i], amp=amps[i],  
   duration=durations[i], phi=phi[i])
tone = numpy.concatenate((tone, newtone))

  1. 绘制数据。

用Matplotlib绘制合成的声音数据。

matplotlib.pyplot.plot(numpy.linspace (0, len(tone)/RATE, len(tone)), tone)
matplotlib.pyplot.show()

合成的声音数据如下图所示:
合成声音段

本攻略的完整代码如下。

import scipy.io.wavfile
import numpy
import sys
import matplotlib.pyplot

RATE = 44100
DTYPE = numpy.int16

# 生成正弦波
def generate(freq, amp, duration, phi):
 t = numpy.linspace(0, duration, duration * RATE)
 data = numpy.sin(2 * numpy.pi * freq * t + phi) * amp

 return data.astype(DTYPE)

if len(sys.argv) != 2:
   print "Please input the number of tones to generate"
   sys.exit()

# 初始化
NTONES = int(sys.argv[1])
amps = 2000. * numpy.random.random((NTONES,)) + 200.
durations = 0.19 * numpy.random.random((NTONES,)) + 0.01
keys = numpy.random.random_integers(1, 88, NTONES)
freqs = 440.0 * 2 ** ((keys - 49.)/12.)
phi = 2 * numpy.pi * numpy.random.random((NTONES,))

tone = numpy.array([], dtype=DTYPE) 

# 谱曲 
for i in xrange(NTONES):
   newtone = generate(freqs[i], amp=amps[i], duration=durations[i], phi=phi[i])
   tone = numpy.concatenate((tone, newtone))

scipy.io.wavfile.write('generated_tone.wav', RATE, tone)

# 绘制声音数据
matplotlib.pyplot.plot(numpy.linspace(0, len(tone)/RATE, len(tone)), tone)
matplotlib.pyplot.show()

攻略小结

我们用随机生成的声音创建了一个WAV文件。concatenate函数用来把各个正弦波连接起来。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程