annotate scripts/PitchBihist.py @ 4:e50c63cf96be branch-tests

rearranging folders
author Maria Panteli
date Mon, 11 Sep 2017 11:51:50 +0100
parents
children 3b67cd634b9a
rev   line source
Maria@4 1 # -*- coding: utf-8 -*-
Maria@4 2 """
Maria@4 3 Created on Tue Feb 2 22:26:10 2016
Maria@4 4
Maria@4 5 @author: mariapanteli
Maria@4 6 """
Maria@4 7 import smoothiecore as s
Maria@4 8 import numpy
Maria@4 9 import scipy.signal
Maria@4 10 # import librosa
Maria@4 11
Maria@4 12
Maria@4 13 class PitchBihist:
Maria@4 14 def __init__(self, win2sec=8):
Maria@4 15 self.y = None
Maria@4 16 self.sr = None
Maria@4 17 self.chroma = None
Maria@4 18 self.chromasr = None
Maria@4 19 self.bihist = None
Maria@4 20 self.win2sec = win2sec
Maria@4 21
Maria@4 22 def bihist_from_chroma(self, filename='test.wav', secondframedecomp=True):
Maria@4 23 self.chroma, self.chromasr = s.get_smoothie_for_bihist(filename=filename, hopinsec=0.005)
Maria@4 24 if secondframedecomp:
Maria@4 25 win2 = int(round(8*self.chromasr))
Maria@4 26 hop2 = int(round(0.5*self.chromasr))
Maria@4 27 nbins, norigframes = self.chroma.shape
Maria@4 28 if norigframes<win2:
Maria@4 29 nframes = 1
Maria@4 30 else:
Maria@4 31 nframes = int(1+numpy.floor((norigframes-win2)/float(hop2)))
Maria@4 32 bihistframes = numpy.empty((nbins*nbins, nframes))
Maria@4 33 for i in range(nframes): # loop over all 8-sec frames
Maria@4 34 frame = self.chroma[:, (i*hop2):min((i*hop2+win2),norigframes)]
Maria@4 35 bihist = self.bihistogram(frame)
Maria@4 36 bihist = numpy.reshape(bihist, -1)
Maria@4 37 bihistframes[:, i] = bihist
Maria@4 38 self.bihist = bihistframes
Maria@4 39 else:
Maria@4 40 self.bihist = numpy.reshape(self.bihistogram(), -1)
Maria@4 41
Maria@4 42 def bihist_from_melodia(self, filename='sample_melodia.csv', secondframedecomp=True, stop_sec=None):
Maria@4 43 def hz_to_cents(freq_Hz, ref_Hz=32.703, n_cents=1200):
Maria@4 44 """ convert frequency values from Hz to cents
Maria@4 45 reference frequency at C1
Maria@4 46 """
Maria@4 47 freq_cents = numpy.round(n_cents * numpy.log2(freq_Hz/ref_Hz))
Maria@4 48 return freq_cents
Maria@4 49 def wrap_to_octave(cents, octave_length=1200):
Maria@4 50 """ wrap to a single octave 0-1200
Maria@4 51 """
Maria@4 52 octave_cents = cents % octave_length
Maria@4 53 return octave_cents
Maria@4 54
Maria@4 55 n_bins = 60
Maria@4 56 data = numpy.loadtxt(filename, delimiter=',')
Maria@4 57 times, freqs = (data[:, 0], data[:, 1])
Maria@4 58 self.chromasr = 1. / (times[1] - times[0])
Maria@4 59 #self.chromasr = 128.
Maria@4 60 if stop_sec is not None:
Maria@4 61 stop_idx = numpy.where(times < stop_sec)[0]
Maria@4 62 times, freqs = times[stop_idx], freqs[stop_idx]
Maria@4 63 freqs[freqs<=0] = numpy.nan
Maria@4 64 #melody = freqs[freqs>0]
Maria@4 65 melody = freqs
Maria@4 66 n_frames = len(melody)
Maria@4 67 melody_cents = hz_to_cents(melody, n_cents=n_bins)
Maria@4 68 melody_octave = wrap_to_octave(melody_cents, octave_length=n_bins)
Maria@4 69 melody_matrix = numpy.zeros((n_bins, n_frames))
Maria@4 70 for time, pitch in enumerate(melody_octave):
Maria@4 71 if not numpy.isnan(pitch):
Maria@4 72 melody_matrix[int(pitch), time] = 1
Maria@4 73 if secondframedecomp:
Maria@4 74 win2 = int(round(self.win2sec*self.chromasr))
Maria@4 75 hop2 = int(round(0.5*self.chromasr))
Maria@4 76 nbins, norigframes = melody_matrix.shape
Maria@4 77 if norigframes<win2:
Maria@4 78 nframes = 1
Maria@4 79 win2 = norigframes
Maria@4 80 else:
Maria@4 81 nframes = int(1+numpy.floor((norigframes-win2)/float(hop2)))
Maria@4 82 bihistframes = numpy.empty((nbins*nbins, nframes))
Maria@4 83 for i in range(nframes): # loop over all 8-sec frames
Maria@4 84 frame = melody_matrix[:, (i*hop2):(i*hop2+win2)]
Maria@4 85 bihist = self.bihistogram(frame)
Maria@4 86 bihist = numpy.reshape(bihist, -1)
Maria@4 87 bihistframes[:, i] = bihist
Maria@4 88 self.bihist = bihistframes
Maria@4 89 else:
Maria@4 90 self.bihist = self.bihistogram(melody_matrix)
Maria@4 91 return self.bihist
Maria@4 92
Maria@4 93 def bihistogram(self, spec, winsec=0.5, align=True):
Maria@4 94 win = int(round(winsec*self.chromasr))
Maria@4 95 ker = numpy.concatenate([numpy.zeros((win, 1)), numpy.ones((win+1, 1))], axis=0)
Maria@4 96 spec = spec.T # transpose to have franes as rows in convolution
Maria@4 97
Maria@4 98 # energy threshold
Maria@4 99 thr = 0.3*numpy.max(spec)
Maria@4 100 spec[spec < max(thr, 0)] = 0
Maria@4 101
Maria@4 102 # transitions via convolution
Maria@4 103 tra = scipy.signal.convolve2d(spec, ker, mode='same')
Maria@4 104 tra[spec > 0] = 0
Maria@4 105
Maria@4 106 # multiply with original
Maria@4 107 B = numpy.dot(tra.T, spec)
Maria@4 108
Maria@4 109 # normalize
Maria@4 110 mxB = numpy.max(B)
Maria@4 111 mnB = numpy.min(B)
Maria@4 112 if mxB != mnB:
Maria@4 113 B = (B - mnB)/float(mxB-mnB)
Maria@4 114
Maria@4 115 # circshift to highest?
Maria@4 116 if align:
Maria@4 117 ref = numpy.argmax(numpy.sum(spec, axis=0))
Maria@4 118 B = numpy.roll(B, -ref, axis=0)
Maria@4 119 B = numpy.roll(B, -ref, axis=1)
Maria@4 120 return B
Maria@4 121
Maria@4 122 def bihist_from_precomp_chroma(self, align=False):
Maria@4 123 win2 = int(round(self.win2sec*self.chromasr))
Maria@4 124 hop2 = int(round(0.5*self.chromasr))
Maria@4 125 nbins, norigframes = self.chroma.shape
Maria@4 126 if norigframes<win2:
Maria@4 127 nframes = 1
Maria@4 128 else:
Maria@4 129 nframes = int(1+numpy.floor((norigframes-win2)/float(hop2)))
Maria@4 130 bihistframes = numpy.empty((nbins*nbins, nframes))
Maria@4 131 for i in range(nframes): # loop over all 8-sec frames
Maria@4 132 frame = self.chroma[:, (i*hop2):min((i*hop2+win2),norigframes)]
Maria@4 133 bihist = self.bihistogram(frame, align=align)
Maria@4 134 bihist = numpy.reshape(bihist, -1)
Maria@4 135 bihistframes[:, i] = bihist
Maria@4 136 self.bihist = bihistframes
Maria@4 137
Maria@4 138 def get_pitchbihist(self, filename='test.wav'):
Maria@4 139 self.bihist_from_chroma(filename=filename)
Maria@4 140 return self.bihist
Maria@4 141
Maria@4 142 def get_pitchbihist_from_chroma(self, chroma=[], chromasr=[]):
Maria@4 143 self.chroma = chroma
Maria@4 144 self.chromasr = chromasr
Maria@4 145 self.bihist_from_precomp_chroma(align=False)
Maria@4 146 return self.bihist
Maria@4 147
Maria@4 148
Maria@4 149 if __name__ == '__main__':
Maria@4 150 pb = PitchBihist()
Maria@4 151 pb.get_pitchbihist()