1 | #! /usr/bin/env python |
---|
2 | |
---|
3 | import sys |
---|
4 | from aubio import pvoc, source |
---|
5 | from numpy import array, arange, zeros, shape, log10, vstack |
---|
6 | from pylab import imshow, show, cm, axis, ylabel, xlabel, xticks, yticks |
---|
7 | |
---|
8 | def get_spectrogram(filename): |
---|
9 | samplerate = 44100 |
---|
10 | win_s = 512 # fft window size |
---|
11 | hop_s = win_s / 2 # hop size |
---|
12 | fft_s = win_s / 2 + 1 # spectrum bins |
---|
13 | |
---|
14 | a = source(filename, samplerate, hop_s) # source file |
---|
15 | pv = pvoc(win_s, hop_s) # phase vocoder |
---|
16 | specgram = zeros([0, fft_s], dtype='float32') # numpy array to store spectrogram |
---|
17 | |
---|
18 | # analysis |
---|
19 | while True: |
---|
20 | samples, read = a() # read file |
---|
21 | specgram = vstack((specgram,pv(samples).norm)) # store new norm vector |
---|
22 | if read < a.hop_size: break |
---|
23 | |
---|
24 | # plotting |
---|
25 | imshow(log10(specgram.T + .001), origin = 'bottom', aspect = 'auto', cmap=cm.gray_r) |
---|
26 | axis([0, len(specgram), 0, len(specgram[0])]) |
---|
27 | # show axes in Hz and seconds |
---|
28 | time_step = hop_s / float(samplerate) |
---|
29 | total_time = len(specgram) * time_step |
---|
30 | print "total time: %0.2fs" % total_time, |
---|
31 | print ", samplerate: %.2fkHz" % (samplerate / 1000.) |
---|
32 | n_xticks = 10 |
---|
33 | n_yticks = 10 |
---|
34 | |
---|
35 | def get_rounded_ticks( top_pos, step, n_ticks ): |
---|
36 | top_label = top_pos * step |
---|
37 | # get the first label |
---|
38 | ticks_first_label = top_pos * step / n_ticks |
---|
39 | # round to the closest .1 |
---|
40 | ticks_first_label = round ( ticks_first_label * 10. ) / 10. |
---|
41 | # compute all labels from the first rounded one |
---|
42 | ticks_labels = [ ticks_first_label * n for n in range(n_ticks) ] + [ top_label ] |
---|
43 | # get the corresponding positions |
---|
44 | ticks_positions = [ ticks_labels[n] / step for n in range(n_ticks) ] + [ top_pos ] |
---|
45 | # convert to string |
---|
46 | ticks_labels = [ "%.1f" % x for x in ticks_labels ] |
---|
47 | # return position, label tuple to use with x/yticks |
---|
48 | return ticks_positions, ticks_labels |
---|
49 | |
---|
50 | # apply to the axis |
---|
51 | xticks( *get_rounded_ticks ( len(specgram), time_step, n_xticks ) ) |
---|
52 | yticks( *get_rounded_ticks ( len(specgram[0]), (samplerate / 2. / 1000.) / len(specgram[0]), n_yticks ) ) |
---|
53 | ylabel('Frequency (kHz)') |
---|
54 | xlabel('Time (s)') |
---|
55 | |
---|
56 | if __name__ == '__main__': |
---|
57 | if len(sys.argv) < 2: |
---|
58 | print "Usage: %s <filename>" % sys.argv[0] |
---|
59 | else: |
---|
60 | for soundfile in sys.argv[1:]: |
---|
61 | get_spectrogram(soundfile) |
---|
62 | # display graph |
---|
63 | show() |
---|