def plot_resynth(harmonics, fft, sample_rate): freqs = [ stft.bin2hertz(i, sample_rate) for i in xrange(len(fft)) ] synth_min_cutoff = 0.5 * min(numpy.where(fft>0, fft, 1)) length = len(fft) for i, sp in enumerate(harmonics): synthesized_peak = partials.qifft_synthesize(sp.fft_bin, sp.mag, sp.curvature_a, length) synthesized_peak = numpy.where( synthesized_peak > synth_min_cutoff, synthesized_peak, 0) if i == 0: pylab.plot( [ f for f, m in zip(freqs, synthesized_peak) if m > 0.0 ], stft.amplitude2db( numpy.array( [ m for f, m in zip(freqs, synthesized_peak) if m > 0.0 ], )), '.-', color="yellow", alpha=0.8, label="resynthesized peak") else: pylab.plot( [ f for f, m in zip(freqs, synthesized_peak) if m > 0.0 ], stft.amplitude2db( numpy.array( [ m for f, m in zip(freqs, synthesized_peak) if m > 0.0 ], )), '.-', color="yellow", alpha=0.8)
def plot_resynth(harmonics, fft, sample_rate): freqs = [stft.bin2hertz(i, sample_rate) for i in xrange(len(fft))] synth_min_cutoff = 0.5 * min(numpy.where(fft > 0, fft, 1)) length = len(fft) for i, sp in enumerate(harmonics): synthesized_peak = partials.qifft_synthesize(sp.fft_bin, sp.mag, sp.curvature_a, length) synthesized_peak = numpy.where(synthesized_peak > synth_min_cutoff, synthesized_peak, 0) if i == 0: pylab.plot( [f for f, m in zip(freqs, synthesized_peak) if m > 0.0], stft.amplitude2db( numpy.array([ m for f, m in zip(freqs, synthesized_peak) if m > 0.0 ], )), '.-', color="yellow", alpha=0.8, label="resynthesized peak") else: pylab.plot( [f for f, m in zip(freqs, synthesized_peak) if m > 0.0], stft.amplitude2db( numpy.array([ m for f, m in zip(freqs, synthesized_peak) if m > 0.0 ], )), '.-', color="yellow", alpha=0.8)
def plot_stft_first_n(window_number, n_windows, fft_amplitude, sample_rate, harms, wav_filename, bin_f0, B, bin_spread_below, bin_spread_above): #if window_number % 2 == 0: count = window_number + 1 color = matplotlib.cm.gnuplot(float(count) / (n_windows + 1)) #label = "%.3f seconds" % (float(count) * stft.HOPSIZE/sample_rate) bin_freqs = [ stft.bin2hertz(bin_num, sample_rate) for bin_num, amplitude in enumerate(fft_amplitude) ] harms_freqs = [ stft.bin2hertz(h.fft_bin, sample_rate) for h in harms if h.mag > 0 ] harms_mags = [stft.amplitude2db(h.mag) for h in harms if h.mag > 0] plot_ideal_lines(bin_f0, len(harms), sample_rate) plot_stiff_area(bin_f0, B, bin_spread_below, bin_spread_above, harms, sample_rate) pylab.plot( bin_freqs, stft.amplitude2db(fft_amplitude), '-', color=color, label="fft", ) pylab.plot( harms_freqs, harms_mags, 'o', color=color, label="harmonics", ) #for est in bins_estimate: # low = stft.bin2hertz(est - bin_spread, sample_rate) # high = stft.bin2hertz(est + bin_spread, sample_rate) # pylab.axvspan(low, high, color='c', alpha=0.3) if window_number >= n_windows - 1: import calc_noise initial_noise_floor, initial_noise_freqs, _, _, _ = calc_noise.get_noise( wav_filename) pylab.plot( initial_noise_freqs, stft.amplitude2db(initial_noise_floor), label="initial noise floor", color="black", )
def plot_fft(fft, sample_rate): freqs = [stft.bin2hertz(i, sample_rate) for i in xrange(len(fft))] pylab.plot([f for f, m in zip(freqs, fft) if m > 0.0], [stft.amplitude2db(m) for f, m in zip(freqs, fft) if m > 0.0], '.-', alpha=0.9, label="fft above noise")
def plot_peaks(partials, sample_rate): pylab.plot( [ stft.bin2hertz(f.fft_bin, sample_rate) for f in partials], [stft.amplitude2db(f.mag) for f in partials], 'o', color="red", label="detected peaks")
def write_harms(dest_dir, count, harm_freqs, mags, harmonics_enable): out = open(os.path.join(dest_dir,'harms-%05i.txt' % count), 'w') for harm_index in range(len(harm_freqs)): if harmonics_enable[harm_index]: if mags[harm_index] > 0.0: out.write('%g\t%g\n' % (harm_freqs[harm_index], stft.amplitude2db(mags[harm_index]))) out.close()
def plot_fft(fft, sample_rate): freqs = [ stft.bin2hertz(i, sample_rate) for i in xrange(len(fft)) ] pylab.plot( [ f for f, m in zip(freqs, fft) if m > 0.0 ], [ stft.amplitude2db(m) for f, m in zip(freqs, fft) if m > 0.0 ], '.-', alpha=0.9, label="fft above noise")
def num_above_noise(signal, noise_top): begin_above = None for i, hm in enumerate(signal): noise_top_extra = stft.db2amplitude( stft.amplitude2db(noise_top) + defs.HARMONIC_DB_ABOVE_NOISE_TOP) if hm < noise_top_extra: begin_above = i break return begin_above
def plot_stft_first_n(window_number, n_windows, fft_amplitude, sample_rate, harms, wav_filename, bin_f0, B, bin_spread_below, bin_spread_above ): #if window_number % 2 == 0: count = window_number+1 color = matplotlib.cm.gnuplot(float(count)/(n_windows+1)) #label = "%.3f seconds" % (float(count) * stft.HOPSIZE/sample_rate) bin_freqs = [ stft.bin2hertz(bin_num, sample_rate) for bin_num, amplitude in enumerate(fft_amplitude) ] harms_freqs = [ stft.bin2hertz(h.fft_bin, sample_rate) for h in harms if h.mag > 0] harms_mags = [ stft.amplitude2db(h.mag) for h in harms if h.mag > 0] plot_ideal_lines(bin_f0, len(harms), sample_rate) plot_stiff_area(bin_f0, B, bin_spread_below, bin_spread_above, harms, sample_rate) pylab.plot(bin_freqs, stft.amplitude2db(fft_amplitude), '-', color=color, label="fft", ) pylab.plot(harms_freqs, harms_mags, 'o', color=color, label="harmonics", ) #for est in bins_estimate: # low = stft.bin2hertz(est - bin_spread, sample_rate) # high = stft.bin2hertz(est + bin_spread, sample_rate) # pylab.axvspan(low, high, color='c', alpha=0.3) if window_number >= n_windows - 1: import calc_noise initial_noise_floor, initial_noise_freqs, _, _, _ = calc_noise.get_noise( wav_filename) pylab.plot(initial_noise_freqs, stft.amplitude2db(initial_noise_floor), label="initial noise floor", color="black", )
def fit_single_exponential_final(xs, ys, noise_y, decay, show=False, plot=False): def single_decay_constraints_fixed(amp1, alpha1): return numpy.array([ (1 > amp1 > 0) - 1, (alpha1 > 0) - 1, ]) def single_exponential_final(x, amp1, alpha1): if any(single_decay_constraints_fixed(amp1, alpha1) != 0): return numpy.ones(len(x)) #return numpy.log( return ( noise_y + amp1*numpy.exp(-alpha1*x) ) initial_guess = numpy.array([ ys[0]-noise_y, decay, ]) if show: print "single exponential fixed, initial:", initial_guess fit, pcov = scipy.optimize.curve_fit( single_exponential_final, #xs, numpy.log(ys), xs, ys, initial_guess, #Dfun=diff_single_exponential_final, col_deriv=1, ) if show: print "single exponential fit:", fit predicted = single_exponential_final(xs, *fit) #ys = numpy.log(ys) if show: pylab.figure() pylab.plot(ys) pylab.plot(predicted) pylab.show() ss_err = ((ys - predicted)**2).sum() ss_tot = ((ys-ys.mean())**2).sum() rsquared = 1. - (ss_err / ss_tot) ys = numpy.exp(ys) predicted = numpy.exp(predicted) try: variance = pcov[1][1] except: variance = None if show: print rsquared print "VAR:", variance if plot: pylab.figure() pylab.subplot(211) pylab.title( str("single exponential, fixed noise\nalpha:%.3f" % (fit[1]))) pylab.plot(xs, stft.amplitude2db(ys), '.') pylab.plot(xs, stft.amplitude2db(predicted)) pylab.subplot(212) pylab.plot(xs, ys, '.') pylab.plot (xs, predicted) pylab.show() return check_ok_fit(fit, rsquared, variance)
return noise, freqs, means, mins, stds if __name__ == "__main__": #noise = get_noise("noise/viola-a-noise.wav") #noise = get_noise("noise/viola-c-noise.wav") wav_filename = sys.argv[1] try: noise_filename = sys.argv[2] except: noise_filename = None noise, freqs, means, mins, stds = get_noise(wav_filename, noise_filename, recalc=True) #get_noise("sine-440-3s.wav") #print variance pylab.plot(freqs, stft.amplitude2db(noise), color="red") #pylab.plot(freqs, stft.amplitude2db(means), color="green") #pylab.plot(freqs, stft.amplitude2db(mins), color="blue") #pylab.semilogx(freqs, stft.amplitude2db(noise), color="red") #pylab.title(wav_filename) #pylab.figure() #pylab.plot(freqs, stds) pylab.show() #if False: if True: data = numpy.vstack( (freqs, stft.amplitude2db(noise)) ).transpose() save_filename = wav_filename + ".txt" numpy.savetxt( save_filename, data)
def calc_harmonics(wav_filename, f0=None, B=None, limit=defs.TOTAL_HARMONICS): if f0 is None: raise Exception("need f0 and B; run another program") # eliminate $HOME ~ and symlinks wav_filename = os.path.realpath(os.path.expanduser(wav_filename)) basename = os.path.splitext(os.path.basename(wav_filename))[0] shared_dirname = os.path.abspath( os.path.join(os.path.dirname(wav_filename), '..')) dest_dir = os.path.join(shared_dirname, "spectrum", basename) if not os.path.exists(dest_dir): os.makedirs(dest_dir) window_buffers, sample_rate = stft.get_buffers_from_file(wav_filename) freqs = [ stft.bin2hertz(i, sample_rate) for i in range(stft.WINDOWSIZE/2+1) ] ### get noise for tuning off low harmonics initial_noise_floor, initial_noise_freqs, _, _, _ = calc_noise.get_noise(wav_filename) noise_cutoff = stft.db2amplitude( stft.amplitude2db(initial_noise_floor) +defs.STFT_MIN_DB_ABOVE_NOISE) bin_f0 = stft.hertz2bin(f0, sample_rate) # radius of search area for peaks bin_spread_below = int( stft.hertz2bin(defs.STFT_PEAK_SPREAD_BELOW_HERTZ*f0, sample_rate)) bin_spread_above = int( stft.hertz2bin(defs.STFT_PEAK_SPREAD_ABOVE_HERTZ*f0, sample_rate)) bin_spread_below = 3 bin_spread_above = 3 if defs.STFT_DUMP_TEXT: write_data.write_Bs(dest_dir, sample_rate, f0, B, limit, bin_spread_below, bin_spread_above) write_data.write_ideals(dest_dir, f0, limit) # store the peaks harmonics = [None]*limit spectrums = [] table_info = tables.save_fft(basename) if table_info: harms_freqs = [] harms_mags = [] if defs.ONLY_N_WINDOWS: window_buffers = window_buffers[:defs.ONLY_N_WINDOWS] for window_number, window_buffer in enumerate(window_buffers): #print '-------- window --- %i' % window_number #fft_amplitude = stft.stft(window_buffer) fft_amplitude = stft.stft_amplitude(window_buffer) if window_number == 0: write_data.write_spectrum(dest_dir, window_number, freqs, stft.amplitude2db(fft_amplitude)) if defs.STFT_DUMP_TEXT: write_data.write_spectrum(dest_dir, window_number, freqs, stft.amplitude2db(fft_amplitude)) spectrums.append(fft_amplitude) # get harmonic peaks, and disable harmonics if can't do harms, _ = partials.get_freqs_mags( limit, bin_f0, B, fft_amplitude, bin_spread_below, bin_spread_above, only_peaks=False) if defs.STFT_PLOT_PARTIALS: plots.plot_partials(fft_amplitude, sample_rate, harms, bin_f0, B, bin_spread_below, bin_spread_above ) if defs.STFT_DUMP_TEXT: dump_freqs = numpy.zeros(limit) dump_mags = numpy.zeros(limit) if table_info: harm_freqs = [] harm_mags = [] for h in harms: i = h.n-1 if harmonics[i] is None: #print stft.bin2hertz(h.fft_bin, sample_rate), h.mag, noise_cutoff[h.fft_bin] harmonics[i] = classes.HarmonicSignal(h.n) #if use_harmonic(h, noise_cutoff, fft_amplitude, # bin_f0, B, # bin_spread_below, bin_spread_above, # ): # harmonics[i] = classes.HarmonicSignal(h.n) #else: # #print "disable harmonic ", n # harmonics[i] = False if harmonics[i] is not False: if h.mag == 0: continue if defs.STFT_DUMP_TEXT: dump_freqs[i] = stft.bin2hertz(h.fft_bin, sample_rate) dump_mags[i] = h.mag if table_info: harm_freqs.append(stft.bin2hertz(h.fft_bin, sample_rate)) harm_mags.append(h.mag) harmonics[i].mags.append(h.mag) harmonics[i].frame_numbers.append(window_number) #print harmonics[i] if table_info: harms_freqs.append(harm_freqs) harms_mags.append(harm_mags) if defs.STFT_DUMP_TEXT: #print dump_mags write_data.write_harms(dest_dir, window_number, dump_freqs, dump_mags, harmonics) if (defs.STFT_PLOT_FIRST_N > 0) and (window_number < defs.STFT_PLOT_FIRST_N): plots.plot_stft_first_n(window_number, defs.STFT_PLOT_FIRST_N, fft_amplitude, sample_rate, harms, wav_filename, bin_f0, B, bin_spread_below, bin_spread_above ) if window_number >= defs.STFT_PLOT_FIRST_N - 1: pylab.show() dh = float(defs.HOPSIZE) / sample_rate if defs.STFT_DUMP_ALL: write_data.write_stft_all(dest_dir, spectrums, freqs, dh) table_info = tables.save_fft(basename) if table_info: for ti in table_info: write_data.write_stft_3d(basename, spectrums, freqs, dh, ti, harms_freqs, harms_mags, sample_rate) # clean up harmonics harmonics = filter(lambda x: x is not False, harmonics) for h in harmonics: h.mags = numpy.array(h.mags) h.frame_numbers = numpy.array(h.frame_numbers) #pylab.plot(stft.amplitude2db(h.mags)) #pylab.show() return harmonics, dh
def plot_peaks(partials, sample_rate): pylab.plot([stft.bin2hertz(f.fft_bin, sample_rate) for f in partials], [stft.amplitude2db(f.mag) for f in partials], 'o', color="red", label="detected peaks")
def write_stft_3d(basename, spectrums, freqs, dh, info, harms_freqs, harms_mags, sample_rate): print "writing %s" % info[0] add_filename = info[0] max_seconds = info[1] min_freq = info[2] max_freq = info[3] print "min, max freq, seconds:", min_freq, max_freq, max_seconds out = open(os.path.join("out", basename+"."+add_filename+".txt"), 'w') # log scale #mag_scale = max(max(harms_mags)) mag_scale = 1.0 #print mag_scale #import pylab #pylab.plot(freqs) max_time_bin = int(max_seconds / dh) min_freq_bin = int(stft.hertz2bin(min_freq, sample_rate)) max_freq_bin = int(stft.hertz2bin(max_freq, sample_rate)) #pylab.show() print "min, max, time bins:", min_freq_bin, max_freq_bin, max_time_bin total_points_x = 10000 total_points_z = 10000 downsample_factor_x = int((max_freq_bin-min_freq_bin) / total_points_x) downsample_factor_z = int(max_time_bin / total_points_z) print "downsample factors:", downsample_factor_x, downsample_factor_z print max_seconds, max_time_bin #print max_freq_bin / downsample_factor_x, #print max_time_bin / downsample_factor_z #import pylab #pylab.plot(freqs) if downsample_factor_x > 1: fft_freqs = [ freqs[i*downsample_factor_x] for i in range(max_freq_bin/downsample_factor_x) ] else: fft_freqs = freqs #fft_freqs = [ scipy.mean(freqs[i:i+downsample_factor_x]) # for i in range(len(freqs)/downsample_factor_x) ] #scipy.signal.decimate( # freqs[min_freq_bin:max_freq_bin], # downsample_factor_x, ftype='iir') #pylab.plot(fft_freqs) #pylab.show() rows = 0 donerows = False for i, fft_amplitude in enumerate(spectrums[:max_time_bin]): if downsample_factor_z > 0: if (i % downsample_factor_z) != 0: continue if downsample_factor_x > 1: fft = [ scipy.mean(fft_amplitude[j*downsample_factor_x :(j+1)*downsample_factor_x]) for j in range(len(fft_amplitude)/downsample_factor_x) ] else: fft = fft_amplitude #fft = scipy.signal.decimate(fft_amplitude[min_freq_bin:max_freq_bin], # downsample_factor_x, ftype='fir') j = 0 k = 0 while j < len(fft_freqs): fft_freq = fft_freqs[j] #print i, k if k < len(harms_freqs[i]): harm_freq = harms_freqs[i][k] else: harm_freq = 1e100 if fft_freq < harm_freq: freq = fft_freq mag = fft[j] / mag_scale j += 1 else: freq = harm_freq if k < len(harms_freqs[i]): mag = harms_mags[i][k] / mag_scale else: mag = -1 k += 1 if freq < min_freq or freq > max_freq: continue #amplitude = fft[j] seconds = i*dh out.write("%g\t%g\t%g\n" % ( freq, seconds, stft.amplitude2db(mag))) if not donerows: rows += 1 # define end of matrix out.write("\n") donerows = True out.close() print "rows:", rows
import numpy import scipy import pylab import stft fs = 1024 seconds = 1 def make_sine(freq): num_samples = fs * seconds t = numpy.linspace(0, seconds, num_samples) w = 2 * numpy.pi * freq signal = numpy.sin(w * t) + numpy.sin(10 * w * t) return signal sig_1 = make_sine(10) fft_normalized_1 = stft.stft_amplitude(sig_1) sig_6 = make_sine(10) fft_normalized_6 = 0.5 * stft.stft_amplitude(sig_6) #pylab.plot(sig) #pylab.plot(fft_normalized_1) pylab.plot(stft.amplitude2db(fft_normalized_1)) pylab.plot(stft.amplitude2db(fft_normalized_6)) pylab.show()
import numpy import scipy import pylab import stft fs = 1024 seconds = 1 def make_sine(freq): num_samples = fs*seconds t = numpy.linspace(0, seconds, num_samples) w = 2 * numpy.pi * freq signal = numpy.sin(w*t) + numpy.sin(10*w*t) return signal sig_1 = make_sine(10) fft_normalized_1 = stft.stft_amplitude(sig_1) sig_6 = make_sine(10) fft_normalized_6 = 0.5*stft.stft_amplitude(sig_6) #pylab.plot(sig) #pylab.plot(fft_normalized_1) pylab.plot(stft.amplitude2db(fft_normalized_1)) pylab.plot(stft.amplitude2db(fft_normalized_6)) pylab.show()
if __name__ == "__main__": #noise = get_noise("noise/viola-a-noise.wav") #noise = get_noise("noise/viola-c-noise.wav") wav_filename = sys.argv[1] try: noise_filename = sys.argv[2] except: noise_filename = None noise, freqs, means, mins, stds = get_noise(wav_filename, noise_filename, recalc=True) #get_noise("sine-440-3s.wav") #print variance pylab.plot(freqs, stft.amplitude2db(noise), color="red") #pylab.plot(freqs, stft.amplitude2db(means), color="green") #pylab.plot(freqs, stft.amplitude2db(mins), color="blue") #pylab.semilogx(freqs, stft.amplitude2db(noise), color="red") #pylab.title(wav_filename) #pylab.figure() #pylab.plot(freqs, stds) pylab.show() #if False: if True: data = numpy.vstack((freqs, stft.amplitude2db(noise))).transpose() save_filename = wav_filename + ".txt" numpy.savetxt(save_filename, data)
def spectral_subtraction_arrays(data_array, noise_array, sample_rate): #data_array = data_array / float(numpy.iinfo(data_array.dtype).max) #noise_array = data_array / float(numpy.iinfo(noise_array.dtype).max) length = len(data_array) smallsize = int(len(noise_array) / length) noise_data = noise_array[:length*smallsize] noise_data = noise_data.reshape(smallsize, length) #window = scipy.signal.get_window("blackmanharris", length) window = scipy.signal.get_window("hamming", length) noise_data *= window noise_ffts = scipy.fftpack.fft(noise_data, axis=1) noise_ffts_abs = abs(noise_ffts) noise_power = noise_ffts_abs**2 means_power = numpy.mean(noise_power, axis=0) # power to dB noise_db = stft.amplitude2db( numpy.sqrt(means_power[:len(means_power)/2+1])/ length ) freqs = [stft.bin2hertz(i, sample_rate, length) for i in range(len(noise_db))] fft = scipy.fftpack.fft(data_array*window) fft_abs = abs(fft)[:len(fft)/2+1] fft_db = stft.amplitude2db( fft_abs / length ) #reconstructed = fft - mins_full #reconstructed = fft #reconstructed = numpy.zeros(len(fft), dtype=complex) #for i in range(len(reconstructed)): theta = numpy.angle(fft) alpha = 1.0 beta = 0.01 r = numpy.zeros(len(fft)) for i in range(len(fft)): r[i] = (abs(fft[i])**2 - alpha * means_power[i]) if r[i] < beta*means_power[i]: r[i] = beta * means_power[i] # else: # r[i] = numpy.sqrt(r[i]) #print r_orig[i], means_full[i], r[i] r = numpy.sqrt(r) reconstructed = ( r * numpy.cos(theta) + r * numpy.sin(theta)*1j); rec_abs = abs(reconstructed)[:len(reconstructed)/2+1] #print r_abs rec_db = stft.amplitude2db( rec_abs / length ) reconstructed_sig = scipy.fftpack.ifft(reconstructed ) reconstructed_sig /= window reconstructed_sig = numpy.real(reconstructed_sig) median_sig = scipy.signal.medfilt(rec_db, 5) median_sig_orig = scipy.signal.medfilt(fft_db, 5) if False: #if True: #pylab.plot(freqs, noise_db, label="mean noise") pylab.plot(freqs, fft_db, label="sig orig") pylab.plot(freqs, rec_db, label="reconstructed") pylab.plot(freqs, median_sig_orig, label="median orig") pylab.plot(freqs, median_sig, label="median rec.") pylab.legend() pylab.show() return reconstructed_sig
def get_bin_f0_B(bin_initial_estimate, fft_buffers, noise_cutoff, bin_spread_below, bin_spread_above, fs): ### gradually discover/refine estimates of bin_f0 and B bin_f0 = bin_initial_estimate B = 1e-4 limit = defs.TOTAL_HARMONICS for i in range(defs.B_INITIAL_PARTIALS, defs.TOTAL_HARMONICS): #print fft_buffers.shape bin_f0, B, rsquared, ok = align_with_B(i, bin_f0, B, fft_buffers, noise_cutoff, bin_spread_below, bin_spread_above, fs) limit = stiff_ideal_conflict.find_limit(bin_f0, B, bin_spread_below, bin_spread_above) #print B, rsquared, limit if i > limit: #print "warning: exceeding lim?", i, limit ok = False if defs.B_PRINT_INDIVIDUAL_BS: print "%i\t%.4f\t%.5e\t\t%i\t%i" % (i, bin_f0, B, ok, 0) if ok is False: limit = i break rows, columns = fft_buffers.shape partialss = [] idealss = [] for j in range(rows): fft = fft_buffers[j] #harmonics, ideal_harmonics = partials.get_freqs_mags(defs.TOTAL_HARMONICS, bin_f0, B, harmonics, ideal_harmonics = partials.get_freqs_mags(limit, bin_f0, B, fft, bin_spread_below, bin_spread_above, only_peaks=True, Bsearch=True) harmonics = [h for h in harmonics if h.mag > noise_cutoff[h.fft_bin]] ideal_harmonics = [ h for h in ideal_harmonics if h.mag > noise_cutoff[h.fft_bin] ] partialss.extend(harmonics) idealss.extend(ideal_harmonics) #if True: if False: pylab.figure() for j in range(rows): fft = fft_buffers[j] pylab.plot(stft.amplitude2db(fft), color="orange") xs = [h.fft_bin for h in partialss] #if h.n > defs.B_MIN_HARMONIC_FIT_TO ] ys = [h.mag for h in partialss] #if h.n > defs.B_MIN_HARMONIC_FIT_TO ] pylab.plot(xs, stft.amplitude2db(ys), 'p', color="blue") pylab.plot(stft.amplitude2db(noise_cutoff), color="black") #ns = [ h.n for h in partialss if h.n > defs.B_MIN_HARMONIC_FIT_TO ] #pylab.plot( ns, # [ h.fft_bin - partials.mode_B2freq(bin_f0, h.n, B) # for h in partialss if h.n > defs.B_MIN_HARMONIC_FIT_TO ], # '.') pylab.show() if defs.B_PLOT_FIT: ns = [h.n for h in partialss if h.n > defs.B_MIN_HARMONIC_FIT_TO] ys = [ h.fft_bin / h.n for h in partialss if h.n > defs.B_MIN_HARMONIC_FIT_TO ] omit_ns = [h.n for h in partialss if h.n <= defs.B_MIN_HARMONIC_FIT_TO] omit_ys = [ h.fft_bin / h.n for h in partialss if h.n <= defs.B_MIN_HARMONIC_FIT_TO ] plots.plot_B_fit(ns, ys, omit_ns, omit_ys, bin_f0, B, fs, idealss) pylab.show() return bin_f0, B, rsquared, partialss, limit
def spectral_subtraction(wav_filename, noise_filename): sample_rate, wav_data = scipy.io.wavfile.read(wav_filename) wav_data = wav_data / float(numpy.iinfo(wav_data.dtype).max) hopsize = len(wav_data) ##noise, freqs, means, mins, stds = calc_noise.get_noise( ## #wav_filename, noise_filename, recalc=True) # wav_filename, noise_filename, recalc=False, # bins=len(wav_data)) sample_rate, noise_data = scipy.io.wavfile.read(noise_filename) noise_data = noise_data / float(numpy.iinfo(noise_data.dtype).max) smallsize = int(len(noise_data) / hopsize) noise_data = noise_data[:hopsize*smallsize] noise_data = noise_data.reshape(smallsize, hopsize) #window = scipy.signal.get_window("blackmanharris", hopsize) window = scipy.signal.get_window("hamming", hopsize) noise_data *= window noise_ffts = scipy.fftpack.fft(noise_data, axis=1) noise_ffts_abs = abs(noise_ffts) noise_power = noise_ffts_abs**2 #mins = numpy.min(noise_ffts_abs, axis=0) #mins_full = mins #mins = mins[:len(mins)/2+1] means_power = numpy.mean(noise_power, axis=0) #means_abs = numpy.abs(means) [:len(means)/2+1] noise_db = stft.amplitude2db( numpy.sqrt(means_power[:len(means_power)/2+1])/hopsize ) #noise_db = 10*numpy.log10(means_power[:len(means_power)/2+1] / hopsize ) freqs = [float(i)*(sample_rate) / hopsize for i in range(len(noise_db))] #for i in range(len(means_abs)): # print means_abs[i] #print means_abs #print means_abs.shape #pylab.semilogy(mins) fft = scipy.fftpack.fft(wav_data*window) #fft = scipy.fftpack.fft(wav_data) fft_abs = abs(fft)[:len(fft)/2+1] #pylab.plot(noise_ffts_abs[0][:len(fft)/2+1]) #pylab.plot(noise_ffts_abs[1][:len(fft)/2+1]) #pylab.plot( numpy.sqrt(means_power[:len(fft)/2+1]) ) #pylab.plot(fft_abs) #pylab.show() #fft_power = fft_abs**2 # print len(fft) # print len(mins) fft_db = stft.amplitude2db( fft_abs / hopsize ) #reconstructed = fft - mins_full #reconstructed = fft #reconstructed = numpy.zeros(len(fft), dtype=complex) #for i in range(len(reconstructed)): theta = numpy.angle(fft) alpha = 1.0 beta = 0.1 r = numpy.zeros(len(fft)) for i in range(len(fft)): r[i] = (abs(fft[i])**2 - alpha * means_power[i]) if r[i] < 0: r[i] = beta * means_power[i] else: r[i] = numpy.sqrt(r[i]) #print r_orig[i], means_full[i], r[i] reconstructed = ( r * numpy.cos(theta) + r * numpy.sin(theta)*1j); rec_abs = abs(reconstructed)[:len(reconstructed)/2+1] #print r_abs rec_db = stft.amplitude2db( rec_abs / hopsize ) reconstructed_sig = scipy.fftpack.ifft(reconstructed ) reconstructed_sig /= window reconstructed_sig = numpy.real(reconstructed_sig) #pylab.figure() #pylab.plot(reconstructed_sig) # FIXME: don't normalize #reconstructed_sig /= max(reconstructed_sig) big = numpy.int16(reconstructed_sig * numpy.iinfo(numpy.int16).max) #pylab.figure() #pylab.plot(big) scipy.io.wavfile.write("foo.wav", sample_rate, big) if True: pylab.plot(freqs, noise_db, label="mean noise") pylab.plot(freqs, fft_db, label="sig orig") pylab.plot(freqs, rec_db, label="reconstructed") pylab.legend() pylab.show()
def partial_explanatory(fft, partial, bin_spread_below, bin_spread_above): #if partial.n < 15 and partial.n > 1: bin_target = int(partial.fft_bin) #print bin_target radius_factor = 1 wide_radius_factor = 3 wide_low = bin_target - wide_radius_factor*bin_spread_below wide_high = bin_target + wide_radius_factor*bin_spread_above+2 wide = fft[wide_low:wide_high] wide_gmean = scipy.stats.gmean(wide) local_snr = stft.amplitude2db(partial.mag / wide_gmean) #pylab.plot(wide) #pylab.show() #print bin_target bin_spread_below = 10 bin_spread_above = 10 low = bin_target - radius_factor*bin_spread_below high = bin_target + radius_factor*bin_spread_above+2 #print low, bin_target, high surrounding = fft[low:high] #synth_min_cutoff = 0.9 * min(numpy.where(fft>0, fft, 1)) synthesized_peak = qifft_synthesize(partial.fft_bin, partial.mag, partial.curvature_a, bin_spread_below+2) synthesized_peak = synthesized_peak[2:] #print synthesized_peak #synthesized_peak = synthesized_peak[low:high] #synthesized_peak = numpy.where( # synthesized_peak > synth_min_cutoff, # synthesized_peak, 0) residual = surrounding - synthesized_peak residual = numpy.sqrt(residual**2) residual_rms = numpy.sqrt( residual**2 ).mean() #residual_ratio = partial.mag / residual_rms surrounding_rms = numpy.sqrt( surrounding**2 ).mean() residual_removed = (surrounding_rms - residual_rms) / surrounding_rms explanatory = residual_removed #print partial.n, residual_ratio, residual_removed global seen_partials #if False: if True: return explanatory, local_snr elif partial.n in seen_partials: return explanatory else: seen_partials.append(partial.n) #surrounding_mean = (defs.B_HIGHER_THAN_SURROUNDING_FACTOR #if partial.n > 15: #if True: large_surrounding = fft[low-10:high+10] pylab.semilogy(numpy.arange(low, len(surrounding)+low), surrounding, '-') pylab.semilogy(partial.fft_bin, partial.mag, 'o') pylab.semilogy( numpy.array([ f for f, m in enumerate(synthesized_peak) if m > 0.0 ]) + low, numpy.array( [ m for f, m in enumerate(synthesized_peak) if m > 0.0 ], )) pylab.semilogy(numpy.arange(low, high), residual, '-') pylab.ylim([1e-6, 1e-1]) #pylab.semilogy(numpy.arange(low-10,high+10), # large_surrounding, '-') pylab.show() #exit(1) return explanatory, local_snr
def estimate_f0_B(filenames): ### ASSUME: all filenames are of the same instrument-string wav_filename = filenames[0] basename='-'.join(os.path.basename(wav_filename).split('-')[0:3]) if basename.startswith("test-440f"): return 440.0, 0, 1, 1, 1, 1 ### get initial f0 estimate base_frequency_estimate = expected_frequencies.get_freq_from_filename( wav_filename) ### get noise initial_noise_floor, initial_noise_freqs, _, _, _ = calc_noise.get_noise(wav_filename) noise_cutoff = stft.db2amplitude( stft.amplitude2db(initial_noise_floor)+defs.B_MINIMUM_HARMONIC_SNR) #### get FFT frames from audio files sample_rate = None freqs = None estimate_B_buffers_list = [] for wav_i, wav_filename in enumerate(filenames): #print wav_filename #window_buffer, sample_rate = stft.get_long_buffer_from_file(wav_filename, window_buffers, sample_rate = stft.get_buffers_from_file(wav_filename, (defs.B_NUM_BUFFERS_ESTIMATE)) if freqs is None: freqs = [ stft.bin2hertz(i, sample_rate) for i in range(stft.WINDOWSIZE/2+1) ] estimate_B_buffers_this_list = [] #fft_amplitude = stft.fft_amplitude(window_buffer, sample_rate) #estimate_B_buffers_this_list.append(fft_amplitude) for window_number in range(defs.B_NUM_BUFFERS_ESTIMATE): window_buffer = window_buffers[window_number] fft_amplitude = stft.stft_amplitude(window_buffer) estimate_B_buffers_this_list.append(fft_amplitude) estimate_B_buffers_list.extend(estimate_B_buffers_this_list) estimate_B_buffers = numpy.array(estimate_B_buffers_list) ### radius of search area for peaks # used with STFT only bin_initial_estimate = stft.hertz2bin(base_frequency_estimate, sample_rate) #bin_initial_estimate = (base_frequency_estimate # * fft_amplitude.shape[0] / (sample_rate/2) # ) #print bin_initial_estimate bin_spread_below = int(math.ceil(abs( stft.hertz2bin( (1.0-defs.B_PEAK_SPREAD_BELOW_HERTZ)*base_frequency_estimate, sample_rate) - bin_initial_estimate))) bin_spread_above = int(math.ceil( stft.hertz2bin( (1.0+defs.B_PEAK_SPREAD_ABOVE_HERTZ)*base_frequency_estimate, sample_rate) - bin_initial_estimate)) #bin_spread_below = int(round(bin_initial_estimate * # defs.B_PEAK_SPREAD_BELOW_HERTZ)) #bin_spread_above = int(round(bin_initial_estimate * # defs.B_PEAK_SPREAD_BELOW_HERTZ)) #bin_spread_below_main = int( # stft.hertz2bin(defs.STFT_PEAK_SPREAD_BELOW_HERTZ*base_frequency_estimate, # sample_rate)) #bin_spread_above_main = int( # stft.hertz2bin(defs.STFT_PEAK_SPREAD_ABOVE_HERTZ*base_frequency_estimate, # sample_rate)) ### actual estimate bin_f0, B, rsquared, harmonics, limit = get_bin_f0_B( bin_initial_estimate, estimate_B_buffers, noise_cutoff, #estimate_B_buffers, numpy.zeros(defs.LONG_WINDOWSIZE+1), bin_spread_below, bin_spread_above, sample_rate) highest_harmonic = 0 for h in harmonics: if highest_harmonic < h.n: highest_harmonic = h.n limit = min(limit, highest_harmonic) # HACK: remove limit #limit = defs.TOTAL_HARMONICS #print "limit to:", limit #harmonics_enable = [True]*defs.TOTAL_HARMONICS harmonics_enable = [True]*limit bins_estimate = [ partials.mode_B2freq(bin_f0, i, B) for i in range(1,len(harmonics_enable)+1) ] bins_naive = [ i*bin_f0 for i in range(1,len(harmonics_enable)+1) ] if defs.B_PLOT: pylab.figure() pylab.plot(initial_noise_freqs, stft.amplitude2db(initial_noise_floor), color='black') #pylab.plot(initial_noise_freqs, # stft.amplitude2db(initial_noise_floor)+defs.B_MINIMUM_HARMONIC_SNR, # color='black') pylab.xlabel("Frequency (seconds)") pylab.ylabel("Power (/ dB)") for i in range(estimate_B_buffers.shape[0]): #color = matplotlib.cm.spring(float(wav_i)/len(filenames)) #color = matplotlib.cm.RdYlGn( #color = matplotlib.cm.spring( # float(i)/len(estimate_B_buffers_this_list)) pylab.plot(freqs, stft.amplitude2db(estimate_B_buffers[i,:]), #color=color, color="orange", alpha=0.5, label=basename, ) for est in bins_estimate: low = stft.bin2hertz(est - bin_spread_below, sample_rate) high = stft.bin2hertz(est + bin_spread_above, sample_rate) if True: pylab.axvspan(low, high, color='c', alpha=0.3) else: pylab.axvline(stft.bin2hertz(est, sample_rate), color='cyan', alpha=0.3, #linewidth=2.0 ) for naive in bins_naive: freq = stft.bin2hertz(naive, sample_rate) pylab.axvline(freq, color='grey', alpha=0.2, #linewidth=2.0 ) for j, harm in enumerate(harmonics): if harm.mag == 0: continue fn = stft.bin2hertz(harm.fft_bin, sample_rate) mag = stft.amplitude2db(harm.mag) #pylab.plot(fn, mag, 'o', # color='green' # ) pylab.xlabel("Frequency") pylab.ylabel("Decibels") if defs.B_DUMP_HARMS: t_fns = [] t_mags = [] for j, harm in enumerate(harmonics): if harm.mag == 0: continue fn = stft.bin2hertz(harm.fft_bin, sample_rate) mag = stft.amplitude2db(harm.mag) t_fns.append(fn) t_mags.append(mag) data = numpy.vstack((t_fns, t_mags)).transpose() numpy.savetxt("B-harms.txt", data) if defs.B_PLOT: pylab.show() f0 = stft.bin2hertz(bin_f0, sample_rate) stiff_ideal_limit = stiff_ideal_conflict.find_limit(bin_f0, B, bin_spread_below, bin_spread_above) lim = min(stiff_ideal_limit, limit) detected_freqs = StringFreqsB(f0, B, lim) stats = StringFreqsB_stats() stats.num_files = len(filenames) stats.rsquared = rsquared stats.highest_mode_detected = limit stats.highest_mode_stiff_ideal = stiff_ideal_limit stats.basename = basename adjusted_B, delta_fn = adjust_B.adjust(basename, limit, f0, B) if adjusted_B is not None: stiff_ideal_lim_adjusted = stiff_ideal_conflict.find_limit( bin_f0, adjusted_B, bin_spread_below, bin_spread_above) lim = min(stiff_ideal_lim_adjusted, limit) adjusted_freqs = StringFreqsB(f0, adjusted_B, lim) adjusted_freqs.delta_fn = delta_fn stats.highest_mode_stiff_ideal_adjusted = stiff_ideal_lim_adjusted stats.delta_fn = delta_fn final = StringFreqsB(f0, adjusted_B, min(stats.highest_mode_detected, stats.highest_mode_stiff_ideal, stiff_ideal_lim_adjusted)) else: adjusted_freqs = None final = StringFreqsB(f0, B, min(stats.highest_mode_detected, stats.highest_mode_stiff_ideal)) return detected_freqs, adjusted_freqs, stats, final
def generate_data(self, dirname, basename, plot_harms=False): #png_dirname = os.path.join(dirname, 'png') #if not os.path.exists(png_dirname): # os.makedirs(png_dirname) if defs.ONLY_FILES_CONTAINING: search_filename = '%s*%s*wav' % ( basename, defs.ONLY_FILES_CONTAINING) else: search_filename = basename + '*.wav' filenames = glob.glob( os.path.join(dirname, search_filename)) filenames = filter(lambda x: "noise" not in x, filenames) filenames.sort() if defs.ONLY_N_FILES > 0: filenames = filenames[:defs.ONLY_N_FILES] _, _, _, final = estimate_f0_B.estimate_f0_B(filenames) f0 = final.f0 B = final.B limit = final.highest_mode stats = HarmonicsStats() stats.num_files = len(filenames) decays = [] for wav_filename_count, wav_filename in enumerate(filenames): basename = os.path.basename(wav_filename) #print "Processing", wav_filename pickle_filename = wav_filename+".stft.pickle" if os.path.exists(pickle_filename): pickle_file = open(pickle_filename, 'rb') harmonics, hop_rate = pickle.load(pickle_file) pickle_file.close() #print "... read pickle" else: #print "... calculating new" #frequency = expected_frequencies.get_freq_from_filename( # wav_filename, f0, B) harmonics, hop_rate = stft_interface.get_harmonics( wav_filename, f0, B, limit) pickle_file = open(pickle_filename, 'wb') pickle.dump( (harmonics, hop_rate), pickle_file, -1) pickle_file.close() #print "... wrote pickle" nums = tables.save_partials(os.path.splitext(basename)[0]) if nums: dest_dir = "out/" for num in nums: h = harmonics[num] #print h.n data = numpy.vstack( ( h.frame_numbers*hop_rate, stft.amplitude2db(h.mags) )).transpose() filename = dest_dir + '/partials-%s-%i.txt' % ( basename, num) numpy.savetxt( filename, data) print "Wrote to %s" % filename for i, h in enumerate(harmonics): stats.num_harms_original += 1 if len(h.mags) < 2: stats.num_harms_max_no_above_noise += 1 continue #if h.n > 0: # pylab.figure() # pylab.semilogy(h.mags, '.') # pylab.title("mode %i" % h.n) # pylab.show() #N = 16 #b, a = scipy.signal.butter(N, 0.25) #b = scipy.signal.firwin(N, 0.25) #a = 1.0 #zi = scipy.signal.lfiltic(b, a, h.mags[0:N], # h.mags[0:N]) #h.mags, zf = scipy.signal.lfilter(b, a, h.mags, # zi=zi) #pylab.semilogy(h.mags) #pylab.show() #if defs.HARMONICS_PRINT_SUMMARY: # print "n: %i\tbegin" %(h.n) noise_mean = get_noise_mean(h.mags, 0.9) #noise_top = get_noise_top(h.mags, 0.9) #frames_above = num_above_noise(h.mags, noise_top) frames_above = num_above_noise(h.mags, noise_mean) #print h.n, "above:", frames_above noise_top_extra_min = stft.db2amplitude( stft.amplitude2db(noise_mean) + defs.HARMONIC_MAX_DB_ABOVE_NOISE_TOP) if max(h.mags) < noise_top_extra_min: # print "bail noise_top_extra" # # FIXME: special stats.num_harms_max_no_above_noise += 1 continue #print h.n, frames_above if frames_above < defs.HARMONIC_MIN_HOPS_ABOVE_NOISE: stats.num_harms_num_no_above_noise += 1 #print "not enough above noise top", frames_above continue ### experiment: only take beginning #h.frame_numbers = h.frame_numbers[:frames_above] #h.mags = h.mags[:frames_above] ### experiment: test the derivative #dh_mags = numpy.zeros(len(h.mags)-1) #for i in range(0, len(h.mags)-1): # subtraction on log scale #dh_mags[i] = (h.mags[i+1] / h.mags[i]) * ( # 1.0 + h.mags[i]) # dh_mags[i] = (h.mags[i+1] - h.mags[i]) #ddh_mags = numpy.zeros(len(dh_mags)) #for i in range(0, len(dh_mags)-1): # ddh_mags[i] = dh_mags[i+1] - dh_mags[i] #dh_mags = (h.mags[1:] - h.mags[:-1]) #sub = (dh_mags > 0) ##print dh_mags * sub #num_below_zero = (dh_mags * sub).sum() #print "bad: %.3g" % (float(num_below_zero) / len(dh_mags) ) ##pylab.plot(dh_mags) ##pylab.show() #print "%.3g\t%.3g\t%.3g\t%.3g" % ( # scipy.std(dh_mags), scipy.median(dh_mags), # scipy.std(ddh_mags), scipy.median(ddh_mags)) #if h.n in defs.HARMONICS_FIT_PLOT_N: #if False: # #pylab.plot(h.mags, '-o') # pylab.plot(dh_mags, '-') # pylab.plot(ddh_mags, '-*') # #pylab.xlim([0, 30]) # # pylab.show() #exit(1) #num_harms_above_noise += 1 ts = hop_rate * h.frame_numbers if h.n == defs.HARMONICS_FIT_PLOT_N: show=True plot=False plot_last=True else: show=False plot=False plot_last=defs.HARMONICS_FIT_PLOT fit, rsquared, variance = decay_exponential.fit_best_exponential( ts, h.mags, noise_mean=noise_mean, show=show, plot=plot, plot_last=plot_last) if fit is None: stats.num_harms_no_fit += 1 print "bail from no fit" continue #alpha = fit[2] alpha = fit[1] #drop_amplitude = fit[0] / noise_mean drop_amplitude = max(h.mags) / noise_mean drop_db = stft.amplitude2db(drop_amplitude) #print drop_db #if drop_db < defs.HARMONIC_MIN_DROP_DB: # stats.num_harms_no_drop += 1 # continue if rsquared < defs.HARMONIC_FIT_MIN_RSQUARED: stats.num_harms_no_rsquared += 1 continue #if variance > defs.HARMONIC_FIT_MAX_VARIANCE: # stats.num_harms_no_variance += 1 # continue #if variance > 1.0: # continue freq = partials.mode_B2freq(f0, h.n, B) w = 2*numpy.pi*freq Q = w / (2*alpha) decay = classes.Decay(freq, w, h.n, alpha, Q, rsquared, variance, drop_db) decays.append(decay) stats.num_harms_end += 1 if defs.HARMONICS_PRINT_SUMMARY: print "n: %i\t%.1f\tdecay: %.2f\tr-squared: %.2f\tvariance: %.2f\tdrop: %.2f db" % ( h.n, freq, alpha, rsquared, variance, drop_db) #print "%s\t%i\t%i\t%i\t%i\t%i" % ( #print "%s\t%i | \t%i\t%i\t%i\t| %i" % ( # basename, # num_harms_original, # num_harms_no_above_noise, # num_harms_no_fit, # #num_harms_no_rsquared, # num_harms_no_drop, # num_harms_end, # ) print "dropped:", stats.num_harms_max_no_above_noise, stats.num_harms_num_no_above_noise, def dot_color(d): #rs = 1.0/d.variance #if rs > 10.: # rs = 10. #rs = 10*d.rsquared rs = d.drop/10.0 rss = rs/10.0 dot = '.' markersize = 5 + 5.0*(rss) color = matplotlib.cm.winter(1.-rss) return dot, color, markersize if defs.HARMONICS_PLOT_DECAYS or plot_harms: pylab.figure() for d in decays: #dot, color, markersize = dot_color(d.rsquared) dot, color, markersize = dot_color(d) pylab.plot(d.n, d.alpha, dot, color=color, markersize=markersize, linewidth=0, ) pylab.xlabel("mode") pylab.ylabel("decay rates") pylab.xlim([0, max([d.n for d in decays])+1]) #pylab.legend() if defs.HARMONICS_PLOT_Q: pylab.figure() #print "# n, loss factor, weight" for d in decays: #print "%i, %.2e, %.2e" %(d.n, 1./d.Q, d.rsquared) #dot, color, markersize = dot_color(1.0/d.variance) dot, color, markersize = dot_color(d) #if d.variance > 10 or d.rsquared < 0.25: #if d.rsquared < 0.3: # dot = 'x' # color = 'red' #else: # print d.variance pylab.plot(d.n, d.Q, dot, color=color, markersize=markersize, linewidth=0, ) pylab.xlabel("mode") pylab.ylabel("Q") pylab.xlim([0, max([d.n for d in decays])+1]) #pylab.legend() if defs.HARMONICS_PLOT_LOSS: pylab.figure() #print "# n, loss factor, weight" for d in decays: #print "%i, %.2e, %.2e" %(d.n, 1./d.Q, d.rsquared) #dot, color, markersize = dot_color(1.0/d.variance) dot, color, markersize = dot_color(d) #if d.variance > 10 or d.rsquared < 0.25: #if d.rsquared < 0.3: # dot = 'x' # color = 'red' #else: # print d.variance pylab.plot(d.n, 1.0/d.Q, dot, color=color, markersize=markersize, linewidth=0, ) pylab.xlabel("mode") pylab.ylabel("loss") pylab.xlim([0, max([d.n for d in decays])+1]) #pylab.legend() ns = [ h.n for h in decays ] stats.highest_harm = max(ns) if (defs.HARMONICS_PLOT_DECAYS or defs.HARMONICS_PLOT_Q or defs.HARMONICS_PLOT_LOSS or plot_harms): pylab.show() return decays, f0, B, stats
def get_bin_f0_B(bin_initial_estimate, fft_buffers, noise_cutoff, bin_spread_below, bin_spread_above, fs): ### gradually discover/refine estimates of bin_f0 and B bin_f0 = bin_initial_estimate B = 1e-4 limit = defs.TOTAL_HARMONICS for i in range(defs.B_INITIAL_PARTIALS, defs.TOTAL_HARMONICS): #print fft_buffers.shape bin_f0, B, rsquared, ok = align_with_B(i, bin_f0, B, fft_buffers, noise_cutoff, bin_spread_below, bin_spread_above, fs) limit = stiff_ideal_conflict.find_limit(bin_f0, B, bin_spread_below, bin_spread_above) #print B, rsquared, limit if i > limit: #print "warning: exceeding lim?", i, limit ok = False if defs.B_PRINT_INDIVIDUAL_BS: print "%i\t%.4f\t%.5e\t\t%i\t%i" % ( i, bin_f0, B, ok, 0) if ok is False: limit = i break rows, columns = fft_buffers.shape partialss = [] idealss = [] for j in range(rows): fft = fft_buffers[j] #harmonics, ideal_harmonics = partials.get_freqs_mags(defs.TOTAL_HARMONICS, bin_f0, B, harmonics, ideal_harmonics = partials.get_freqs_mags(limit, bin_f0, B, fft, bin_spread_below, bin_spread_above, only_peaks=True, Bsearch=True) harmonics = [ h for h in harmonics if h.mag > noise_cutoff[h.fft_bin] ] ideal_harmonics = [ h for h in ideal_harmonics if h.mag > noise_cutoff[h.fft_bin] ] partialss.extend(harmonics) idealss.extend(ideal_harmonics) #if True: if False: pylab.figure() for j in range(rows): fft = fft_buffers[j] pylab.plot(stft.amplitude2db(fft), color="orange") xs = [ h.fft_bin for h in partialss] #if h.n > defs.B_MIN_HARMONIC_FIT_TO ] ys = [ h.mag for h in partialss] #if h.n > defs.B_MIN_HARMONIC_FIT_TO ] pylab.plot(xs, stft.amplitude2db(ys), 'p', color="blue") pylab.plot(stft.amplitude2db(noise_cutoff), color="black") #ns = [ h.n for h in partialss if h.n > defs.B_MIN_HARMONIC_FIT_TO ] #pylab.plot( ns, # [ h.fft_bin - partials.mode_B2freq(bin_f0, h.n, B) # for h in partialss if h.n > defs.B_MIN_HARMONIC_FIT_TO ], # '.') pylab.show() if defs.B_PLOT_FIT: ns = [ h.n for h in partialss if h.n > defs.B_MIN_HARMONIC_FIT_TO ] ys = [ h.fft_bin / h.n for h in partialss if h.n > defs.B_MIN_HARMONIC_FIT_TO ] omit_ns = [ h.n for h in partialss if h.n <= defs.B_MIN_HARMONIC_FIT_TO ] omit_ys = [ h.fft_bin / h.n for h in partialss if h.n <= defs.B_MIN_HARMONIC_FIT_TO ] plots.plot_B_fit(ns, ys, omit_ns, omit_ys, bin_f0, B, fs, idealss) pylab.show() return bin_f0, B, rsquared, partialss, limit
def estimate_f0_B(filenames): ### ASSUME: all filenames are of the same instrument-string wav_filename = filenames[0] basename = '-'.join(os.path.basename(wav_filename).split('-')[0:3]) if basename.startswith("test-440f"): return 440.0, 0, 1, 1, 1, 1 ### get initial f0 estimate base_frequency_estimate = expected_frequencies.get_freq_from_filename( wav_filename) ### get noise initial_noise_floor, initial_noise_freqs, _, _, _ = calc_noise.get_noise( wav_filename) noise_cutoff = stft.db2amplitude( stft.amplitude2db(initial_noise_floor) + defs.B_MINIMUM_HARMONIC_SNR) #### get FFT frames from audio files sample_rate = None freqs = None estimate_B_buffers_list = [] for wav_i, wav_filename in enumerate(filenames): #print wav_filename #window_buffer, sample_rate = stft.get_long_buffer_from_file(wav_filename, window_buffers, sample_rate = stft.get_buffers_from_file( wav_filename, (defs.B_NUM_BUFFERS_ESTIMATE)) if freqs is None: freqs = [ stft.bin2hertz(i, sample_rate) for i in range(stft.WINDOWSIZE / 2 + 1) ] estimate_B_buffers_this_list = [] #fft_amplitude = stft.fft_amplitude(window_buffer, sample_rate) #estimate_B_buffers_this_list.append(fft_amplitude) for window_number in range(defs.B_NUM_BUFFERS_ESTIMATE): window_buffer = window_buffers[window_number] fft_amplitude = stft.stft_amplitude(window_buffer) estimate_B_buffers_this_list.append(fft_amplitude) estimate_B_buffers_list.extend(estimate_B_buffers_this_list) estimate_B_buffers = numpy.array(estimate_B_buffers_list) ### radius of search area for peaks # used with STFT only bin_initial_estimate = stft.hertz2bin(base_frequency_estimate, sample_rate) #bin_initial_estimate = (base_frequency_estimate # * fft_amplitude.shape[0] / (sample_rate/2) # ) #print bin_initial_estimate bin_spread_below = int( math.ceil( abs( stft.hertz2bin((1.0 - defs.B_PEAK_SPREAD_BELOW_HERTZ) * base_frequency_estimate, sample_rate) - bin_initial_estimate))) bin_spread_above = int( math.ceil( stft.hertz2bin((1.0 + defs.B_PEAK_SPREAD_ABOVE_HERTZ) * base_frequency_estimate, sample_rate) - bin_initial_estimate)) #bin_spread_below = int(round(bin_initial_estimate * # defs.B_PEAK_SPREAD_BELOW_HERTZ)) #bin_spread_above = int(round(bin_initial_estimate * # defs.B_PEAK_SPREAD_BELOW_HERTZ)) #bin_spread_below_main = int( # stft.hertz2bin(defs.STFT_PEAK_SPREAD_BELOW_HERTZ*base_frequency_estimate, # sample_rate)) #bin_spread_above_main = int( # stft.hertz2bin(defs.STFT_PEAK_SPREAD_ABOVE_HERTZ*base_frequency_estimate, # sample_rate)) ### actual estimate bin_f0, B, rsquared, harmonics, limit = get_bin_f0_B( bin_initial_estimate, estimate_B_buffers, noise_cutoff, #estimate_B_buffers, numpy.zeros(defs.LONG_WINDOWSIZE+1), bin_spread_below, bin_spread_above, sample_rate) highest_harmonic = 0 for h in harmonics: if highest_harmonic < h.n: highest_harmonic = h.n limit = min(limit, highest_harmonic) # HACK: remove limit #limit = defs.TOTAL_HARMONICS #print "limit to:", limit #harmonics_enable = [True]*defs.TOTAL_HARMONICS harmonics_enable = [True] * limit bins_estimate = [ partials.mode_B2freq(bin_f0, i, B) for i in range(1, len(harmonics_enable) + 1) ] bins_naive = [i * bin_f0 for i in range(1, len(harmonics_enable) + 1)] if defs.B_PLOT: pylab.figure() pylab.plot(initial_noise_freqs, stft.amplitude2db(initial_noise_floor), color='black') #pylab.plot(initial_noise_freqs, # stft.amplitude2db(initial_noise_floor)+defs.B_MINIMUM_HARMONIC_SNR, # color='black') pylab.xlabel("Frequency (seconds)") pylab.ylabel("Power (/ dB)") for i in range(estimate_B_buffers.shape[0]): #color = matplotlib.cm.spring(float(wav_i)/len(filenames)) #color = matplotlib.cm.RdYlGn( #color = matplotlib.cm.spring( # float(i)/len(estimate_B_buffers_this_list)) pylab.plot( freqs, stft.amplitude2db(estimate_B_buffers[i, :]), #color=color, color="orange", alpha=0.5, label=basename, ) for est in bins_estimate: low = stft.bin2hertz(est - bin_spread_below, sample_rate) high = stft.bin2hertz(est + bin_spread_above, sample_rate) if True: pylab.axvspan(low, high, color='c', alpha=0.3) else: pylab.axvline( stft.bin2hertz(est, sample_rate), color='cyan', alpha=0.3, #linewidth=2.0 ) for naive in bins_naive: freq = stft.bin2hertz(naive, sample_rate) pylab.axvline( freq, color='grey', alpha=0.2, #linewidth=2.0 ) for j, harm in enumerate(harmonics): if harm.mag == 0: continue fn = stft.bin2hertz(harm.fft_bin, sample_rate) mag = stft.amplitude2db(harm.mag) #pylab.plot(fn, mag, 'o', # color='green' # ) pylab.xlabel("Frequency") pylab.ylabel("Decibels") if defs.B_DUMP_HARMS: t_fns = [] t_mags = [] for j, harm in enumerate(harmonics): if harm.mag == 0: continue fn = stft.bin2hertz(harm.fft_bin, sample_rate) mag = stft.amplitude2db(harm.mag) t_fns.append(fn) t_mags.append(mag) data = numpy.vstack((t_fns, t_mags)).transpose() numpy.savetxt("B-harms.txt", data) if defs.B_PLOT: pylab.show() f0 = stft.bin2hertz(bin_f0, sample_rate) stiff_ideal_limit = stiff_ideal_conflict.find_limit( bin_f0, B, bin_spread_below, bin_spread_above) lim = min(stiff_ideal_limit, limit) detected_freqs = StringFreqsB(f0, B, lim) stats = StringFreqsB_stats() stats.num_files = len(filenames) stats.rsquared = rsquared stats.highest_mode_detected = limit stats.highest_mode_stiff_ideal = stiff_ideal_limit stats.basename = basename adjusted_B, delta_fn = adjust_B.adjust(basename, limit, f0, B) if adjusted_B is not None: stiff_ideal_lim_adjusted = stiff_ideal_conflict.find_limit( bin_f0, adjusted_B, bin_spread_below, bin_spread_above) lim = min(stiff_ideal_lim_adjusted, limit) adjusted_freqs = StringFreqsB(f0, adjusted_B, lim) adjusted_freqs.delta_fn = delta_fn stats.highest_mode_stiff_ideal_adjusted = stiff_ideal_lim_adjusted stats.delta_fn = delta_fn final = StringFreqsB( f0, adjusted_B, min(stats.highest_mode_detected, stats.highest_mode_stiff_ideal, stiff_ideal_lim_adjusted)) else: adjusted_freqs = None final = StringFreqsB( f0, B, min(stats.highest_mode_detected, stats.highest_mode_stiff_ideal)) return detected_freqs, adjusted_freqs, stats, final