1 #! /usr/bin/env python
3 import numpy as np
4 from aubio import pitch
5 import pylab as plt
7 buf_size = 2048 * 1
8 hop_size = buf_size // 4
10 samplerate = 44100
11 minfreq = 40
12 maxfreq = 6000
14 def sinewave(freq, duration, samplerate = samplerate):
15     """ generate a sinewave """
16     length = hop_size
17     while length < duration * samplerate:
18         length += hop_size
19     return np.sin( 2. * np.pi * np.arange(length) * freq / samplerate ).astype("float32")
21 def get_stats_for_pitch_method(method, freqs, samplerate = samplerate):
22     """ for a given pitch method and a list of frequency, generate a sinewave
23     and get mean deviation """
24     means = np.zeros(len(freqs))
25     medians = np.zeros(len(freqs))
26     for freq, fn in zip(freqs, range(len(freqs))):
27         s = sinewave(freq, .50).reshape(-1, hop_size)
28         #s = (sinewave(freq, .50) + .0*sinewave(freq/2., .50)).reshape(-1, hop_size)
29         p = pitch(method, buf_size, hop_size, samplerate = samplerate)
30         candidates = np.zeros(len(s))
31         #samples = np.zeros(buf_size)
32         for frame, i in zip(s, range(len(s))):
33             candidates[i] = p(frame)
34         # skip first few candidates
35         candidates = candidates[4:]
36         means[fn] = np.mean(candidates[candidates != 0] - freq)
37         medians[fn] = np.median(candidates[candidates != 0] - freq)
38         print (freq, means[fn], medians[fn])
39     return means, medians
41 if __name__ == '__main__':
42     freqs = np.arange(minfreq, maxfreq, 1.)
43     modes = ["yin", "yinfft"]
44     for mode in modes:
45         means, medians = get_stats_for_pitch_method(mode, freqs)
46         plt.figure()
47         plt.plot(freqs, means, 'g-')
48         plt.plot(freqs, medians, 'r--')
49         #plt.savefig(mode + '_deviations_test.png', dpi=300)
50         plt.show()