Пример #1
0
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)
Пример #2
0
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)
Пример #3
0
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",
        )
Пример #4
0
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")
Пример #5
0
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")
Пример #6
0
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()
Пример #7
0
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")
Пример #8
0
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
Пример #9
0
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",
            )
Пример #10
0
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)
Пример #11
0
    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)

Пример #12
0
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
Пример #13
0
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")
Пример #14
0
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
Пример #15
0
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()
Пример #16
0
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()


Пример #17
0

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)
Пример #18
0
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 
Пример #19
0
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
Пример #20
0
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()
Пример #21
0
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
Пример #22
0
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
Пример #23
0
    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
Пример #24
0
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
Пример #25
0
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