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 = 0.0 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) #print B, rsquared limit = stiff_ideal_conflict.find_limit(bin_f0, B, bin_spread_below, bin_spread_above) #print B, rsquared, limit if i > limit: ok = False #print "%i\t%.2f\t%.2e\t\t%i\t%i" % ( # i, bin_f0, B, ok, lim) if ok is False: 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, 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 False: pylab.figure() 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 align_with_B(num_harmonics, bin_f0, B, ffts, noise_cutoff, bin_spread_below, bin_spread_above, sample_rate): rows, columns = ffts.shape partialss = [] idealss = [] for j in range(rows): fft = ffts[j] harmonics, ideal_harmonics = partials.get_freqs_mags(num_harmonics, bin_f0, B, fft, bin_spread_below, bin_spread_above, only_peaks=True, Bsearch=True) if harmonics is None: return bin_f0, B, None, False 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) #ns = [ h.n for h in partialss if h.n > 1 ] #ys = [ h.fft_bin / h.n for h in partialss if h.n > 1 ] 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 ] bin_f0, B, rsquared = estimate_B(ns, ys, initial_bin_f0=bin_f0, initial_B=B) if defs.B_PLOT_FIT_INDIVIDUAL: 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, sample_rate, idealss) pylab.show() return bin_f0, B, rsquared, True
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 align_with_B(num_harmonics, bin_f0, B, ffts, noise_cutoff, bin_spread_below, bin_spread_above, sample_rate): rows, columns = ffts.shape partialss = [] idealss = [] for j in range(rows): fft = ffts[j] harmonics, ideal_harmonics = partials.get_freqs_mags(num_harmonics, bin_f0, B, fft, bin_spread_below, bin_spread_above, only_peaks=True, Bsearch=True) if harmonics is None: return bin_f0, B, None, False 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) #ns = [ h.n for h in partialss if h.n > 1 ] #ys = [ h.fft_bin / h.n for h in partialss if h.n > 1 ] 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 ] ns_orig = list(ns) ys_orig = list(ys) ns = [] ys = [] weights = [] #for i, h in enumerate(partialss): # if h.n <= defs.B_MIN_HARMONIC_FIT_TO: # continue #if stiff_ideal_conflict.does_confict(bin_f0, B, # bin_spread_below, bin_spread_above, h.n): # #print "bail from conflict" # continue # ns.append( h.n ) # ys.append( h.fft_bin / h.n) # weights.append( h.mag - noise_cutoff[h.fft_bin] ) ns = ns_orig ys = ys_orig bin_f0, B, rsquared = estimate_B(ns, ys, weights, initial_bin_f0=bin_f0, initial_B=B) if defs.B_PLOT_FIT_INDIVIDUAL: 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, sample_rate, idealss) pylab.show() ok = True nums_per = [] #print '----' for n in range(1,num_harmonics+1): nums = len( [h.n for h in partialss if h.n == n]) nums_per.append(nums) #print nums, if nums_per[num_harmonics-1] < 4: #ok = False #print "bail", num_harmonics pass return bin_f0, B, rsquared, ok
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 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 align_with_B(num_harmonics, bin_f0, B, ffts, noise_cutoff, bin_spread_below, bin_spread_above, sample_rate): rows, columns = ffts.shape partialss = [] idealss = [] for j in range(rows): fft = ffts[j] harmonics, ideal_harmonics = partials.get_freqs_mags(num_harmonics, bin_f0, B, fft, bin_spread_below, bin_spread_above, only_peaks=True, Bsearch=True) if harmonics is None: return bin_f0, B, None, False 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) #ns = [ h.n for h in partialss if h.n > 1 ] #ys = [ h.fft_bin / h.n for h in partialss if h.n > 1 ] 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 ] ns_orig = list(ns) ys_orig = list(ys) ns = [] ys = [] weights = [] #for i, h in enumerate(partialss): # if h.n <= defs.B_MIN_HARMONIC_FIT_TO: # continue #if stiff_ideal_conflict.does_confict(bin_f0, B, # bin_spread_below, bin_spread_above, h.n): # #print "bail from conflict" # continue # ns.append( h.n ) # ys.append( h.fft_bin / h.n) # weights.append( h.mag - noise_cutoff[h.fft_bin] ) ns = ns_orig ys = ys_orig bin_f0, B, rsquared = estimate_B(ns, ys, weights, initial_bin_f0=bin_f0, initial_B=B) if defs.B_PLOT_FIT_INDIVIDUAL: 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, sample_rate, idealss) pylab.show() ok = True nums_per = [] #print '----' for n in range(1, num_harmonics + 1): nums = len([h.n for h in partialss if h.n == n]) nums_per.append(nums) #print nums, if nums_per[num_harmonics - 1] < 4: #ok = False #print "bail", num_harmonics pass return bin_f0, B, rsquared, ok