我目前正在使用python和numpy / scipy实现节拍检测算法。 我基本上需要读取.wav文件并进行处理。这是代码:
sampling_rate, wave_data = scipy.io.wavfile.read(argv[1])
wave_data
是一个1-D numpy数组,有大约441 000个元素(声音为10秒,采样率为44.1 kHz)。现在,我需要对此数组中的每两个元素进行一些基本的数学运算。这就是我现在的做法:
wave_data = [sampling_rate * (wave_data[i+1] - wave_data[i])
for i in xrange(len(wave_data)-1)]
这种操作需要花费太多时间(没有分析时会很明显)。我需要“就地”成对映射数组,而不创建新的python列表。我知道有numpy.vectorize
,但我不知道如何成对地进行映射(映射数组的每两个元素)。
答案 0 :(得分:4)
以下任何一种情况都可以:
wave_date = sampling_rate * np.diff(wave_data)
或
wave_date = sampling_rate * (wave_data[1:] - wave_data[:-1])
例如:
In [7]: sampling_rate = 2
In [8]: wave_data = np.array([1, 3, 5, 2, 8, 10])
In [9]: sampling_rate * (wave_data[1:] - wave_data[:-1])
Out[9]: array([ 4, 4, -6, 12, 4])
就性能而言,这两种方法都比列表理解快约500倍:
In [16]: wave_data = np.array([1., 3, 5, 2, 8, 10, 5, 2, 4, 7] * 44100)
In [17]: %timeit sampling_rate * np.diff(wave_data)
100 loops, best of 3: 2.2 ms per loop
In [18]: %timeit sampling_rate * (wave_data[1:] - wave_data[:-1])
100 loops, best of 3: 2.15 ms per loop
In [19]: %timeit [sampling_rate * (wave_data[i+1] - wave_data[i]) for i in xrange(len(wave_data)-1)]
1 loops, best of 3: 970 ms per loop