예제 #1
0
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
예제 #2
0
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()
예제 #3
0
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
예제 #4
0
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()