def find_peak(f0, osc_ctrl_queue, audio_in_queue, comedi, serial, alsa_stream_in): firstsamp = 0 # Location of first sample of pluck fftlen = SECONDS_PLUCK_DECAY * INPUT_RATE # Number of bins for pitch determination FFT fnb = plot_file_name(f0, serial) # Base filename for plot pngs pluck = stimulate(f0, SECONDS_PLUCK_DECAY, osc_ctrl_queue, audio_in_queue, comedi, alsa_stream_in) save_pluck_data(f0, serial, pluck) #exit(1) spectrum = fft.fft(pluck, 2*len(pluck)) #[:4*len(tofft)/2] fftlen = len(spectrum) spectrum = spectrum[:fftlen/2] sampname = fnb + "-samples.png" freqname = fnb + "-spect.png" if PLOT_TRIAL: pluckplt = BackgroundPlot(5, sampname, range(len(pluck)), pluck, title=fnb) bin_l = int((f0-50)*fftlen/INPUT_RATE) bin_h = int((f0+50)*fftlen/INPUT_RATE) estimate = estimate_in(spectrum, bin_l, bin_h) print "\n>>>>>>>> Sent %fHz; Peak estimate: %fHz\n" % (f0, estimate) if not PLOT_TRIAL : time.sleep(10) # This now should happen at top of stimulate else: freqs = [float(i)*INPUT_RATE/fftlen for i in range(bin_l, bin_h+1)] pluckplt.waitForPlot() os.chmod(sampname, 0666) gtitle = "investigating %.3fHz: estimate %f" % (f0, estimate) freqplt = BackgroundPlot(5, freqname, freqs, 20*numpy.log(abs(spectrum[bin_l:bin_h+1])), gtitle, estimate, '.-') freqplt.waitForPlot() os.chmod(freqname, 0666) return estimate
def main(): ### init comedi = comedi_interface.Comedi() comedi.send_all(0) #comedi.send(comedi_interface.CHANNEL_A0, 1) audio = alsa_interface.Audio() audio_output_lock = multiprocessing.Lock() audio_output_lock.acquire() global logfile logfile = open(LOGFILE, 'w') # Later on, we'll say (in stimulate(), actually): # audio_output_lock.release() # sleep(some time) # pluck_data = wait_left(... # and this should play the whole precomputed output block # starting the input some time into it. freq_queue, audio_in_queue = audio.begin(audio_output_lock) alsa_stream_in = audio.alsa_stream_in ### get silence if False: global silence print "getting silence..." silence = stimulate(0.0, 1*SECONDS_MEASUREMENT, freq_queue, audio_output_lock, audio_in_queue, comedi, alsa_stream_in) print "... silence gotten" wavname = "silence.wav" if FORMAT_NUMPY == numpy.int16: scipy.io.wavfile.write(wavname, INPUT_RATE, silence) else: scipy.io.wavfile.write(wavname, INPUT_RATE, numpy.int32((2**31-1)*silence)) #f0=438.0 # Expected frequency of fundamental #f0=658.0 # Expected frequency of fundamental #f0=2*658.0 #f0= .0 # Expected frequency of fundamental #f0 = 143.0 f0 = 220.0 B = 0.0 tries = LOCATE_F0_ATTEMPTS max_partials = MAX_PARTIAL series = [0] * (max_partials+1) start_partial = 1 tested_modes = [] tested_favgs = [] ### kick-start process #start_partial = 10 #tested_modes = [1, 2, 3, 4, 5, 6, 7, 8, 9] #tested_favgs = [ 439.69665405 , 879.34497282 ,1321.67762859, 1763.11055972 , 2204.01194094 , # 2649.08665505 , 3094.1608183 , 3533.91024435 , 3986.87554256] for p in range(start_partial, max_partials+1): text = "--- mode %i" % (p) logfile.write(text+"\n") logfile.flush() outfile = open("estimates-%i.txt" % p, "w") f0, B, rsquared = estimate_f0_B.estimate_B( tested_modes, tested_favgs, f0, B) f_test = partials.mode_B2freq(f0, p, B) f_avg = 0 for attempt in range(tries): f_measured = find_peak(f_test, freq_queue, audio_output_lock, audio_in_queue, comedi, attempt, alsa_stream_in) f_avg += f_measured f_test = 0.1*f_test + 0.9*f_measured outfile.write("%f\n" % f_measured) #time.sleep(10) f_avg /= tries # no, not useful tested_modes.append(p) tested_favgs.append(f_avg) if p == 1: f0 = f_test f0, B, rsquared = estimate_f0_B.estimate_B( tested_modes, tested_favgs, f0, B) #text = "Estimated string f0: %.2f\tinharmonicity B: %.3g\tR^2 \"variability\": %.3g" % (f0, B, rsquared) text = "Estimated string f0: %.2f\tinharmonicity B: %.3g\tR^2: %.3g" % (f0, B, rsquared) logfile.write(text+"\n") logfile.flush() #f0 = f0avg * (p + 1) / p series[p] = f_avg outfile.close() series = series[1:] # High pass de-glitch filter # dgfa, dgfb = sig.iirdesign(50.*0.5/INPUT_RATE, 20*0.5/INPUT_RATE, 3, 70) # (but we still save the raw data) numpy.savetxt( os.path.join(SAVE_PATH, "detected-freqs.txt"), numpy.array(series) ) exit(1) for f0_idx in range(len(series)) : f0 = series[f0_idx] for attempt in range(MEASUREMENTS) : pluck = stimulate(f0, SECONDS_MEASUREMENT, freq_queue, audio_output_lock, audio_in_queue, comedi, alsa_stream_in) save_pluck_data(f0_idx+1, attempt, pluck) if PLOT_TRIAL: fnb = plot_file_name(f0_idx+1, attempt) graphname = fnb + "-measured.png" pluckplt = BackgroundPlot(7, graphname, range(len(pluck)), pluck, title=fnb) pluckplt.waitForPlot() os.chmod(graphname, 0666) ### clean up audio.end() audio.close() logfile.close()
def find_peak(f0, osc_ctrl_queue, lock, audio_in_queue, comedi, serial, alsa_stream_in): firstsamp = 0 # Location of first sample of pluck fftlen = SECONDS_PEAKFINDER_FFT * INPUT_RATE # Number of bins for pitch determination FFT fnb = plot_file_name(f0, serial) # Base filename for plot pngs pluck = stimulate(f0, SECONDS_PEAKFINDER_FFT, osc_ctrl_queue, lock, audio_in_queue, comedi, alsa_stream_in) save_pluck_data(f0, serial, pluck) #data_un_silenced = spectral_subtraction.spectral_subtraction_arrays( # pluck, silence, INPUT_RATE) fft_points = 2*len(pluck) spectrum = fft.fft(pluck, fft_points) #[:4*len(tofft)/2] fftlen = len(spectrum) spectrum = spectrum[:fftlen/2+1] / fft_points power_spectrum = abs(spectrum)**2 sampname = fnb + "-samples.png" freqname = fnb + "-spect.png" if PLOT_TRIAL: pluckplt = BackgroundPlot(5, sampname, range(len(pluck)), pluck, title=fnb) #pylab.plot(pluck, '.-') #pylab.show() #freq_spread = 50.0 freq_spread = 5.0 bin_l = int((f0 - freq_spread)*fftlen/INPUT_RATE) bin_h = int((f0 + freq_spread)*fftlen/INPUT_RATE) bin_f0 = int((f0)*fftlen/INPUT_RATE) estimate_bin, estimate_mag = estimate_in(spectrum, bin_l, bin_h) estimate = estimate_bin #estimate, decay, estimate_mag, _, _ = chemistry.fit_lorentzian(power_spectrum, # bin_l, bin_h, bin_f0, # False, False) # #True, False) peak_dB = 10*numpy.log10(estimate_mag) decay = -1 #mean_spectral_energy = abs(spectrum).mean() #peak_energy_above_mean = ( # 20*numpy.log10(estimate_mag) - # 20*numpy.log10(mean_spectral_energy)) #print "\n>>>>>>>> Sent %fHz; Peak estimate: %fHz\n" % (f0, estimate) text = "Sent %.2fHz; Peak estimate: %.2fHz; Peak magnitude: %.2f dB; Decay rate: %.3f" % (f0, estimate, peak_dB, decay) logfile.write(text+"\n") logfile.flush() if PLOT_TRIAL : freqs = [float(i)*INPUT_RATE/fftlen for i in range(bin_l, bin_h+1)] pluckplt.waitForPlot() os.chmod(sampname, 0666) gtitle = "investigating %.3fHz: estimate %f" % (f0, estimate) freqplt = BackgroundPlot(5, freqname, freqs, 20*numpy.log10(abs(spectrum[bin_l:bin_h+1])), gtitle, estimate, '.-') freqplt.waitForPlot() os.chmod(freqname, 0666) return estimate
def main(): ### init comedi = comedi_interface.Comedi() comedi.send_all(0) #comedi.send(comedi_interface.CHANNEL_A0, 1) audio = alsa_interface.Audio() audio_input_lock = multiprocessing.Lock() audio_output_lock = multiprocessing.Lock() audio_input_lock.acquire() audio_output_lock.acquire() # Later on, we'll say: # audio_output_lock.release() # sleep(some time) # pluck_data = wait_left(6.0) # ## audio_input_lock.release() # # get some data # # When everything settles down, both processes should # # release their locks (might need some extra logic in them) # audio_input_lock.acquire() # audio_output_lock.acquire() # queue.send(next buffer of stuff) # as many times as is necessary, # and this should play the whole precomputed output block # starting the input some time into it. # Seems the separate output thread tascam_input_process # is deprecated in alsa_interface.py, so need some consultancy # on whether this is what you're thinking about. # Also need to precompute the blocks instead of using the # freq_queue stuff which might be a bit of a big change. freq_queue, audio_in_queue = audio.begin(audio_input_lock) alsa_stream_in = audio.alsa_stream_in f0=438.0 # Expected frequency of fundamental B = 0.0 tries = LOCATE_F0_ATTEMPTS max_partials = MAX_PARTIAL series = [0] * (max_partials+1) tested_modes = [] tested_favgs = [] for p in range(1, max_partials+1): outfile = open("estimates-%i.txt" % p, "w") f_test = partials.mode_B2freq(f0, p, B) f_avg = 0 for attempt in range(tries): f_measured = find_peak(f_test, freq_queue, audio_in_queue, comedi, attempt, alsa_stream_in) f_avg += f_measured f_test = 0.1*f_test + 0.9*f_measured outfile.write("%f\n" % f_measured) #time.sleep(10) f_avg /= tries tested_modes.append(p) tested_favgs.append(f_avg) f0, B, rsquared = partials.estimate_B( tested_modes, tested_favgs, f0, B) print "--------------" print "%.2f\t%.3g\t%.3g" % (f0, B, rsquared) print "--------------" #f0 = f0avg * (p + 1) / p series[p] = f_avg outfile.close() series = series[1:] # High pass de-glitch filter dgfa, dgfb = sig.iirdesign(50.*0.5/INPUT_RATE, 20*0.5/INPUT_RATE, 3, 70) numpy.savetxt( os.path.join(SAVE_PATH, "detected-freqs.txt"), numpy.array(series) ) for f0_idx in range(len(series)) : f0 = series[f0_idx] for attempt in range(MEASUREMENTS) : pluck = stimulate(f0, SECONDS_MEASUREMENT, freq_queue, audio_in_queue, comedi, alsa_stream_in) save_pluck_data(f0_idx+1, attempt, pluck) if PLOT_TRIAL: fnb = plot_file_name(f0_idx+1, attempt) graphname = fnb + "-measured.png" pluckplt = BackgroundPlot(10, graphname, range(len(pluck)), pluck, title=fnb) pluckplt.waitForPlot() os.chmod(graphname, 0666) else: time.sleep(10) ### clean up audio.end() audio.close()