comparison scripts/PitchBihist.py @ 37:2cc444441f42 branch-tests

refactor pitchbihist and introduce default melody_sr
author Maria Panteli
date Thu, 14 Sep 2017 14:50:00 +0100
parents 3b67cd634b9a
children e5e8e8a96948
comparison
equal deleted inserted replaced
36:3b67cd634b9a 37:2cc444441f42
11 import smoothiecore as s 11 import smoothiecore as s
12 12
13 13
14 class PitchBihist: 14 class PitchBihist:
15 def __init__(self, win2sec=8): 15 def __init__(self, win2sec=8):
16 self.y = None
17 self.sr = None
18 self.chroma = None
19 self.chromasr = None
20 self.melodiasr = 44100. / 128.
21 self.bihist = None
22 self.win2sec = win2sec 16 self.win2sec = win2sec
17 self.hop2sec = 0.5
18 self.melody_sr = 44100. / 128.
23 19
24 20
25 def hz_to_cents(self, freq_Hz, ref_Hz=32.703, n_cents=1200): 21 def hz_to_cents(self, freq_Hz, ref_Hz=32.703, n_cents=1200):
26 """ convert frequency values from Hz to cents 22 """ convert frequency values from Hz to cents
27 reference frequency at C1 23 reference frequency at C1
40 def get_melody_from_file(self, melodia_file, stop_sec=None): 36 def get_melody_from_file(self, melodia_file, stop_sec=None):
41 if not os.path.exists(melodia_file): 37 if not os.path.exists(melodia_file):
42 return [] 38 return []
43 data = np.loadtxt(melodia_file, delimiter=',') 39 data = np.loadtxt(melodia_file, delimiter=',')
44 times, freqs = (data[:, 0], data[:, 1]) 40 times, freqs = (data[:, 0], data[:, 1])
45 self.chromasr = 1. / (times[1] - times[0]) 41 #melody_sr = 1. / (times[1] - times[0])
46 if stop_sec is not None: 42 if stop_sec is not None:
47 stop_idx = np.where(times < stop_sec)[0] 43 stop_idx = np.where(times < stop_sec)[0]
48 times, freqs = times[stop_idx], freqs[stop_idx] 44 times, freqs = times[stop_idx], freqs[stop_idx]
49 freqs[freqs<=0] = np.nan 45 freqs[freqs<=0] = np.nan
50 melody = freqs 46 melody = freqs
51 return melody 47 return melody#, melody_sr
52 48
53 49
54 def get_melody_matrix(self, melody): 50 def get_melody_matrix(self, melody):
55 n_bins = 60 51 n_bins = 60
56 n_frames = len(melody) 52 n_frames = len(melody)
62 melody_matrix[int(pitch), time] = 1 58 melody_matrix[int(pitch), time] = 1
63 return melody_matrix 59 return melody_matrix
64 60
65 61
66 def bihist_from_melodia(self, filename='sample_melodia.csv', secondframedecomp=True, stop_sec=None): 62 def bihist_from_melodia(self, filename='sample_melodia.csv', secondframedecomp=True, stop_sec=None):
63 #melody, melody_sr = self.get_melody_from_file(filename, stop_sec=stop_sec)
67 melody = self.get_melody_from_file(filename, stop_sec=stop_sec) 64 melody = self.get_melody_from_file(filename, stop_sec=stop_sec)
68 if len(melody) == 0: 65 if len(melody) == 0:
69 self.bihist = [] 66 return []
70 return self.bihist
71 melody_matrix = self.get_melody_matrix(melody) 67 melody_matrix = self.get_melody_matrix(melody)
68 bihist = []
72 if secondframedecomp: 69 if secondframedecomp:
73 nbins, norigframes = melody_matrix.shape 70 nbins, norigframes = melody_matrix.shape
74 win2 = int(round(self.win2sec*self.chromasr)) 71 win2 = int(round(self.win2sec * self.melody_sr))
75 hop2 = int(round(0.5*self.chromasr)) 72 hop2 = int(round(self.hop2sec * self.melody_sr))
76 if norigframes<=win2: 73 if norigframes<=win2:
77 nframes = 1 74 nframes = 1
78 win2 = norigframes 75 win2 = norigframes
79 else: 76 else:
80 nframes = int(np.ceil((norigframes-win2)/float(hop2))) 77 nframes = int(np.ceil((norigframes-win2)/float(hop2)))
82 for i in range(nframes): # loop over all 8-sec frames 79 for i in range(nframes): # loop over all 8-sec frames
83 frame = melody_matrix[:, (i*hop2):(i*hop2+win2)] 80 frame = melody_matrix[:, (i*hop2):(i*hop2+win2)]
84 bihist = self.bihistogram(frame) 81 bihist = self.bihistogram(frame)
85 bihist = np.reshape(bihist, -1) 82 bihist = np.reshape(bihist, -1)
86 bihistframes[:, i] = bihist 83 bihistframes[:, i] = bihist
87 self.bihist = bihistframes 84 bihist = bihistframes
88 else: 85 else:
89 self.bihist = self.bihistogram(melody_matrix) 86 bihist = self.bihistogram(melody_matrix)
90 return self.bihist 87 return bihist
91 88
92 89
93 def bihistogram(self, spec, winsec=0.5, align=True): 90 def bihistogram(self, spec, spec_sr=None, winsec=0.5, align=True):
94 win = int(round(winsec*self.chromasr)) 91 if spec_sr is None:
92 # assume spec is melody_matrix with default sr
93 spec_sr = self.melody_sr
94 win = int(round(winsec * spec_sr))
95 ker = np.concatenate([np.zeros((win, 1)), np.ones((win+1, 1))], axis=0) 95 ker = np.concatenate([np.zeros((win, 1)), np.ones((win+1, 1))], axis=0)
96 spec = spec.T # transpose to have franes as rows in convolution 96 spec = spec.T # transpose to have frames as rows in convolution
97 97
98 # energy threshold 98 # energy threshold
99 thr = 0.3*np.max(spec) 99 thr = 0.3*np.max(spec)
100 spec[spec < max(thr, 0)] = 0 100 spec[spec < max(thr, 0)] = 0
101 101
118 B = np.roll(B, -ref, axis=0) 118 B = np.roll(B, -ref, axis=0)
119 B = np.roll(B, -ref, axis=1) 119 B = np.roll(B, -ref, axis=1)
120 return B 120 return B
121 121
122 122
123 def bihist_from_chroma(self, filename='test.wav', secondframedecomp=True):
124 self.chroma, self.chromasr = s.get_smoothie_for_bihist(filename=filename, hopinsec=0.005)
125 if secondframedecomp:
126 win2 = int(round(8*self.chromasr))
127 hop2 = int(round(0.5*self.chromasr))
128 nbins, norigframes = self.chroma.shape
129 if norigframes<win2:
130 nframes = 1
131 else:
132 nframes = int(1+np.floor((norigframes-win2)/float(hop2)))
133 bihistframes = np.empty((nbins*nbins, nframes))
134 for i in range(nframes): # loop over all 8-sec frames
135 frame = self.chroma[:, (i*hop2):min((i*hop2+win2),norigframes)]
136 bihist = self.bihistogram(frame)
137 bihist = np.reshape(bihist, -1)
138 bihistframes[:, i] = bihist
139 self.bihist = bihistframes
140 else:
141 self.bihist = np.reshape(self.bihistogram(), -1)
142
143
144 def bihist_from_precomp_chroma(self, align=False):
145 win2 = int(round(self.win2sec*self.chromasr))
146 hop2 = int(round(0.5*self.chromasr))
147 nbins, norigframes = self.chroma.shape
148 if norigframes<win2:
149 nframes = 1
150 else:
151 nframes = int(1+np.floor((norigframes-win2)/float(hop2)))
152 bihistframes = np.empty((nbins*nbins, nframes))
153 for i in range(nframes): # loop over all 8-sec frames
154 frame = self.chroma[:, (i*hop2):min((i*hop2+win2),norigframes)]
155 bihist = self.bihistogram(frame, align=align)
156 bihist = np.reshape(bihist, -1)
157 bihistframes[:, i] = bihist
158 self.bihist = bihistframes
159
160 def get_pitchbihist(self, filename='test.wav'):
161 self.bihist_from_chroma(filename=filename)
162 return self.bihist
163
164 def get_pitchbihist_from_chroma(self, chroma=[], chromasr=[]):
165 self.chroma = chroma
166 self.chromasr = chromasr
167 self.bihist_from_precomp_chroma(align=False)
168 return self.bihist
169
170
171 if __name__ == '__main__': 123 if __name__ == '__main__':
172 pb = PitchBihist() 124 pb = PitchBihist()
173 pb.get_pitchbihist() 125 pb.bihist_from_melodia(filename='vamp_melodia.csv')