def beat_phase(defs, oss_sr, oss_data, candidate_bpms_orig, plot=False): ### overlap overlapped = overlap.sliding_window( #numpy.append( # numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE), # oss_data[:-2*defs.BH_HOPSIZE]), oss_data, defs.BP_WINDOWSIZE, defs.BP_HOPSIZE) #beat_histogram_sr = oss_sr / defs.BP_HOPSIZE #print candidate_bpms_orig candidate_bpms = candidate_bpms_orig bphase = numpy.zeros(defs.BPM_MAX) for i in xrange(overlapped.shape[0]): cands = candidate_bpms[i] onset_scores = numpy.zeros(len(cands)) tempo_scores = numpy.zeros(len(cands)) for j, bpm in enumerate(cands): #for j, bpm in enumerate(candidate_bpms): mag, std = calc_pulse_trains(bpm, overlapped[i], oss_sr) #bpms_max[i] += mag #bpms_std[i] += std ### correct up to here #print i, bpm, mag, std tempo_scores[j] = mag #print tempo_scores[j] onset_scores[j] = std tempo_scores /= tempo_scores.sum() onset_scores /= onset_scores.sum() tempo_scores = tempo_scores + onset_scores tempo_scores /= tempo_scores.sum() # find best 2 scores besti = tempo_scores.argmax() bestbpm = round(cands[besti]) #bestbpm = candidate_bpms[besti] #print candidate_bpms[i] #print tempo_scores beststr = tempo_scores[besti] #tempo_scores[besti] = 0.0 #second_besti = tempo_scores.argmax() #second_bestbpm = candidate_bpms[i][second_besti] #second_beststr = tempo_scores[second_besti] #if i >= (defs.BP_WINDOWSIZE / defs.BP_HOPSIZE): bphase[ int(bestbpm) ] += beststr #print bestbpm, "\t", beststr if defs.WRITE_BP: numpy.savetxt("out/bp-%i.txt" % (i+1), numpy.vstack((candidate_bpms[i], tempo_scores)).transpose()) numpy.savetxt("out/bp-peak-%i.txt" % (i+1), numpy.vstack((int(bestbpm), beststr)).transpose()) if defs.WRITE_BP: bp = open('out/beat_phase.txt', 'w') for b in bphase: if b == 0: text = "0\n" else: text = "%.5f\n" % b bp.write(text) bp.close() if plot: pylab.figure() pylab.plot(numpy.arange(len(bphase)), bphase, label="marsyas") pylab.title("bphase") pylab.legend() bpm = bphase.argmax() bpm_strength = bphase[bpm] return bpm, bphase
def onset_strength_signal(wav_sr, wav_data, plot=False): ### overlapping time data # add extra window of zeros at beginning to match marsyas overlapped = overlap.sliding_window( numpy.append( numpy.zeros(defs.OSS_WINDOWSIZE - defs.OSS_HOPSIZE), wav_data), #wav_data, defs.OSS_WINDOWSIZE, defs.OSS_HOPSIZE) oss_sr = wav_sr / float(defs.OSS_HOPSIZE) windowed = overlapped * marsyas_hamming( #scipy.signal.get_window( "hamming", defs.OSS_WINDOWSIZE) ### log-magnitude of FFT ffts = scipy.fftpack.fft(windowed, defs.OSS_WINDOWSIZE, axis=1) ffts_abs = abs(ffts)[:,:ffts.shape[1]/2 + 1] # extra scaling to match Marsyas FFT output ffts_abs /= defs.OSS_WINDOWSIZE logmag = numpy.log(1.0 + 1000.0 * ffts_abs) #numpy.savetxt('log0.txt', logmag[0]) #numpy.savetxt('log1.txt', logmag[1]) ### flux flux = numpy.zeros( ffts_abs.shape[0] ) # output time signal prev = numpy.zeros( ffts_abs.shape[1] ) for i in xrange( 0, ffts_abs.shape[0] ): diff = logmag[i] - prev diffreduced = diff[1:] # to match Marsyas diffclipped = diffreduced.clip(min=0) prev = numpy.copy(logmag[i]) flux[i] = sum(diffclipped) #if i < 2: # print diffclipped #numpy.savetxt('flux.txt', flux) ### clear out first window #flux[0] = 0.0 if plot: ts = numpy.arange( len(flux) ) / oss_sr pylab.figure() pylab.plot( ts, flux) ### filter if defs.OSS_LOWPASS_CUTOFF > 0: b = scipy.signal.firwin(defs.OSS_LOWPASS_N, defs.OSS_LOWPASS_CUTOFF / (oss_sr/2.0) ) #b, a = scipy.signal.butter(2, defs.OSS_LOWPASS_CUTOFF / (oss_sr/2.0) ) #filtered_flux = scipy.signal.filtfilt(b, a, flux) #a = numpy.zeros(defs.OSS_LOWPASS_N) #a[0] = 1.0 filtered_flux = scipy.signal.lfilter(b, 1.0, flux) else: filtered_flux = flux #numpy.savetxt('filtered.txt', filtered_flux) if plot: ts = numpy.arange( len(filtered_flux) ) / oss_sr pylab.plot( ts, filtered_flux) pylab.title("Onset strength signal") return oss_sr, filtered_flux
def beat_histogram(defs, oss_sr, oss_data, plot=False): ### overlap overlapped = overlap.sliding_window( #numpy.append( # numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE), # oss_data[:-2*defs.BH_HOPSIZE]), oss_data, defs.BH_WINDOWSIZE, defs.BH_HOPSIZE) #beat_histogram_sr = oss_sr / defs.BH_HOPSIZE #for i in range(len(overlapped[0])): # print overlapped[0][i] #exit(1) ### autocorrelation autocorr = autocorrelation(overlapped) ### beat histogram Hn = numpy.zeros((autocorr.shape[0], 4 * defs.BPM_MAX)) for i in xrange(autocorr.shape[0]): #if i > 0 and i != (defs.BH_WINDOWSIZE / defs.BH_HOPSIZE): # Hn[i] = Hn[i-1] prev_Hni = 4 * defs.BPM_MAX - 1 pprev_Hni = prev_Hni sumamp = 0.0 count = 1 for j in xrange(1, autocorr.shape[1]): factor = 8 / 2 Hni = int(oss_sr * 60.0 * factor / (j + 1) + 0.5) #bpm = autocorr_bpms[i] if Hni < 4 * defs.BPM_MAX: amp = autocorr[i][j] #print j, Hni, amp if amp < 0: amp = 0 if prev_Hni == Hni: sumamp += amp count += 1 else: sumamp += amp Hn[i][prev_Hni] = sumamp / float(count) sumamp = 0.0 count = 1 ### linear interpolate not-set bins if pprev_Hni - prev_Hni > 1: x0 = prev_Hni x1 = pprev_Hni y0 = Hn[i][prev_Hni] y1 = Hn[i][pprev_Hni] for k in xrange(prev_Hni + 1, pprev_Hni): Hn[i][k] = y0 + (y1 - y0) * (k - x0) / (x1 - x0) #print x0, x1, y0, y1, Hn[i][pprev_Hni-1] pprev_Hni = prev_Hni prev_Hni = Hni #numpy.savetxt('bh.txt', Hn[0]) #for a in range(0, 20): # numpy.savetxt("bh-combo-%i.txt" % a, Hn[a]) #if plot: # pylab.figure() # Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0 # pylab.plot(Hn_bpms, summed_beat_histograms) # pylab.title("Beat histogram") ### time stretch, add harmonic_strengthened_bh = numpy.zeros(Hn.shape) for i in xrange(Hn.shape[0]): ### unchecked direct translation of marsyas factor2 = 0.5 factor4 = 0.25 stretched = numpy.zeros(Hn.shape[1]) numSamples = Hn.shape[1] for t in xrange(Hn.shape[1]): ni = t * factor2 li = int(ni) % numSamples ri = li + 1 w = ni - li #print "%i\t%i\t%f\t%f" % (li, ri, w, ni) #zzz if ri < numSamples: stretched[t] += Hn[i][li] + w * (Hn[i][ri] - Hn[i][li]) else: stretched[t] += Hn[t] ni = t * factor4 li = int(ni) % numSamples ri = li + 1 w = ni - li if ri < numSamples: stretched[t] += Hn[i][li] + w * (Hn[i][ri] - Hn[i][li]) else: stretched[t] += Hn[t] harmonic_strengthened_bh[i] = (Hn[i] + stretched) if defs.WRITE_BH: samps = numpy.arange(defs.BH_WINDOWSIZE) numpy.savetxt("out/aq-%i.txt" % (i + 1), numpy.vstack((samps, autocorr[i])).transpose()) bpms = numpy.arange(4 * defs.BPM_MAX) / 4.0 numpy.savetxt("out/bh-%i.txt" % (i + 1), numpy.vstack((bpms, Hn[i])).transpose()) numpy.savetxt( "out/hbh-%i.txt" % (i + 1), numpy.vstack((bpms, harmonic_strengthened_bh[i])).transpose()) #for a in range(0, 20): # numpy.savetxt("bh-combo-%i.txt" % a, harmonic_strengthened_bh[a]) #if plot: # Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0 # pylab.plot(Hn_bpms, harmonic_strengthened_bh) ### pick top 8 candidates #peaks = [] #for i in xrange( Hn.shape[0] ): # these_peaks = find_peaks(harmonic_strengthened_bh[i], # number=8, width=11) # peaks.append(these_peaks) #summed = numpy.sum(harmonic_strengthened_bh, axis=0) #summed = numpy.sum(Hn, axis=0) if plot: pylab.figure() sHn = numpy.sum(Hn, axis=0) sHBH = numpy.sum(harmonic_strengthened_bh, axis=0) pylab.plot(numpy.arange(len(sHn)) / 4.0, sHn, label="sum") pylab.plot(numpy.arange(len(sHBH)) / 4.0, sHBH, label="enhanced") if defs.OPTIONS_BH == 3: b, a = scipy.signal.butter(1, 0.1) filtered = scipy.signal.filtfilt(b, a, sHBH) pylab.plot(numpy.arange(len(filtered)) / 4.0, filtered, label="filtered") pylab.title("Summed beat histogram") # folded_hist = numpy.zeros(60*4) # for i in xrange(1, len(summed)-1): # bpm = i/4.0 # j = i # while bpm < 15: # bpm *= 2 # j *= 2 # while bpm > 30: # bpm /= 2.0 # j /= 2.0 # #j = int(round(j)) # j = int(j) # #print "%i\tto\t%i" % (i, j) # if j >= len(folded_hist): # continue # folded_hist [j] += summed[i] # if defs.WRITE_BH: combo_peaks = open('out/beat_histogram.txt', 'w') peaks = [] bh_total = numpy.zeros((Hn.shape[0], 10)) for i in xrange(Hn.shape[0]): these_peaks = find_peaks(defs, harmonic_strengthened_bh[i], number=10, peak_neighbors=1) bh_total[i, :] = these_peaks if defs.WRITE_BH: tl = [] for b in these_peaks: tl.append("%.2f" % (b / 4.0)) text = " ".join(tl) combo_peaks.write(text + "\n") bpms = numpy.array(these_peaks) / 4.0 bpms_strengths = [harmonic_strengthened_bh[i][4 * b] for b in bpms] numpy.savetxt("out/bh-peaks-%i.txt" % (i + 1), numpy.vstack((bpms, bpms_strengths)).transpose()) peaks.append(numpy.array(these_peaks) / 4.0) if defs.WRITE_BH: combo_peaks.close() if defs.CHECK_REFERENCE: calc = bh_total / 4.0 ref = numpy.loadtxt("reference/%s/beat_histogram.txt" % defs.basename) delta = calc - ref maxerr = numpy.abs(delta).max() if maxerr < 1e-12: print "BH ok, maximum deviation %.2g" % maxerr else: pylab.figure() pylab.title("BH: calculated - reference") pylab.plot(delta) pylab.show() exit(1) #cand_peaks = find_peaks(sHn, # number=8, peak_neighbors=11) / 4.0 #pylab.plot(numpy.arange(len(sHn))/4.0, sHn) #pylab.show() #pylab.plot(cand_peaks) return peaks
def onset_strength_signal(defs, wav_sr, wav_data, plot=False): ### overlapping time data # add extra window of zeros at beginning to match marsyas overlapped = overlap.sliding_window( numpy.append( numpy.zeros(defs.OSS_WINDOWSIZE - defs.OSS_HOPSIZE), wav_data), #wav_data, defs.OSS_WINDOWSIZE, defs.OSS_HOPSIZE) oss_sr = wav_sr / float(defs.OSS_HOPSIZE) #print oss_sr if defs.OPTIONS_ONSET == 0: rms = numpy.sqrt( numpy.mean(overlapped**2, axis=1)) #dif = numpy.clip( rms[1:] - rms[:-1], 0, numpy.Inf) #return oss_sr, dif return oss_sr, rms windowed = overlapped * marsyas_hamming( #scipy.signal.get_window( "hamming", defs.OSS_WINDOWSIZE) ### log-magnitude of FFT ffts = scipy.fftpack.fft(windowed, defs.OSS_WINDOWSIZE, axis=1) ffts_abs = abs(ffts)[:,:ffts.shape[1]/2 + 1] # extra scaling to match Marsyas FFT output ffts_abs /= defs.OSS_WINDOWSIZE logmag = numpy.log(1.0 + 1000.0 * ffts_abs) ### flux flux = numpy.zeros( ffts_abs.shape[0] ) # output time signal prev = numpy.zeros( ffts_abs.shape[1] ) for i in xrange( 0, ffts_abs.shape[0] ): diff = logmag[i] - prev diffreduced = diff[1:] # to match Marsyas diffclipped = diffreduced.clip(min=0) prev = numpy.copy(logmag[i]) flux[i] = sum(diffclipped) #if i < 2: # print diffclipped #if True: # ts = numpy.arange(len(flux)-1) / oss_sr # pylab.plot(ts, flux[1:], color="red") #numpy.savetxt('flux.txt', flux) ### clear out first window #flux[0] = 0.0 if defs.OPTIONS_ONSET == 1: return oss_sr, flux if plot: ts = numpy.arange( len(flux) ) / oss_sr pylab.figure() #pylab.plot( ts, flux) ### filter if defs.OSS_LOWPASS_CUTOFF > 0 and defs.OPTIONS_ONSET < 3: b = scipy.signal.firwin(defs.OSS_LOWPASS_N, defs.OSS_LOWPASS_CUTOFF / (oss_sr/2.0) ) #print b filtered_flux = scipy.signal.lfilter(b, 1.0, flux) #b, a = scipy.signal.butter(2, 0.1 / (oss_sr/2.0), # btype="high") #filtered_flux = scipy.signal.filtfilt(b, a, flux) else: filtered_flux = flux if plot: ts = numpy.arange( len(filtered_flux) ) / oss_sr pylab.plot( ts, filtered_flux, label="filtered") pylab.title("Onset strength signal") ts = numpy.arange( len(filtered_flux) ) / oss_sr if defs.WRITE_ONSETS: #cutoff = int(2048*128/44100.0 * oss_sr) cutoff = 2048 #print "cutoff", cutoff #print logmag.shape logmag_short = logmag[:cutoff,] #print logmag_short.shape numpy.savetxt('out/logmag.txt', logmag_short.transpose()) #logmag[:cutoff,].transpose()) numpy.savetxt('out/flux.txt', numpy.vstack( (ts, flux)).transpose() ) numpy.savetxt('out/onset_strength.txt', numpy.vstack( (ts, filtered_flux)).transpose() ) num_bh_frames = int(len(filtered_flux) / defs.BH_HOPSIZE) filtered_flux = filtered_flux[:num_bh_frames * defs.BH_HOPSIZE] if defs.CHECK_REFERENCE: calc = filtered_flux ref = numpy.loadtxt( "reference/OSS-4-filter.txt") delta = calc - ref maxerr = max(abs(delta)) if maxerr < 1e-12: print "OSS ok, maximum deviation %.2g" % maxerr else: pylab.figure() pylab.title("OSS: calculated - reference") pylab.plot(delta) pylab.show() exit(1) if plot: pylab.legend() return oss_sr, filtered_flux
def beat_period_detection(defs, oss_sr, oss_data, plot=False, limit_pulse_trains=False, skip_calc_pulse_trains=False, intermediate_data=False): ### 1) Overlap overlapped = overlap.sliding_window( #numpy.append( # numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE), # oss_data[:-2*defs.BH_HOPSIZE]), oss_data, defs.BH_WINDOWSIZE, defs.BH_HOPSIZE, zeroPad=True) #beat_period_sr = oss_sr / defs.BH_HOPSIZE ### 2) Generalized Autocorrelation autocorr = autocorrelation(overlapped) minlag = int(oss_sr * 60.0 / defs.BPM_MAX) maxlag = int(oss_sr * 60.0 / defs.BPM_MIN) + 1 num_frames = autocorr.shape[0] #win_size = autocorr.shape[1] ### 3) Enhance Harmonics harmonic_enhanced = numpy.zeros(autocorr.shape) for i in xrange(num_frames): auto = autocorr[i] stretched = numpy.zeros(defs.BH_WINDOWSIZE) for j in xrange(512): stretched[j] = auto[2 * j] + auto[4 * j] harmonic_enhanced[i] = (auto + stretched) ### 4) Pick peaks peaks = numpy.zeros((num_frames, 10)) for i in xrange(num_frames): these_peaks = find_peaks(defs, harmonic_enhanced[i], number=10, peak_neighbors=1, minsample=minlag, maxsample=maxlag) peaks[i, :] = these_peaks ### 5) Evaluate pulse trains tempo_lags = numpy.zeros(num_frames) for i in xrange(num_frames): cands = peaks[i] onset_scores = numpy.zeros(len(cands)) tempo_scores = numpy.zeros(len(cands)) for j, cand in enumerate(cands): if cand == 0: continue lag = int(round(cand)) if not skip_calc_pulse_trains: mag, var = calc_pulse_trains( lag, overlapped[i], limit_pulse_trains=limit_pulse_trains) else: mag = 0.0 var = 0.0 tempo_scores[j] = mag onset_scores[j] = var tempo_scores /= tempo_scores.sum() onset_scores /= onset_scores.sum() combo_scores = tempo_scores + onset_scores combo_scores /= combo_scores.sum() # find best score besti = combo_scores.argmax() bestlag = round(cands[besti]) tempo_lags[i] = bestlag if defs.CHECK_REFERENCE: ref = numpy.loadtxt("reference/BEATS-5-pulse.txt") delta = tempo_lags - ref maxerr = numpy.abs(delta).max() if maxerr < 1e-12: print "Beat pulse detection ok, maximum deviation %.2g" % maxerr else: pylab.figure() pylab.title("Beat pulse detection: this - reference") pylab.plot(delta) pylab.show() exit(1) if not intermediate_data: return tempo_lags else: return tempo_lags, peaks, autocorr, harmonic_enhanced, overlapped
def beat_histogram(oss_sr, oss_data, plot=False): ### overlap overlapped = overlap.sliding_window( numpy.append(numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE), oss_data), #oss_data, defs.BH_WINDOWSIZE, defs.BH_HOPSIZE) #beat_histogram_sr = oss_sr / defs.BH_HOPSIZE ### autocorrelation autocorr = autocorrelation(overlapped) ### beat histogram Hn = numpy.zeros((autocorr.shape[0], 4 * defs.BPM_MAX)) for i in xrange(autocorr.shape[0]): if i > 0 and i != (defs.BH_WINDOWSIZE / defs.BH_HOPSIZE): Hn[i] = Hn[i - 1] prev_Hni = 4 * defs.BPM_MAX - 1 pprev_Hni = prev_Hni sumamp = 0.0 count = 1 for j in xrange(1, autocorr.shape[1]): factor = 8 / 2 Hni = int((oss_sr * 60.0 * factor / (j + 1)) + 0.5) #bpm = autocorr_bpms[i] if Hni < 4 * defs.BPM_MAX and Hni > 40: amp = autocorr[i][j] if amp < 0: amp = 0 if prev_Hni == Hni: sumamp += amp count += 1 else: sumamp += amp Hn[i][prev_Hni] += sumamp / float(count) sumamp = 0.0 count = 1 ### linear interpolate not-set bins if pprev_Hni - prev_Hni > 1: x0 = prev_Hni x1 = pprev_Hni y0 = Hn[i][prev_Hni] y1 = Hn[i][pprev_Hni] for k in xrange(prev_Hni + 1, pprev_Hni): Hn[i][k] = y0 + (y1 - y0) * (k - x0) / (x1 - x0) #print x0, x1, y0, y1, Hn[i][pprev_Hni-1] pprev_Hni = prev_Hni prev_Hni = Hni #numpy.savetxt('bh.txt', Hn[0]) #for a in range(0, 20): # numpy.savetxt("bh-combo-%i.txt" % a, Hn[a]) #if plot: # pylab.figure() # Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0 # pylab.plot(Hn_bpms, summed_beat_histograms) # pylab.title("Beat histogram") ### time stretch, add harmonic_strengthened_bh = numpy.zeros(Hn.shape) for i in xrange(Hn.shape[0]): ### unchecked direct translation of marsyas stretched = numpy.zeros(Hn.shape[1]) factor = 0.5 numSamples = Hn.shape[1] for t in xrange(Hn.shape[1]): ni = t * factor li = int(ni) % numSamples ri = li + 1 w = ni - li if ri < numSamples: stretched[t] = Hn[i][li] + w * (Hn[i][ri] - Hn[i][li]) else: stretched[t] = Hn[t] harmonic_strengthened_bh[i] = (Hn[i] + stretched) numpy.savetxt("foo-%i.txt" % i, harmonic_strengthened_bh[i]) #for a in range(0, 20): # numpy.savetxt("bh-combo-%i.txt" % a, harmonic_strengthened_bh[a]) #if plot: # Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0 # pylab.plot(Hn_bpms, harmonic_strengthened_bh) ### pick top 8 candidates #peaks = [] #for i in xrange( Hn.shape[0] ): # these_peaks = find_peaks(harmonic_strengthened_bh[i], # number=8, width=11) # peaks.append(these_peaks) #summed = numpy.sum(harmonic_strengthened_bh, axis=0) #summed = numpy.sum(Hn, axis=0) if plot: pylab.figure() pylab.plot(numpy.arange(len(Hn)) / 4.0, Hn) # folded_hist = numpy.zeros(60*4) # for i in xrange(1, len(summed)-1): # bpm = i/4.0 # j = i # while bpm < 15: # bpm *= 2 # j *= 2 # while bpm > 30: # bpm /= 2.0 # j /= 2.0 # #j = int(round(j)) # j = int(j) # #print "%i\tto\t%i" % (i, j) # if j >= len(folded_hist): # continue # folded_hist [j] += summed[i] # ### zzz confirmed up to here peaks = [] for i in xrange(Hn.shape[0]): these_peaks = find_peaks(harmonic_strengthened_bh[i], number=8, peak_neighbors=11) peaks.append(these_peaks / 4.0) #bpms = numpy.array(these_peaks)/4.0 # numpy.savetxt("bh-peaks-%i.txt" % i, bpms) #candidate_bpms = [ Hn_bpms[i] for i in peaks ] #print candidate_bpms #for p in peaks: # print numpy.array(p)/4 #if plot: # pylab.figure() # pylab.plot(numpy.arange(30*4, 60*4)/4.0, folded_hist[30*4:]) # pylab.show() return peaks
def beat_phase(defs, oss_sr, oss_data, candidate_bpms_orig, plot=False): ### overlap overlapped = overlap.sliding_window( #numpy.append( # numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE), # oss_data[:-2*defs.BH_HOPSIZE]), oss_data, defs.BP_WINDOWSIZE, defs.BP_HOPSIZE) #beat_histogram_sr = oss_sr / defs.BP_HOPSIZE if defs.WRITE_BP: bp_accum = open("out/bp-accum.txt", "w") #print candidate_bpms_orig candidate_bpms = candidate_bpms_orig bphase = numpy.zeros(defs.BPM_MAX) for i in xrange(overlapped.shape[0]): cands = candidate_bpms[i] onset_scores = numpy.zeros(len(cands)) tempo_scores = numpy.zeros(len(cands)) for j, bpm in enumerate(cands): if bpm == 0: continue mag, var = calc_pulse_trains(bpm, overlapped[i], oss_sr) tempo_scores[j] = mag onset_scores[j] = var if defs.WRITE_BP: numpy.savetxt( "out/bp-%i.txt" % (i + 1), numpy.vstack((cands, tempo_scores, onset_scores)).transpose()) tempo_scores /= tempo_scores.sum() onset_scores /= onset_scores.sum() combo_scores = tempo_scores + onset_scores combo_scores /= combo_scores.sum() # find best score besti = combo_scores.argmax() bestbpm = round(cands[besti]) beststr = combo_scores[besti] bphase[int(bestbpm)] += beststr if defs.WRITE_BP: #numpy.savetxt("out/bp-%i.txt" % (i+1), # numpy.vstack((cands, tempo_scores, onset_scores, combo_scores)).transpose()) #numpy.savetxt("out/bp-peak-%i.txt" % (i+1), # numpy.vstack((int(bestbpm), beststr)).transpose()) text = "%i\t%.15f\n" % (int(bestbpm), beststr) bp_accum.write(text) if defs.WRITE_BP: bp = open('out/beat_phase.txt', 'w') for b in bphase: if b == 0: text = "0\n" else: text = "%.5f\n" % b bp.write(text) bp.close() if plot: pylab.figure() pylab.plot(numpy.arange(len(bphase)), bphase, label="marsyas") pylab.title("bphase") pylab.legend() bpm = bphase.argmax() #bpm_strength = bphase[bpm] if defs.CHECK_REFERENCE: calc = bphase ref = numpy.loadtxt("reference/%s/beat_phase.txt" % defs.basename) delta = calc - ref maxerr = numpy.abs(delta).max() if maxerr < 1e-6: print "BP ok, maximum deviation %.2g" % maxerr else: pylab.figure() pylab.title("BP: calculated - reference") pylab.plot(delta) pylab.figure() pylab.plot(calc) pylab.plot(ref) pylab.show() exit(1) if defs.WRITE_BP: bp_accum.close() return bpm, bphase
def onset_strength_signal(wav_sr, wav_data, plot=False): ### overlapping time data # add extra window of zeros at beginning to match marsyas overlapped = overlap.sliding_window( numpy.append(numpy.zeros(defs.OSS_WINDOWSIZE - defs.OSS_HOPSIZE), wav_data), #wav_data, defs.OSS_WINDOWSIZE, defs.OSS_HOPSIZE) oss_sr = wav_sr / float(defs.OSS_HOPSIZE) windowed = overlapped * marsyas_hamming( #scipy.signal.get_window( "hamming", defs.OSS_WINDOWSIZE) ### log-magnitude of FFT ffts = scipy.fftpack.fft(windowed, defs.OSS_WINDOWSIZE, axis=1) ffts_abs = abs(ffts)[:, :ffts.shape[1] / 2 + 1] # extra scaling to match Marsyas FFT output ffts_abs /= defs.OSS_WINDOWSIZE logmag = numpy.log(1.0 + 1000.0 * ffts_abs) #numpy.savetxt('log0.txt', logmag[0]) #numpy.savetxt('log1.txt', logmag[1]) ### flux flux = numpy.zeros(ffts_abs.shape[0]) # output time signal prev = numpy.zeros(ffts_abs.shape[1]) for i in xrange(0, ffts_abs.shape[0]): diff = logmag[i] - prev diffreduced = diff[1:] # to match Marsyas diffclipped = diffreduced.clip(min=0) prev = numpy.copy(logmag[i]) flux[i] = sum(diffclipped) #if i < 2: # print diffclipped #numpy.savetxt('flux.txt', flux) ### clear out first window #flux[0] = 0.0 if plot: ts = numpy.arange(len(flux)) / oss_sr pylab.figure() pylab.plot(ts, flux) ### filter if defs.OSS_LOWPASS_CUTOFF > 0: b = scipy.signal.firwin(defs.OSS_LOWPASS_N, defs.OSS_LOWPASS_CUTOFF / (oss_sr / 2.0)) #b, a = scipy.signal.butter(2, defs.OSS_LOWPASS_CUTOFF / (oss_sr/2.0) ) #filtered_flux = scipy.signal.filtfilt(b, a, flux) #a = numpy.zeros(defs.OSS_LOWPASS_N) #a[0] = 1.0 filtered_flux = scipy.signal.lfilter(b, 1.0, flux) else: filtered_flux = flux #numpy.savetxt('filtered.txt', filtered_flux) if plot: ts = numpy.arange(len(filtered_flux)) / oss_sr pylab.plot(ts, filtered_flux) pylab.title("Onset strength signal") return oss_sr, filtered_flux
def onset_strength_signal(defs, wav_sr, wav_data, plot=False): ### overlapping time data # add extra window of zeros at beginning to match marsyas overlapped = overlap.sliding_window( numpy.append(numpy.zeros(defs.OSS_WINDOWSIZE - defs.OSS_HOPSIZE), wav_data), #wav_data, defs.OSS_WINDOWSIZE, defs.OSS_HOPSIZE) oss_sr = wav_sr / float(defs.OSS_HOPSIZE) #print oss_sr if defs.OPTIONS_ONSET == 0: rms = numpy.sqrt(numpy.mean(overlapped**2, axis=1)) #dif = numpy.clip( rms[1:] - rms[:-1], 0, numpy.Inf) #return oss_sr, dif return oss_sr, rms windowed = overlapped * marsyas_hamming( #scipy.signal.get_window( "hamming", defs.OSS_WINDOWSIZE) ### log-magnitude of FFT ffts = scipy.fftpack.fft(windowed, defs.OSS_WINDOWSIZE, axis=1) ffts_abs = abs(ffts)[:, :ffts.shape[1] / 2 + 1] # extra scaling to match Marsyas FFT output ffts_abs /= defs.OSS_WINDOWSIZE logmag = numpy.log(1.0 + 1000.0 * ffts_abs) ### flux flux = numpy.zeros(ffts_abs.shape[0]) # output time signal prev = numpy.zeros(ffts_abs.shape[1]) for i in xrange(0, ffts_abs.shape[0]): diff = logmag[i] - prev diffreduced = diff[1:] # to match Marsyas diffclipped = diffreduced.clip(min=0) prev = numpy.copy(logmag[i]) flux[i] = sum(diffclipped) #if i < 2: # print diffclipped #if True: # ts = numpy.arange(len(flux)-1) / oss_sr # pylab.plot(ts, flux[1:], color="red") #numpy.savetxt('flux.txt', flux) ### clear out first window #flux[0] = 0.0 if defs.OPTIONS_ONSET == 1: return oss_sr, flux if plot: ts = numpy.arange(len(flux)) / oss_sr pylab.figure() #pylab.plot( ts, flux) ### filter if defs.OSS_LOWPASS_CUTOFF > 0 and defs.OPTIONS_ONSET < 3: b = scipy.signal.firwin(defs.OSS_LOWPASS_N, defs.OSS_LOWPASS_CUTOFF / (oss_sr / 2.0)) #print b filtered_flux = scipy.signal.lfilter(b, 1.0, flux) #b, a = scipy.signal.butter(2, 0.1 / (oss_sr/2.0), # btype="high") #filtered_flux = scipy.signal.filtfilt(b, a, flux) else: filtered_flux = flux if plot: ts = numpy.arange(len(filtered_flux)) / oss_sr pylab.plot(ts, filtered_flux, label="filtered") pylab.title("Onset strength signal") ts = numpy.arange(len(filtered_flux)) / oss_sr if defs.WRITE_ONSETS: #cutoff = int(2048*128/44100.0 * oss_sr) cutoff = 2048 #print "cutoff", cutoff #print logmag.shape logmag_short = logmag[:cutoff, ] #print logmag_short.shape numpy.savetxt('out/logmag.txt', logmag_short.transpose()) #logmag[:cutoff,].transpose()) numpy.savetxt('out/flux.txt', numpy.vstack((ts, flux)).transpose()) numpy.savetxt('out/onset_strength.txt', numpy.vstack((ts, filtered_flux)).transpose()) num_bh_frames = int(len(filtered_flux) / defs.BH_HOPSIZE) filtered_flux = filtered_flux[:num_bh_frames * defs.BH_HOPSIZE] if defs.CHECK_REFERENCE: calc = filtered_flux ref = numpy.loadtxt("reference/OSS-4-filter.txt") delta = calc - ref maxerr = max(abs(delta)) if maxerr < 1e-12: print "OSS ok, maximum deviation %.2g" % maxerr else: pylab.figure() pylab.title("OSS: calculated - reference") pylab.plot(delta) pylab.show() exit(1) if plot: pylab.legend() return oss_sr, filtered_flux
def beat_phase(defs, oss_sr, oss_data, candidate_bpms_orig, plot=False): ### overlap overlapped = overlap.sliding_window( #numpy.append( # numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE), # oss_data), oss_data, defs.BP_WINDOWSIZE, defs.BP_HOPSIZE) #beat_histogram_sr = oss_sr / defs.BP_HOPSIZE #print candidate_bpms_orig candidate_bpms = candidate_bpms_orig candidate_bpms = candidate_bpms_orig[:4] #for bpm in candidate_bpms_orig: # #print bpm, base # candidate_bpms.add(bpm) #candidate_bpms = list(candidate_bpms) #candidate_bpms.sort() #print candidate_bpms if defs.OPTIONS_BP == 0: onset_scores = numpy.zeros(len(candidate_bpms)) tempo_scores = numpy.zeros(len(candidate_bpms)) pylab.plot(overlapped[0]) for j, bpm in enumerate(candidate_bpms): #print "Evaluating %.1f BPM" % bpm #train = make_sine_train(bpm) train, period = make_impulse_train(bpm, len(overlapped[0]), oss_sr) for i in xrange(overlapped.shape[0]): #for i in xrange(1): mag, offset, var = match_offset(train, overlapped[i], period) #print "%.2f\t%.2f" % ( # mag / numpy.sum(train), var) onset_scores[j] += mag + var #pylab.title("actual signal") #pylab.plot(overlapped[i]) #pylab.plot(train) #pylab.show() pylab.plot(30*train[period-8:]) #print onset_scores / max(onset_scores) best_i = onset_scores.argmax() print onset_scores[0] + onset_scores[2] print onset_scores[1] + onset_scores[3] pylab.show() return candidate_bpms[best_i], 0 exit(1) if False: if False: #mag, std = calc_pulse_trains(bpm, overlapped[i], oss_sr) mag, std = calc_sine_trains(bpm, overlapped[i], oss_sr) #print "%.1f\t%.3f\t%.3f" % (bpm, mag, std) onset_scores[j] += mag tempo_scores[j] += std #exit(1) #print candidate_bpms #print onset_scores #print tempo_scores best_i = tempo_scores.argmax() best_bpm = candidate_bpms[best_i] return best_bpm, 0 bhisto = numpy.zeros(defs.BPM_MAX) #bpms_max = numpy.zeros( len(candidate_bpms) ) #bpms_std = numpy.zeros( len(candidate_bpms) ) for i in xrange(overlapped.shape[0]): onset_scores = numpy.zeros(len(candidate_bpms)) tempo_scores = numpy.zeros(len(candidate_bpms)) #for j, bpm in enumerate(candidate_bpms[i]): for j, bpm in enumerate(candidate_bpms): mag, std = calc_pulse_trains(bpm, overlapped[i], oss_sr) #bpms_max[i] += mag #bpms_std[i] += std ### correct up to here #print i, bpm, mag, std tempo_scores[j] = mag onset_scores[j] = std tempo_scores /= tempo_scores.sum() onset_scores /= onset_scores.sum() tempo_scores = tempo_scores + onset_scores tempo_scores /= tempo_scores.sum() # find best 2 scores besti = tempo_scores.argmax() #bestbpm = candidate_bpms[i][besti] bestbpm = candidate_bpms[besti] beststr = tempo_scores[besti] #tempo_scores[besti] = 0.0 #second_besti = tempo_scores.argmax() #second_bestbpm = candidate_bpms[i][second_besti] #second_beststr = tempo_scores[second_besti] if i >= (defs.BP_WINDOWSIZE / defs.BP_HOPSIZE): bhisto[ int(bestbpm) ] += beststr #bhisto[ int(second_bestbpm*4) ] += second_beststr #print bestbpm, '\t', beststr, '\t', #print second_bestbpm, '\t', second_beststr #b, a = scipy.signal.butter(4, 0.5) #filt = scipy.signal.filtfilt(b, a, bhisto) if plot: pylab.figure() pylab.plot(numpy.arange(len(bhisto)), bhisto, label="marsyas") #pylab.plot(numpy.arange(len(bhisto))/4.0, filt, # label="extra filtered") pylab.title("bhisto") pylab.legend() bpm1 = bhisto.argmax() bhisto[bpm1] = 0.0 bpm2 = bhisto.argmax() return bpm1, bpm2
def beat_period_detection(defs, oss_sr, oss_data, plot=False): ### 1) Overlap overlapped = overlap.sliding_window( #numpy.append( # numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE), # oss_data[:-2*defs.BH_HOPSIZE]), oss_data, defs.BH_WINDOWSIZE, defs.BH_HOPSIZE, zeroPad=True) #beat_period_sr = oss_sr / defs.BH_HOPSIZE ### 2) Generalized Autocorrelation autocorr = autocorrelation(overlapped) minlag = int(oss_sr*60.0 / defs.BPM_MAX) maxlag = int(oss_sr*60.0 / defs.BPM_MIN) + 1 num_frames = autocorr.shape[0] #win_size = autocorr.shape[1] ### 3) Enhance Harmonics harmonic_enhanced = numpy.zeros( autocorr.shape ) for i in xrange( num_frames ): auto = autocorr[i] stretched = numpy.zeros( defs.BH_WINDOWSIZE ) for j in xrange( 512 ): stretched[j] = auto[2*j] + auto[4*j] harmonic_enhanced[i] = ( auto + stretched ) ### 4) Pick peaks peaks = numpy.zeros( (num_frames, 10) ) for i in xrange( num_frames ): these_peaks = find_peaks(defs, harmonic_enhanced[i], number=10, peak_neighbors=1, minsample=minlag, maxsample=maxlag) peaks[i,:] = these_peaks ### 5) Evaluate pulse trains tempo_lags = numpy.zeros(num_frames) for i in xrange(num_frames): cands = peaks[i] onset_scores = numpy.zeros(len(cands)) tempo_scores = numpy.zeros(len(cands)) for j, cand in enumerate(cands): if cand == 0: continue lag = int(round(cand)) mag, var = calc_pulse_trains(lag, overlapped[i], oss_sr) tempo_scores[j] = mag onset_scores[j] = var tempo_scores /= tempo_scores.sum() onset_scores /= onset_scores.sum() combo_scores = tempo_scores + onset_scores combo_scores /= combo_scores.sum() # find best score besti = combo_scores.argmax() bestlag = round(cands[besti]) tempo_lags[i] = bestlag if defs.CHECK_REFERENCE: ref = numpy.loadtxt( "reference/BEATS-5-pulse.txt") delta = tempo_lags - ref maxerr = numpy.abs(delta).max() if maxerr < 1e-12: print "Beat pulse detection ok, maximum deviation %.2g" % maxerr else: pylab.figure() pylab.title("Beat pulse detection: this - reference") pylab.plot(delta) pylab.show() exit(1) return tempo_lags
def beat_histogram(oss_sr, oss_data, plot=False): ### overlap overlapped = overlap.sliding_window( numpy.append( numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE), oss_data), #oss_data, defs.BH_WINDOWSIZE, defs.BH_HOPSIZE) #beat_histogram_sr = oss_sr / defs.BH_HOPSIZE ### autocorrelation autocorr = autocorrelation(overlapped) ### beat histogram Hn = numpy.zeros( (autocorr.shape[0], 4*defs.BPM_MAX) ) for i in xrange( autocorr.shape[0] ): if i > 0 and i != (defs.BH_WINDOWSIZE / defs.BH_HOPSIZE): Hn[i] = Hn[i-1] prev_Hni = 4*defs.BPM_MAX-1 pprev_Hni = prev_Hni sumamp = 0.0 count = 1 for j in xrange(1, autocorr.shape[1]): factor = 8/2 Hni = int((oss_sr * 60.0 * factor / (j+1)) + 0.5); #bpm = autocorr_bpms[i] if Hni < 4*defs.BPM_MAX and Hni > 40: amp = autocorr[i][j] if amp < 0: amp = 0 if prev_Hni == Hni: sumamp += amp count += 1 else: sumamp += amp Hn[i][prev_Hni] += sumamp / float(count) sumamp = 0.0 count = 1 ### linear interpolate not-set bins if pprev_Hni - prev_Hni > 1: x0 = prev_Hni x1 = pprev_Hni y0 = Hn[i][prev_Hni] y1 = Hn[i][pprev_Hni] for k in xrange(prev_Hni+1, pprev_Hni): Hn[i][k] = y0 + (y1-y0)*(k-x0)/(x1-x0) #print x0, x1, y0, y1, Hn[i][pprev_Hni-1] pprev_Hni = prev_Hni prev_Hni = Hni #numpy.savetxt('bh.txt', Hn[0]) #for a in range(0, 20): # numpy.savetxt("bh-combo-%i.txt" % a, Hn[a]) #if plot: # pylab.figure() # Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0 # pylab.plot(Hn_bpms, summed_beat_histograms) # pylab.title("Beat histogram") ### time stretch, add harmonic_strengthened_bh = numpy.zeros( Hn.shape ) for i in xrange( Hn.shape[0] ): ### unchecked direct translation of marsyas stretched = numpy.zeros( Hn.shape[1] ) factor = 0.5 numSamples = Hn.shape[1] for t in xrange( Hn.shape[1] ): ni = t*factor li = int(ni) % numSamples ri = li + 1 w = ni - li if ri < numSamples: stretched[t] = Hn[i][li] + w * (Hn[i][ri] - Hn[i][li]) else: stretched[t] = Hn[t] harmonic_strengthened_bh[i] = ( Hn[i] + stretched ) numpy.savetxt("foo-%i.txt" % i, harmonic_strengthened_bh[i]) #for a in range(0, 20): # numpy.savetxt("bh-combo-%i.txt" % a, harmonic_strengthened_bh[a]) #if plot: # Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0 # pylab.plot(Hn_bpms, harmonic_strengthened_bh) ### pick top 8 candidates #peaks = [] #for i in xrange( Hn.shape[0] ): # these_peaks = find_peaks(harmonic_strengthened_bh[i], # number=8, width=11) # peaks.append(these_peaks) #summed = numpy.sum(harmonic_strengthened_bh, axis=0) #summed = numpy.sum(Hn, axis=0) if plot: pylab.figure() pylab.plot(numpy.arange(len(Hn))/4.0, Hn) # folded_hist = numpy.zeros(60*4) # for i in xrange(1, len(summed)-1): # bpm = i/4.0 # j = i # while bpm < 15: # bpm *= 2 # j *= 2 # while bpm > 30: # bpm /= 2.0 # j /= 2.0 # #j = int(round(j)) # j = int(j) # #print "%i\tto\t%i" % (i, j) # if j >= len(folded_hist): # continue # folded_hist [j] += summed[i] # ### zzz confirmed up to here peaks = [] for i in xrange( Hn.shape[0] ): these_peaks = find_peaks(harmonic_strengthened_bh[i], number=8, peak_neighbors=11) peaks.append(these_peaks / 4.0) #bpms = numpy.array(these_peaks)/4.0 # numpy.savetxt("bh-peaks-%i.txt" % i, bpms) #candidate_bpms = [ Hn_bpms[i] for i in peaks ] #print candidate_bpms #for p in peaks: # print numpy.array(p)/4 #if plot: # pylab.figure() # pylab.plot(numpy.arange(30*4, 60*4)/4.0, folded_hist[30*4:]) # pylab.show() return peaks
def onset_strength_signal(defs, wav_sr, wav_data, plot=False): ### overlapping time data # add extra window of zeros at beginning to match marsyas overlapped = overlap.sliding_window( numpy.append( numpy.zeros(defs.OSS_WINDOWSIZE - defs.OSS_HOPSIZE), wav_data), #wav_data, defs.OSS_WINDOWSIZE, defs.OSS_HOPSIZE) oss_sr = wav_sr / float(defs.OSS_HOPSIZE) if defs.OPTIONS_ONSET == 0: rms = numpy.sqrt( numpy.mean(overlapped**2, axis=1)) #dif = numpy.clip( rms[1:] - rms[:-1], 0, numpy.Inf) #return oss_sr, dif return oss_sr, rms windowed = overlapped * marsyas_hamming( #scipy.signal.get_window( "hamming", defs.OSS_WINDOWSIZE) ### log-magnitude of FFT ffts = scipy.fftpack.fft(windowed, defs.OSS_WINDOWSIZE, axis=1) ffts_abs = abs(ffts)[:,:ffts.shape[1]/2 + 1] # extra scaling to match Marsyas FFT output ffts_abs /= defs.OSS_WINDOWSIZE logmag = numpy.log(1.0 + 1000.0 * ffts_abs) #numpy.savetxt('log0.txt', logmag[0]) #numpy.savetxt('log1.txt', logmag[1]) ### flux flux = numpy.zeros( ffts_abs.shape[0] ) # output time signal prev = numpy.zeros( ffts_abs.shape[1] ) for i in xrange( 0, ffts_abs.shape[0] ): diff = logmag[i] - prev diffreduced = diff[1:] # to match Marsyas diffclipped = diffreduced.clip(min=0) prev = numpy.copy(logmag[i]) flux[i] = sum(diffclipped) #if i < 2: # print diffclipped #numpy.savetxt('flux.txt', flux) ### clear out first window #flux[0] = 0.0 if defs.OPTIONS_ONSET == 1: return oss_sr, flux if plot: ts = numpy.arange( len(flux) ) / oss_sr pylab.figure() #pylab.plot( ts, flux) ### filter if defs.OSS_LOWPASS_CUTOFF > 0: b = scipy.signal.firwin(defs.OSS_LOWPASS_N, defs.OSS_LOWPASS_CUTOFF / (oss_sr/2.0) ) filtered_flux = scipy.signal.lfilter(b, 1.0, flux) #b, a = scipy.signal.butter(2, 0.1 / (oss_sr/2.0), # btype="high") #filtered_flux = scipy.signal.filtfilt(b, a, flux) else: filtered_flux = flux if plot: ts = numpy.arange( len(filtered_flux) ) / oss_sr pylab.plot( ts, filtered_flux) pylab.title("Onset strength signal") ts = numpy.arange( len(filtered_flux) ) / oss_sr #numpy.savetxt('filtered.txt', # numpy.vstack( (ts, filtered_flux)).transpose() ) #numpy.savetxt('flux.txt', # numpy.vstack( (ts, flux)).transpose() ) if defs.OPTIONS_ONSET == 3: b, a = scipy.signal.butter(5, 5 / (oss_sr/2.0)) mean_flux = scipy.signal.filtfilt(b, a, filtered_flux) cutoff_flux = (filtered_flux - mean_flux).clip(min=0) #pylab.plot( ts, mean_flux) #pylab.plot( ts, cutoff_flux) #numpy.savetxt('cutoff.txt', # numpy.vstack( (ts, cutoff_flux)).transpose() ) return oss_sr, cutoff_flux #pylab.show() #exit(1) return oss_sr, filtered_flux
def beat_histogram(defs, oss_sr, oss_data, plot=False): ### overlap overlapped = overlap.sliding_window( #numpy.append( # numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE), # oss_data[:-2*defs.BH_HOPSIZE]), oss_data, defs.BH_WINDOWSIZE, defs.BH_HOPSIZE) #beat_histogram_sr = oss_sr / defs.BH_HOPSIZE #for i in range(len(overlapped[0])): # print overlapped[0][i] #exit(1) ### autocorrelation autocorr = autocorrelation(overlapped) ### beat histogram Hn = numpy.zeros( (autocorr.shape[0], 4*defs.BPM_MAX) ) for i in xrange( autocorr.shape[0] ): #if i > 0 and i != (defs.BH_WINDOWSIZE / defs.BH_HOPSIZE): # Hn[i] = Hn[i-1] prev_Hni = 4*defs.BPM_MAX-1 pprev_Hni = prev_Hni sumamp = 0.0 count = 1 for j in xrange(1, autocorr.shape[1]): factor = 8/2 Hni = int(oss_sr * 60.0 * factor / (j+1) + 0.5); #bpm = autocorr_bpms[i] if Hni < 4*defs.BPM_MAX: amp = autocorr[i][j] #print j, Hni, amp if amp < 0: amp = 0 if prev_Hni == Hni: sumamp += amp count += 1 else: sumamp += amp Hn[i][prev_Hni] = sumamp / float(count) sumamp = 0.0 count = 1 ### linear interpolate not-set bins if pprev_Hni - prev_Hni > 1: x0 = prev_Hni x1 = pprev_Hni y0 = Hn[i][prev_Hni] y1 = Hn[i][pprev_Hni] for k in xrange(prev_Hni+1, pprev_Hni): Hn[i][k] = y0 + (y1-y0)*(k-x0)/(x1-x0) #print x0, x1, y0, y1, Hn[i][pprev_Hni-1] pprev_Hni = prev_Hni prev_Hni = Hni #numpy.savetxt('bh.txt', Hn[0]) #for a in range(0, 20): # numpy.savetxt("bh-combo-%i.txt" % a, Hn[a]) #if plot: # pylab.figure() # Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0 # pylab.plot(Hn_bpms, summed_beat_histograms) # pylab.title("Beat histogram") ### time stretch, add harmonic_strengthened_bh = numpy.zeros( Hn.shape ) for i in xrange( Hn.shape[0] ): ### unchecked direct translation of marsyas factor2 = 0.5 factor4 = 0.25 stretched = numpy.zeros( Hn.shape[1] ) numSamples = Hn.shape[1] for t in xrange( Hn.shape[1] ): ni = t*factor2 li = int(ni) % numSamples ri = li + 1 w = ni - li #print "%i\t%i\t%f\t%f" % (li, ri, w, ni) #zzz if ri < numSamples: stretched[t] += Hn[i][li] + w * (Hn[i][ri] - Hn[i][li]) else: stretched[t] += Hn[t] ni = t*factor4 li = int(ni) % numSamples ri = li + 1 w = ni - li if ri < numSamples: stretched[t] += Hn[i][li] + w * (Hn[i][ri] - Hn[i][li]) else: stretched[t] += Hn[t] harmonic_strengthened_bh[i] = ( Hn[i] + stretched ) if defs.WRITE_BH: samps = numpy.arange(defs.BH_WINDOWSIZE) numpy.savetxt("out/aq-%i.txt" % (i+1), numpy.vstack((samps, autocorr[i])).transpose()) bpms = numpy.arange(4*defs.BPM_MAX)/4.0 numpy.savetxt("out/bh-%i.txt" % (i+1), numpy.vstack((bpms, Hn[i])).transpose()) numpy.savetxt("out/hbh-%i.txt" % (i+1), numpy.vstack((bpms, harmonic_strengthened_bh[i])).transpose()) #for a in range(0, 20): # numpy.savetxt("bh-combo-%i.txt" % a, harmonic_strengthened_bh[a]) #if plot: # Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0 # pylab.plot(Hn_bpms, harmonic_strengthened_bh) ### pick top 8 candidates #peaks = [] #for i in xrange( Hn.shape[0] ): # these_peaks = find_peaks(harmonic_strengthened_bh[i], # number=8, width=11) # peaks.append(these_peaks) #summed = numpy.sum(harmonic_strengthened_bh, axis=0) #summed = numpy.sum(Hn, axis=0) if plot: pylab.figure() sHn = numpy.sum(Hn, axis=0) sHBH = numpy.sum(harmonic_strengthened_bh, axis=0) pylab.plot(numpy.arange(len(sHn))/4.0, sHn, label="sum") pylab.plot(numpy.arange(len(sHBH))/4.0, sHBH, label="enhanced") if defs.OPTIONS_BH == 3: b, a = scipy.signal.butter(1, 0.1) filtered = scipy.signal.filtfilt(b, a, sHBH) pylab.plot(numpy.arange(len(filtered))/4.0, filtered, label="filtered") pylab.title("Summed beat histogram") # folded_hist = numpy.zeros(60*4) # for i in xrange(1, len(summed)-1): # bpm = i/4.0 # j = i # while bpm < 15: # bpm *= 2 # j *= 2 # while bpm > 30: # bpm /= 2.0 # j /= 2.0 # #j = int(round(j)) # j = int(j) # #print "%i\tto\t%i" % (i, j) # if j >= len(folded_hist): # continue # folded_hist [j] += summed[i] # if defs.WRITE_BH: combo_peaks = open('out/beat_histogram.txt', 'w') peaks = [] for i in xrange( Hn.shape[0] ): these_peaks = find_peaks(defs, harmonic_strengthened_bh[i], number=10, peak_neighbors=1) if defs.WRITE_BH: gnd = 120 has_gnd = False tl = [] for b in these_peaks: tl.append("%.2f" % (b/4.0)) if gnd*0.96*4 <= b <= gnd*1.04*4: #print "yes" has_gnd = True text = " ".join(tl) combo_peaks.write( text + "\n") if has_gnd: these_peaks = list(these_peaks) these_peaks.append(0) else: these_peaks = list(these_peaks) these_peaks.append(gnd*4) #these_peaks.append(0) #print these_peaks N = len(overlapped[i]) ts = (numpy.arange( N ) + N*i/16.0 ) / oss_sr numpy.savetxt("out/bad-bh-%i.txt" % (i+1), numpy.vstack( (ts, overlapped[i])).transpose() ) defs.extra.append(i) bpms = numpy.array(these_peaks)/4.0 bpms_strengths = [harmonic_strengthened_bh[i][4*b] for b in bpms] numpy.savetxt("out/bh-peaks-%i.txt" % (i+1), numpy.vstack((bpms, bpms_strengths)).transpose()) peaks.append( numpy.array(these_peaks) / 4.0) if defs.WRITE_BH: combo_peaks.close() #cand_peaks = find_peaks(sHn, # number=8, peak_neighbors=11) / 4.0 #pylab.plot(numpy.arange(len(sHn))/4.0, sHn) #pylab.show() #pylab.plot(cand_peaks) return peaks
def beat_phase(oss_sr, oss_data, candidate_bpms_orig, plot=False): ### overlap overlapped = overlap.sliding_window( numpy.append(numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE), oss_data), #oss_data, defs.BP_WINDOWSIZE, defs.BP_HOPSIZE) #beat_histogram_sr = oss_sr / defs.BP_HOPSIZE #print candidate_bpms_orig candidate_bpms = candidate_bpms_orig #for bpm in candidate_bpms_orig: # #print bpm, base # candidate_bpms.add(bpm) #candidate_bpms = list(candidate_bpms) #candidate_bpms.sort() #print candidate_bpms bhisto = numpy.zeros(defs.BPM_MAX) #bpms_max = numpy.zeros( len(candidate_bpms) ) #bpms_std = numpy.zeros( len(candidate_bpms) ) for i in xrange(overlapped.shape[0]): onset_scores = numpy.zeros(len(candidate_bpms)) tempo_scores = numpy.zeros(len(candidate_bpms)) for j, bpm in enumerate(candidate_bpms[i]): mag, std = calc_pulse_trains(bpm, overlapped[i], oss_sr) #bpms_max[i] += mag #bpms_std[i] += std ### correct up to here #print i, bpm, mag, std tempo_scores[j] = mag onset_scores[j] = std tempo_scores /= tempo_scores.sum() onset_scores /= onset_scores.sum() tempo_scores = tempo_scores + onset_scores tempo_scores /= tempo_scores.sum() # find best 2 scores besti = tempo_scores.argmax() bestbpm = candidate_bpms[i][besti] beststr = tempo_scores[besti] tempo_scores[besti] = 0.0 second_besti = tempo_scores.argmax() second_bestbpm = candidate_bpms[i][second_besti] second_beststr = tempo_scores[second_besti] if i >= (defs.BP_WINDOWSIZE / defs.BP_HOPSIZE): bhisto[int(bestbpm)] += beststr #bhisto[ int(second_bestbpm*4) ] += second_beststr #print bestbpm, '\t', beststr, '\t', #print second_bestbpm, '\t', second_beststr #b, a = scipy.signal.butter(4, 0.5) #filt = scipy.signal.filtfilt(b, a, bhisto) if plot: pylab.plot(numpy.arange(len(bhisto)) / 4.0, bhisto, label="marsyas") #pylab.plot(numpy.arange(len(bhisto))/4.0, filt, # label="extra filtered") pylab.title("bhisto") pylab.legend() bpm1 = bhisto.argmax() bhisto[bpm1] = 0.0 bpm2 = bhisto.argmax() return bpm1, bpm2
def beat_phase(defs, oss_sr, oss_data, candidate_bpms_orig, plot=False): ### overlap overlapped = overlap.sliding_window( #numpy.append( # numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE), # oss_data[:-2*defs.BH_HOPSIZE]), oss_data, defs.BP_WINDOWSIZE, defs.BP_HOPSIZE) #beat_histogram_sr = oss_sr / defs.BP_HOPSIZE if defs.WRITE_BP: bp_accum = open("out/bp-accum.txt", "w") #print candidate_bpms_orig candidate_bpms = candidate_bpms_orig bphase = numpy.zeros(defs.BPM_MAX) for i in xrange(overlapped.shape[0]): cands = candidate_bpms[i] onset_scores = numpy.zeros(len(cands)) tempo_scores = numpy.zeros(len(cands)) for j, bpm in enumerate(cands): if bpm == 0: continue mag, var = calc_pulse_trains(bpm, overlapped[i], oss_sr) tempo_scores[j] = mag onset_scores[j] = var if defs.WRITE_BP: numpy.savetxt("out/bp-%i.txt" % (i+1), numpy.vstack((cands, tempo_scores, onset_scores)).transpose()) tempo_scores /= tempo_scores.sum() onset_scores /= onset_scores.sum() combo_scores = tempo_scores + onset_scores combo_scores /= combo_scores.sum() # find best score besti = combo_scores.argmax() bestbpm = round(cands[besti]) beststr = combo_scores[besti] bphase[ int(bestbpm) ] += beststr if defs.WRITE_BP: #numpy.savetxt("out/bp-%i.txt" % (i+1), # numpy.vstack((cands, tempo_scores, onset_scores, combo_scores)).transpose()) #numpy.savetxt("out/bp-peak-%i.txt" % (i+1), # numpy.vstack((int(bestbpm), beststr)).transpose()) text = "%i\t%.15f\n" % (int(bestbpm), beststr) bp_accum.write(text) if defs.WRITE_BP: bp = open('out/beat_phase.txt', 'w') for b in bphase: if b == 0: text = "0\n" else: text = "%.5f\n" % b bp.write(text) bp.close() if plot: pylab.figure() pylab.plot(numpy.arange(len(bphase)), bphase, label="marsyas") pylab.title("bphase") pylab.legend() bpm = bphase.argmax() #bpm_strength = bphase[bpm] if defs.CHECK_REFERENCE: calc = bphase ref = numpy.loadtxt( "reference/%s/beat_phase.txt" % defs.basename) delta = calc - ref maxerr = numpy.abs(delta).max() if maxerr < 1e-6: print "BP ok, maximum deviation %.2g" % maxerr else: pylab.figure() pylab.title("BP: calculated - reference") pylab.plot(delta) pylab.figure() pylab.plot(calc) pylab.plot(ref) pylab.show() exit(1) if defs.WRITE_BP: bp_accum.close() return bpm, bphase