4

我目前正在使用 python 和 numpy/scipy 实现节拍检测算法。我基本上需要读取一个 .wav 文件并对其进行处理。这是代码:

sampling_rate, wave_data = scipy.io.wavfile.read(argv[1])

wave_data是一个一维 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,但我不知道如何成对进行映射(映射数组的每两个元素)。

4

1 回答 1

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
于 2013-02-03T13:05:02.883 回答