Example #1
0
def beat_phase(defs, oss_sr, oss_data, candidate_bpms_orig, plot=False):
    ### overlap
    overlapped = overlap.sliding_window(
        #numpy.append(
        #    numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE),
        #    oss_data[:-2*defs.BH_HOPSIZE]),
        oss_data,
        defs.BP_WINDOWSIZE, defs.BP_HOPSIZE)
    #beat_histogram_sr = oss_sr / defs.BP_HOPSIZE

    #print candidate_bpms_orig
    candidate_bpms = candidate_bpms_orig
    bphase = numpy.zeros(defs.BPM_MAX)
    for i in xrange(overlapped.shape[0]):
        cands = candidate_bpms[i]
        onset_scores = numpy.zeros(len(cands))
        tempo_scores = numpy.zeros(len(cands))
        for j, bpm in enumerate(cands):
        #for j, bpm in enumerate(candidate_bpms):
            mag, std = calc_pulse_trains(bpm, overlapped[i], oss_sr)
            #bpms_max[i] += mag
            #bpms_std[i] += std
            ### correct up to here
            #print i, bpm, mag, std
            tempo_scores[j] = mag
            #print tempo_scores[j]
            onset_scores[j] = std
        tempo_scores /= tempo_scores.sum()
        onset_scores /= onset_scores.sum()

        tempo_scores = tempo_scores + onset_scores
        tempo_scores /= tempo_scores.sum()

        # find best 2 scores
        besti = tempo_scores.argmax()
        bestbpm = round(cands[besti])
        #bestbpm = candidate_bpms[besti]
        #print candidate_bpms[i]
        #print tempo_scores
        beststr = tempo_scores[besti]
        #tempo_scores[besti] = 0.0
        #second_besti = tempo_scores.argmax()
        #second_bestbpm = candidate_bpms[i][second_besti]
        #second_beststr = tempo_scores[second_besti]

        #if i >= (defs.BP_WINDOWSIZE / defs.BP_HOPSIZE):
        bphase[ int(bestbpm) ] += beststr
        #print bestbpm, "\t", beststr

        if defs.WRITE_BP:
            numpy.savetxt("out/bp-%i.txt" % (i+1),
                numpy.vstack((candidate_bpms[i], tempo_scores)).transpose())
            numpy.savetxt("out/bp-peak-%i.txt" % (i+1),
                numpy.vstack((int(bestbpm), beststr)).transpose())

    if defs.WRITE_BP:
        bp = open('out/beat_phase.txt', 'w')
        for b in bphase:
            if b == 0:
                text = "0\n"
            else:
                text = "%.5f\n" % b
            bp.write(text)
        bp.close()

    if plot:
        pylab.figure()
        pylab.plot(numpy.arange(len(bphase)), bphase,
            label="marsyas")
        pylab.title("bphase")
        pylab.legend()

    bpm = bphase.argmax()
    bpm_strength = bphase[bpm]

    return bpm, bphase
def onset_strength_signal(wav_sr, wav_data, plot=False):
    ### overlapping time data
    # add extra window of zeros at beginning to match marsyas
    overlapped = overlap.sliding_window(
        numpy.append(
            numpy.zeros(defs.OSS_WINDOWSIZE - defs.OSS_HOPSIZE),
            wav_data),
        #wav_data,
        defs.OSS_WINDOWSIZE, defs.OSS_HOPSIZE)
    oss_sr = wav_sr / float(defs.OSS_HOPSIZE)
    windowed = overlapped * marsyas_hamming(
        #scipy.signal.get_window( "hamming",
        defs.OSS_WINDOWSIZE)

    ### log-magnitude of FFT
    ffts = scipy.fftpack.fft(windowed, defs.OSS_WINDOWSIZE,  axis=1)
    ffts_abs = abs(ffts)[:,:ffts.shape[1]/2 + 1]
    # extra scaling to match Marsyas FFT output
    ffts_abs /= defs.OSS_WINDOWSIZE
    logmag = numpy.log(1.0 + 1000.0 * ffts_abs)

    #numpy.savetxt('log0.txt', logmag[0])
    #numpy.savetxt('log1.txt', logmag[1])

    ### flux
    flux = numpy.zeros( ffts_abs.shape[0] ) # output time signal
    prev = numpy.zeros( ffts_abs.shape[1] )
    for i in xrange( 0, ffts_abs.shape[0] ):
        diff = logmag[i] - prev
        diffreduced = diff[1:] # to match Marsyas
        diffclipped = diffreduced.clip(min=0)
        prev = numpy.copy(logmag[i])
        flux[i] = sum(diffclipped)
        #if i < 2:
        #    print diffclipped

    #numpy.savetxt('flux.txt', flux)
    ### clear out first window
    #flux[0] = 0.0

    if plot:
        ts = numpy.arange( len(flux) ) / oss_sr
        pylab.figure()
        pylab.plot( ts, flux)
    ### filter
    if defs.OSS_LOWPASS_CUTOFF > 0:
        b = scipy.signal.firwin(defs.OSS_LOWPASS_N,
            defs.OSS_LOWPASS_CUTOFF / (oss_sr/2.0) )
    #b, a = scipy.signal.butter(2, defs.OSS_LOWPASS_CUTOFF / (oss_sr/2.0) )
    #filtered_flux = scipy.signal.filtfilt(b, a, flux)
    #a = numpy.zeros(defs.OSS_LOWPASS_N)
    #a[0] = 1.0
        filtered_flux = scipy.signal.lfilter(b, 1.0, flux)
    else:
        filtered_flux = flux

    #numpy.savetxt('filtered.txt', filtered_flux)

    if plot:
        ts = numpy.arange( len(filtered_flux) ) / oss_sr
        pylab.plot( ts, filtered_flux)
        pylab.title("Onset strength signal")
    return oss_sr, filtered_flux
Example #3
0
def beat_histogram(defs, oss_sr, oss_data, plot=False):
    ### overlap
    overlapped = overlap.sliding_window(
        #numpy.append(
        #    numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE),
        #    oss_data[:-2*defs.BH_HOPSIZE]),
        oss_data,
        defs.BH_WINDOWSIZE,
        defs.BH_HOPSIZE)
    #beat_histogram_sr = oss_sr / defs.BH_HOPSIZE
    #for i in range(len(overlapped[0])):
    #    print overlapped[0][i]
    #exit(1)

    ### autocorrelation
    autocorr = autocorrelation(overlapped)

    ### beat histogram
    Hn = numpy.zeros((autocorr.shape[0], 4 * defs.BPM_MAX))
    for i in xrange(autocorr.shape[0]):
        #if i > 0 and i != (defs.BH_WINDOWSIZE / defs.BH_HOPSIZE):
        #    Hn[i] = Hn[i-1]
        prev_Hni = 4 * defs.BPM_MAX - 1
        pprev_Hni = prev_Hni
        sumamp = 0.0
        count = 1

        for j in xrange(1, autocorr.shape[1]):
            factor = 8 / 2
            Hni = int(oss_sr * 60.0 * factor / (j + 1) + 0.5)
            #bpm = autocorr_bpms[i]
            if Hni < 4 * defs.BPM_MAX:
                amp = autocorr[i][j]
                #print j, Hni, amp
                if amp < 0:
                    amp = 0
                if prev_Hni == Hni:
                    sumamp += amp
                    count += 1
                else:
                    sumamp += amp
                    Hn[i][prev_Hni] = sumamp / float(count)
                    sumamp = 0.0
                    count = 1
                ### linear interpolate not-set bins
                if pprev_Hni - prev_Hni > 1:
                    x0 = prev_Hni
                    x1 = pprev_Hni
                    y0 = Hn[i][prev_Hni]
                    y1 = Hn[i][pprev_Hni]
                    for k in xrange(prev_Hni + 1, pprev_Hni):
                        Hn[i][k] = y0 + (y1 - y0) * (k - x0) / (x1 - x0)
                    #print x0, x1, y0, y1, Hn[i][pprev_Hni-1]
                pprev_Hni = prev_Hni
                prev_Hni = Hni
    #numpy.savetxt('bh.txt', Hn[0])

    #for a in range(0, 20):
    #    numpy.savetxt("bh-combo-%i.txt" % a, Hn[a])

    #if plot:
    #    pylab.figure()
    #    Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0
    #    pylab.plot(Hn_bpms, summed_beat_histograms)
    #    pylab.title("Beat histogram")

    ### time stretch, add
    harmonic_strengthened_bh = numpy.zeros(Hn.shape)
    for i in xrange(Hn.shape[0]):
        ### unchecked direct translation of marsyas
        factor2 = 0.5
        factor4 = 0.25
        stretched = numpy.zeros(Hn.shape[1])
        numSamples = Hn.shape[1]
        for t in xrange(Hn.shape[1]):
            ni = t * factor2
            li = int(ni) % numSamples
            ri = li + 1
            w = ni - li
            #print "%i\t%i\t%f\t%f" % (li, ri, w, ni)
            #zzz
            if ri < numSamples:
                stretched[t] += Hn[i][li] + w * (Hn[i][ri] - Hn[i][li])
            else:
                stretched[t] += Hn[t]

            ni = t * factor4
            li = int(ni) % numSamples
            ri = li + 1
            w = ni - li
            if ri < numSamples:
                stretched[t] += Hn[i][li] + w * (Hn[i][ri] - Hn[i][li])
            else:
                stretched[t] += Hn[t]
        harmonic_strengthened_bh[i] = (Hn[i] + stretched)

        if defs.WRITE_BH:
            samps = numpy.arange(defs.BH_WINDOWSIZE)
            numpy.savetxt("out/aq-%i.txt" % (i + 1),
                          numpy.vstack((samps, autocorr[i])).transpose())
            bpms = numpy.arange(4 * defs.BPM_MAX) / 4.0
            numpy.savetxt("out/bh-%i.txt" % (i + 1),
                          numpy.vstack((bpms, Hn[i])).transpose())
            numpy.savetxt(
                "out/hbh-%i.txt" % (i + 1),
                numpy.vstack((bpms, harmonic_strengthened_bh[i])).transpose())

    #for a in range(0, 20):
    #    numpy.savetxt("bh-combo-%i.txt" % a, harmonic_strengthened_bh[a])

    #if plot:
    #    Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0
    #    pylab.plot(Hn_bpms, harmonic_strengthened_bh)

    ### pick top 8 candidates
    #peaks = []
    #for i in xrange( Hn.shape[0] ):
    #    these_peaks = find_peaks(harmonic_strengthened_bh[i],
    #        number=8, width=11)
    #    peaks.append(these_peaks)

    #summed = numpy.sum(harmonic_strengthened_bh, axis=0)
    #summed = numpy.sum(Hn, axis=0)

    if plot:
        pylab.figure()
        sHn = numpy.sum(Hn, axis=0)
        sHBH = numpy.sum(harmonic_strengthened_bh, axis=0)
        pylab.plot(numpy.arange(len(sHn)) / 4.0, sHn, label="sum")
        pylab.plot(numpy.arange(len(sHBH)) / 4.0, sHBH, label="enhanced")
        if defs.OPTIONS_BH == 3:
            b, a = scipy.signal.butter(1, 0.1)
            filtered = scipy.signal.filtfilt(b, a, sHBH)
            pylab.plot(numpy.arange(len(filtered)) / 4.0,
                       filtered,
                       label="filtered")
        pylab.title("Summed beat histogram")

#    folded_hist = numpy.zeros(60*4)
#    for i in xrange(1, len(summed)-1):
#        bpm = i/4.0
#        j = i
#        while bpm < 15:
#            bpm *= 2
#            j *= 2
#        while bpm > 30:
#            bpm /= 2.0
#            j /= 2.0
#        #j = int(round(j))
#        j = int(j)
#        #print "%i\tto\t%i" % (i, j)
#        if j >= len(folded_hist):
#            continue
#        folded_hist [j] += summed[i]
#

    if defs.WRITE_BH:
        combo_peaks = open('out/beat_histogram.txt', 'w')
    peaks = []
    bh_total = numpy.zeros((Hn.shape[0], 10))
    for i in xrange(Hn.shape[0]):
        these_peaks = find_peaks(defs,
                                 harmonic_strengthened_bh[i],
                                 number=10,
                                 peak_neighbors=1)
        bh_total[i, :] = these_peaks
        if defs.WRITE_BH:
            tl = []
            for b in these_peaks:
                tl.append("%.2f" % (b / 4.0))
            text = "  ".join(tl)
            combo_peaks.write(text + "\n")
            bpms = numpy.array(these_peaks) / 4.0
            bpms_strengths = [harmonic_strengthened_bh[i][4 * b] for b in bpms]
            numpy.savetxt("out/bh-peaks-%i.txt" % (i + 1),
                          numpy.vstack((bpms, bpms_strengths)).transpose())
        peaks.append(numpy.array(these_peaks) / 4.0)
    if defs.WRITE_BH:
        combo_peaks.close()

    if defs.CHECK_REFERENCE:
        calc = bh_total / 4.0
        ref = numpy.loadtxt("reference/%s/beat_histogram.txt" % defs.basename)
        delta = calc - ref
        maxerr = numpy.abs(delta).max()
        if maxerr < 1e-12:
            print "BH ok, maximum deviation %.2g" % maxerr
        else:
            pylab.figure()
            pylab.title("BH: calculated - reference")
            pylab.plot(delta)
            pylab.show()
            exit(1)
    #cand_peaks = find_peaks(sHn,
    #        number=8, peak_neighbors=11) / 4.0
    #pylab.plot(numpy.arange(len(sHn))/4.0, sHn)
    #pylab.show()
    #pylab.plot(cand_peaks)
    return peaks
def onset_strength_signal(defs, wav_sr, wav_data, plot=False):
    ### overlapping time data
    # add extra window of zeros at beginning to match marsyas
    overlapped = overlap.sliding_window(
        numpy.append(
            numpy.zeros(defs.OSS_WINDOWSIZE - defs.OSS_HOPSIZE),
            wav_data),
        #wav_data,
        defs.OSS_WINDOWSIZE, defs.OSS_HOPSIZE)
    oss_sr = wav_sr / float(defs.OSS_HOPSIZE)
    #print oss_sr
    if defs.OPTIONS_ONSET == 0:
        rms = numpy.sqrt( numpy.mean(overlapped**2, axis=1))
        #dif = numpy.clip( rms[1:] - rms[:-1], 0, numpy.Inf)
        #return oss_sr, dif
        return oss_sr, rms


    windowed = overlapped * marsyas_hamming(
        #scipy.signal.get_window( "hamming",
        defs.OSS_WINDOWSIZE)

    ### log-magnitude of FFT
    ffts = scipy.fftpack.fft(windowed, defs.OSS_WINDOWSIZE, axis=1)
    ffts_abs = abs(ffts)[:,:ffts.shape[1]/2 + 1]
    # extra scaling to match Marsyas FFT output
    ffts_abs /= defs.OSS_WINDOWSIZE
    logmag = numpy.log(1.0 + 1000.0 * ffts_abs)

    ### flux
    flux = numpy.zeros( ffts_abs.shape[0] ) # output time signal
    prev = numpy.zeros( ffts_abs.shape[1] )
    for i in xrange( 0, ffts_abs.shape[0] ):
        diff = logmag[i] - prev
        diffreduced = diff[1:] # to match Marsyas
        diffclipped = diffreduced.clip(min=0)
        prev = numpy.copy(logmag[i])
        flux[i] = sum(diffclipped)
        #if i < 2:
        #    print diffclipped

    #if True:
    #    ts = numpy.arange(len(flux)-1) / oss_sr
    #    pylab.plot(ts, flux[1:], color="red")

    #numpy.savetxt('flux.txt', flux)
    ### clear out first window
    #flux[0] = 0.0
    if defs.OPTIONS_ONSET == 1:
        return oss_sr, flux


    if plot:
        ts = numpy.arange( len(flux) ) / oss_sr
        pylab.figure()
        #pylab.plot( ts, flux)
    ### filter
    if defs.OSS_LOWPASS_CUTOFF > 0 and defs.OPTIONS_ONSET < 3:
        b = scipy.signal.firwin(defs.OSS_LOWPASS_N,
            defs.OSS_LOWPASS_CUTOFF / (oss_sr/2.0) )
        #print b
        filtered_flux = scipy.signal.lfilter(b, 1.0, flux)

        #b, a = scipy.signal.butter(2, 0.1 / (oss_sr/2.0),
        #    btype="high")
        #filtered_flux = scipy.signal.filtfilt(b, a, flux)
    else:
        filtered_flux = flux

    if plot:
        ts = numpy.arange( len(filtered_flux) ) / oss_sr
        pylab.plot( ts, filtered_flux, label="filtered")
        pylab.title("Onset strength signal")

    ts = numpy.arange( len(filtered_flux) ) / oss_sr
    if defs.WRITE_ONSETS:
        #cutoff = int(2048*128/44100.0 * oss_sr)
        cutoff = 2048
        #print "cutoff", cutoff
        #print logmag.shape
        logmag_short = logmag[:cutoff,]
        #print logmag_short.shape
        numpy.savetxt('out/logmag.txt',
            logmag_short.transpose())
            #logmag[:cutoff,].transpose())

        numpy.savetxt('out/flux.txt',
            numpy.vstack( (ts, flux)).transpose() )
        numpy.savetxt('out/onset_strength.txt',
            numpy.vstack( (ts, filtered_flux)).transpose() )


    num_bh_frames = int(len(filtered_flux) / defs.BH_HOPSIZE)
    filtered_flux = filtered_flux[:num_bh_frames * defs.BH_HOPSIZE]

    if defs.CHECK_REFERENCE:
        calc = filtered_flux
        ref = numpy.loadtxt(
            "reference/OSS-4-filter.txt")
        delta = calc - ref
        maxerr = max(abs(delta))
        if maxerr < 1e-12:
            print "OSS ok, maximum deviation %.2g" % maxerr
        else:
            pylab.figure()
            pylab.title("OSS: calculated - reference")
            pylab.plot(delta)
            pylab.show()
            exit(1)
    if plot:
        pylab.legend()
    return oss_sr, filtered_flux
def beat_period_detection(defs,
                          oss_sr,
                          oss_data,
                          plot=False,
                          limit_pulse_trains=False,
                          skip_calc_pulse_trains=False,
                          intermediate_data=False):
    ### 1) Overlap
    overlapped = overlap.sliding_window(
        #numpy.append(
        #    numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE),
        #    oss_data[:-2*defs.BH_HOPSIZE]),
        oss_data,
        defs.BH_WINDOWSIZE,
        defs.BH_HOPSIZE,
        zeroPad=True)
    #beat_period_sr = oss_sr / defs.BH_HOPSIZE

    ### 2) Generalized Autocorrelation
    autocorr = autocorrelation(overlapped)

    minlag = int(oss_sr * 60.0 / defs.BPM_MAX)
    maxlag = int(oss_sr * 60.0 / defs.BPM_MIN) + 1

    num_frames = autocorr.shape[0]
    #win_size = autocorr.shape[1]

    ### 3) Enhance Harmonics
    harmonic_enhanced = numpy.zeros(autocorr.shape)
    for i in xrange(num_frames):
        auto = autocorr[i]
        stretched = numpy.zeros(defs.BH_WINDOWSIZE)
        for j in xrange(512):
            stretched[j] = auto[2 * j] + auto[4 * j]
        harmonic_enhanced[i] = (auto + stretched)

    ### 4) Pick peaks
    peaks = numpy.zeros((num_frames, 10))
    for i in xrange(num_frames):
        these_peaks = find_peaks(defs,
                                 harmonic_enhanced[i],
                                 number=10,
                                 peak_neighbors=1,
                                 minsample=minlag,
                                 maxsample=maxlag)
        peaks[i, :] = these_peaks

    ### 5) Evaluate pulse trains
    tempo_lags = numpy.zeros(num_frames)
    for i in xrange(num_frames):
        cands = peaks[i]
        onset_scores = numpy.zeros(len(cands))
        tempo_scores = numpy.zeros(len(cands))
        for j, cand in enumerate(cands):
            if cand == 0:
                continue
            lag = int(round(cand))
            if not skip_calc_pulse_trains:
                mag, var = calc_pulse_trains(
                    lag, overlapped[i], limit_pulse_trains=limit_pulse_trains)
            else:
                mag = 0.0
                var = 0.0
            tempo_scores[j] = mag
            onset_scores[j] = var
        tempo_scores /= tempo_scores.sum()
        onset_scores /= onset_scores.sum()

        combo_scores = tempo_scores + onset_scores
        combo_scores /= combo_scores.sum()

        # find best score
        besti = combo_scores.argmax()
        bestlag = round(cands[besti])

        tempo_lags[i] = bestlag

    if defs.CHECK_REFERENCE:
        ref = numpy.loadtxt("reference/BEATS-5-pulse.txt")
        delta = tempo_lags - ref
        maxerr = numpy.abs(delta).max()
        if maxerr < 1e-12:
            print "Beat pulse detection ok, maximum deviation %.2g" % maxerr
        else:
            pylab.figure()
            pylab.title("Beat pulse detection: this - reference")
            pylab.plot(delta)
            pylab.show()
            exit(1)

    if not intermediate_data:
        return tempo_lags
    else:
        return tempo_lags, peaks, autocorr, harmonic_enhanced, overlapped
def beat_histogram(oss_sr, oss_data, plot=False):
    ### overlap
    overlapped = overlap.sliding_window(
        numpy.append(numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE),
                     oss_data),
        #oss_data,
        defs.BH_WINDOWSIZE,
        defs.BH_HOPSIZE)
    #beat_histogram_sr = oss_sr / defs.BH_HOPSIZE

    ### autocorrelation
    autocorr = autocorrelation(overlapped)

    ### beat histogram
    Hn = numpy.zeros((autocorr.shape[0], 4 * defs.BPM_MAX))
    for i in xrange(autocorr.shape[0]):
        if i > 0 and i != (defs.BH_WINDOWSIZE / defs.BH_HOPSIZE):
            Hn[i] = Hn[i - 1]
        prev_Hni = 4 * defs.BPM_MAX - 1
        pprev_Hni = prev_Hni
        sumamp = 0.0
        count = 1

        for j in xrange(1, autocorr.shape[1]):
            factor = 8 / 2
            Hni = int((oss_sr * 60.0 * factor / (j + 1)) + 0.5)
            #bpm = autocorr_bpms[i]
            if Hni < 4 * defs.BPM_MAX and Hni > 40:
                amp = autocorr[i][j]
                if amp < 0:
                    amp = 0
                if prev_Hni == Hni:
                    sumamp += amp
                    count += 1
                else:
                    sumamp += amp
                    Hn[i][prev_Hni] += sumamp / float(count)
                    sumamp = 0.0
                    count = 1
                ### linear interpolate not-set bins
                if pprev_Hni - prev_Hni > 1:
                    x0 = prev_Hni
                    x1 = pprev_Hni
                    y0 = Hn[i][prev_Hni]
                    y1 = Hn[i][pprev_Hni]
                    for k in xrange(prev_Hni + 1, pprev_Hni):
                        Hn[i][k] = y0 + (y1 - y0) * (k - x0) / (x1 - x0)
                    #print x0, x1, y0, y1, Hn[i][pprev_Hni-1]
                pprev_Hni = prev_Hni
                prev_Hni = Hni
    #numpy.savetxt('bh.txt', Hn[0])

    #for a in range(0, 20):
    #    numpy.savetxt("bh-combo-%i.txt" % a, Hn[a])

    #if plot:
    #    pylab.figure()
    #    Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0
    #    pylab.plot(Hn_bpms, summed_beat_histograms)
    #    pylab.title("Beat histogram")

    ### time stretch, add
    harmonic_strengthened_bh = numpy.zeros(Hn.shape)
    for i in xrange(Hn.shape[0]):
        ### unchecked direct translation of marsyas
        stretched = numpy.zeros(Hn.shape[1])
        factor = 0.5
        numSamples = Hn.shape[1]
        for t in xrange(Hn.shape[1]):
            ni = t * factor
            li = int(ni) % numSamples
            ri = li + 1
            w = ni - li
            if ri < numSamples:
                stretched[t] = Hn[i][li] + w * (Hn[i][ri] - Hn[i][li])
            else:
                stretched[t] = Hn[t]
        harmonic_strengthened_bh[i] = (Hn[i] + stretched)

        numpy.savetxt("foo-%i.txt" % i, harmonic_strengthened_bh[i])

    #for a in range(0, 20):
    #    numpy.savetxt("bh-combo-%i.txt" % a, harmonic_strengthened_bh[a])

    #if plot:
    #    Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0
    #    pylab.plot(Hn_bpms, harmonic_strengthened_bh)

    ### pick top 8 candidates
    #peaks = []
    #for i in xrange( Hn.shape[0] ):
    #    these_peaks = find_peaks(harmonic_strengthened_bh[i],
    #        number=8, width=11)
    #    peaks.append(these_peaks)

    #summed = numpy.sum(harmonic_strengthened_bh, axis=0)
    #summed = numpy.sum(Hn, axis=0)

    if plot:
        pylab.figure()
        pylab.plot(numpy.arange(len(Hn)) / 4.0, Hn)

#    folded_hist = numpy.zeros(60*4)
#    for i in xrange(1, len(summed)-1):
#        bpm = i/4.0
#        j = i
#        while bpm < 15:
#            bpm *= 2
#            j *= 2
#        while bpm > 30:
#            bpm /= 2.0
#            j /= 2.0
#        #j = int(round(j))
#        j = int(j)
#        #print "%i\tto\t%i" % (i, j)
#        if j >= len(folded_hist):
#            continue
#        folded_hist [j] += summed[i]
#

### zzz confirmed up to here
    peaks = []
    for i in xrange(Hn.shape[0]):
        these_peaks = find_peaks(harmonic_strengthened_bh[i],
                                 number=8,
                                 peak_neighbors=11)
        peaks.append(these_peaks / 4.0)
        #bpms = numpy.array(these_peaks)/4.0
    #    numpy.savetxt("bh-peaks-%i.txt" % i, bpms)

    #candidate_bpms = [ Hn_bpms[i] for i in peaks ]
    #print candidate_bpms
    #for p in peaks:
    #    print numpy.array(p)/4
    #if plot:
    #    pylab.figure()
    #    pylab.plot(numpy.arange(30*4, 60*4)/4.0, folded_hist[30*4:])
    #    pylab.show()
    return peaks
Example #7
0
def beat_phase(defs, oss_sr, oss_data, candidate_bpms_orig, plot=False):
    ### overlap
    overlapped = overlap.sliding_window(
        #numpy.append(
        #    numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE),
        #    oss_data[:-2*defs.BH_HOPSIZE]),
        oss_data,
        defs.BP_WINDOWSIZE,
        defs.BP_HOPSIZE)
    #beat_histogram_sr = oss_sr / defs.BP_HOPSIZE

    if defs.WRITE_BP:
        bp_accum = open("out/bp-accum.txt", "w")
    #print candidate_bpms_orig
    candidate_bpms = candidate_bpms_orig
    bphase = numpy.zeros(defs.BPM_MAX)
    for i in xrange(overlapped.shape[0]):
        cands = candidate_bpms[i]

        onset_scores = numpy.zeros(len(cands))
        tempo_scores = numpy.zeros(len(cands))
        for j, bpm in enumerate(cands):
            if bpm == 0:
                continue
            mag, var = calc_pulse_trains(bpm, overlapped[i], oss_sr)
            tempo_scores[j] = mag
            onset_scores[j] = var
        if defs.WRITE_BP:
            numpy.savetxt(
                "out/bp-%i.txt" % (i + 1),
                numpy.vstack((cands, tempo_scores, onset_scores)).transpose())
        tempo_scores /= tempo_scores.sum()
        onset_scores /= onset_scores.sum()

        combo_scores = tempo_scores + onset_scores
        combo_scores /= combo_scores.sum()

        # find best score
        besti = combo_scores.argmax()
        bestbpm = round(cands[besti])
        beststr = combo_scores[besti]

        bphase[int(bestbpm)] += beststr

        if defs.WRITE_BP:
            #numpy.savetxt("out/bp-%i.txt" % (i+1),
            #    numpy.vstack((cands, tempo_scores, onset_scores, combo_scores)).transpose())
            #numpy.savetxt("out/bp-peak-%i.txt" % (i+1),
            #    numpy.vstack((int(bestbpm), beststr)).transpose())
            text = "%i\t%.15f\n" % (int(bestbpm), beststr)
            bp_accum.write(text)

    if defs.WRITE_BP:
        bp = open('out/beat_phase.txt', 'w')
        for b in bphase:
            if b == 0:
                text = "0\n"
            else:
                text = "%.5f\n" % b
            bp.write(text)
        bp.close()

    if plot:
        pylab.figure()
        pylab.plot(numpy.arange(len(bphase)), bphase, label="marsyas")
        pylab.title("bphase")
        pylab.legend()

    bpm = bphase.argmax()
    #bpm_strength = bphase[bpm]

    if defs.CHECK_REFERENCE:
        calc = bphase
        ref = numpy.loadtxt("reference/%s/beat_phase.txt" % defs.basename)
        delta = calc - ref
        maxerr = numpy.abs(delta).max()
        if maxerr < 1e-6:
            print "BP ok, maximum deviation %.2g" % maxerr
        else:
            pylab.figure()
            pylab.title("BP: calculated - reference")
            pylab.plot(delta)
            pylab.figure()
            pylab.plot(calc)
            pylab.plot(ref)
            pylab.show()
            exit(1)

    if defs.WRITE_BP:
        bp_accum.close()
    return bpm, bphase
def onset_strength_signal(wav_sr, wav_data, plot=False):
    ### overlapping time data
    # add extra window of zeros at beginning to match marsyas
    overlapped = overlap.sliding_window(
        numpy.append(numpy.zeros(defs.OSS_WINDOWSIZE - defs.OSS_HOPSIZE),
                     wav_data),
        #wav_data,
        defs.OSS_WINDOWSIZE,
        defs.OSS_HOPSIZE)
    oss_sr = wav_sr / float(defs.OSS_HOPSIZE)
    windowed = overlapped * marsyas_hamming(
        #scipy.signal.get_window( "hamming",
        defs.OSS_WINDOWSIZE)

    ### log-magnitude of FFT
    ffts = scipy.fftpack.fft(windowed, defs.OSS_WINDOWSIZE, axis=1)
    ffts_abs = abs(ffts)[:, :ffts.shape[1] / 2 + 1]
    # extra scaling to match Marsyas FFT output
    ffts_abs /= defs.OSS_WINDOWSIZE
    logmag = numpy.log(1.0 + 1000.0 * ffts_abs)

    #numpy.savetxt('log0.txt', logmag[0])
    #numpy.savetxt('log1.txt', logmag[1])

    ### flux
    flux = numpy.zeros(ffts_abs.shape[0])  # output time signal
    prev = numpy.zeros(ffts_abs.shape[1])
    for i in xrange(0, ffts_abs.shape[0]):
        diff = logmag[i] - prev
        diffreduced = diff[1:]  # to match Marsyas
        diffclipped = diffreduced.clip(min=0)
        prev = numpy.copy(logmag[i])
        flux[i] = sum(diffclipped)
        #if i < 2:
        #    print diffclipped

    #numpy.savetxt('flux.txt', flux)
    ### clear out first window
    #flux[0] = 0.0

    if plot:
        ts = numpy.arange(len(flux)) / oss_sr
        pylab.figure()
        pylab.plot(ts, flux)
    ### filter
    if defs.OSS_LOWPASS_CUTOFF > 0:
        b = scipy.signal.firwin(defs.OSS_LOWPASS_N,
                                defs.OSS_LOWPASS_CUTOFF / (oss_sr / 2.0))
        #b, a = scipy.signal.butter(2, defs.OSS_LOWPASS_CUTOFF / (oss_sr/2.0) )
        #filtered_flux = scipy.signal.filtfilt(b, a, flux)
        #a = numpy.zeros(defs.OSS_LOWPASS_N)
        #a[0] = 1.0
        filtered_flux = scipy.signal.lfilter(b, 1.0, flux)
    else:
        filtered_flux = flux

    #numpy.savetxt('filtered.txt', filtered_flux)

    if plot:
        ts = numpy.arange(len(filtered_flux)) / oss_sr
        pylab.plot(ts, filtered_flux)
        pylab.title("Onset strength signal")
    return oss_sr, filtered_flux
def onset_strength_signal(defs, wav_sr, wav_data, plot=False):
    ### overlapping time data
    # add extra window of zeros at beginning to match marsyas
    overlapped = overlap.sliding_window(
        numpy.append(numpy.zeros(defs.OSS_WINDOWSIZE - defs.OSS_HOPSIZE),
                     wav_data),
        #wav_data,
        defs.OSS_WINDOWSIZE,
        defs.OSS_HOPSIZE)
    oss_sr = wav_sr / float(defs.OSS_HOPSIZE)
    #print oss_sr
    if defs.OPTIONS_ONSET == 0:
        rms = numpy.sqrt(numpy.mean(overlapped**2, axis=1))
        #dif = numpy.clip( rms[1:] - rms[:-1], 0, numpy.Inf)
        #return oss_sr, dif
        return oss_sr, rms

    windowed = overlapped * marsyas_hamming(
        #scipy.signal.get_window( "hamming",
        defs.OSS_WINDOWSIZE)

    ### log-magnitude of FFT
    ffts = scipy.fftpack.fft(windowed, defs.OSS_WINDOWSIZE, axis=1)
    ffts_abs = abs(ffts)[:, :ffts.shape[1] / 2 + 1]
    # extra scaling to match Marsyas FFT output
    ffts_abs /= defs.OSS_WINDOWSIZE
    logmag = numpy.log(1.0 + 1000.0 * ffts_abs)

    ### flux
    flux = numpy.zeros(ffts_abs.shape[0])  # output time signal
    prev = numpy.zeros(ffts_abs.shape[1])
    for i in xrange(0, ffts_abs.shape[0]):
        diff = logmag[i] - prev
        diffreduced = diff[1:]  # to match Marsyas
        diffclipped = diffreduced.clip(min=0)
        prev = numpy.copy(logmag[i])
        flux[i] = sum(diffclipped)
        #if i < 2:
        #    print diffclipped

    #if True:
    #    ts = numpy.arange(len(flux)-1) / oss_sr
    #    pylab.plot(ts, flux[1:], color="red")

    #numpy.savetxt('flux.txt', flux)
    ### clear out first window
    #flux[0] = 0.0
    if defs.OPTIONS_ONSET == 1:
        return oss_sr, flux

    if plot:
        ts = numpy.arange(len(flux)) / oss_sr
        pylab.figure()
        #pylab.plot( ts, flux)
    ### filter
    if defs.OSS_LOWPASS_CUTOFF > 0 and defs.OPTIONS_ONSET < 3:
        b = scipy.signal.firwin(defs.OSS_LOWPASS_N,
                                defs.OSS_LOWPASS_CUTOFF / (oss_sr / 2.0))
        #print b
        filtered_flux = scipy.signal.lfilter(b, 1.0, flux)

        #b, a = scipy.signal.butter(2, 0.1 / (oss_sr/2.0),
        #    btype="high")
        #filtered_flux = scipy.signal.filtfilt(b, a, flux)
    else:
        filtered_flux = flux

    if plot:
        ts = numpy.arange(len(filtered_flux)) / oss_sr
        pylab.plot(ts, filtered_flux, label="filtered")
        pylab.title("Onset strength signal")

    ts = numpy.arange(len(filtered_flux)) / oss_sr
    if defs.WRITE_ONSETS:
        #cutoff = int(2048*128/44100.0 * oss_sr)
        cutoff = 2048
        #print "cutoff", cutoff
        #print logmag.shape
        logmag_short = logmag[:cutoff, ]
        #print logmag_short.shape
        numpy.savetxt('out/logmag.txt', logmag_short.transpose())
        #logmag[:cutoff,].transpose())

        numpy.savetxt('out/flux.txt', numpy.vstack((ts, flux)).transpose())
        numpy.savetxt('out/onset_strength.txt',
                      numpy.vstack((ts, filtered_flux)).transpose())

    num_bh_frames = int(len(filtered_flux) / defs.BH_HOPSIZE)
    filtered_flux = filtered_flux[:num_bh_frames * defs.BH_HOPSIZE]

    if defs.CHECK_REFERENCE:
        calc = filtered_flux
        ref = numpy.loadtxt("reference/OSS-4-filter.txt")
        delta = calc - ref
        maxerr = max(abs(delta))
        if maxerr < 1e-12:
            print "OSS ok, maximum deviation %.2g" % maxerr
        else:
            pylab.figure()
            pylab.title("OSS: calculated - reference")
            pylab.plot(delta)
            pylab.show()
            exit(1)
    if plot:
        pylab.legend()
    return oss_sr, filtered_flux
Example #10
0
def beat_phase(defs, oss_sr, oss_data, candidate_bpms_orig, plot=False):
    ### overlap
    overlapped = overlap.sliding_window(
        #numpy.append(
        #    numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE),
        #    oss_data),
        oss_data,
        defs.BP_WINDOWSIZE, defs.BP_HOPSIZE)
    #beat_histogram_sr = oss_sr / defs.BP_HOPSIZE

    #print candidate_bpms_orig
    candidate_bpms = candidate_bpms_orig
    candidate_bpms = candidate_bpms_orig[:4]
    #for bpm in candidate_bpms_orig:
    #    #print bpm, base
    #    candidate_bpms.add(bpm)
    #candidate_bpms = list(candidate_bpms)
    #candidate_bpms.sort()
    #print candidate_bpms
    if defs.OPTIONS_BP == 0:
        onset_scores = numpy.zeros(len(candidate_bpms))
        tempo_scores = numpy.zeros(len(candidate_bpms))
        pylab.plot(overlapped[0])
        for j, bpm in enumerate(candidate_bpms):
            #print "Evaluating %.1f BPM" % bpm
            #train = make_sine_train(bpm)
            train, period = make_impulse_train(bpm, len(overlapped[0]), oss_sr)

            for i in xrange(overlapped.shape[0]):
            #for i in xrange(1):
                mag, offset, var = match_offset(train, overlapped[i], period)
                #print "%.2f\t%.2f" % (
                #    mag / numpy.sum(train), var)

                onset_scores[j] += mag + var

                #pylab.title("actual signal")
                #pylab.plot(overlapped[i])
                #pylab.plot(train)
                #pylab.show()
            pylab.plot(30*train[period-8:])
        #print onset_scores / max(onset_scores)
        best_i = onset_scores.argmax()
        print onset_scores[0] + onset_scores[2]
        print onset_scores[1] + onset_scores[3]

        pylab.show()
        return candidate_bpms[best_i], 0

        exit(1)
        if False:
            if False:
                #mag, std = calc_pulse_trains(bpm, overlapped[i], oss_sr)
                mag, std = calc_sine_trains(bpm, overlapped[i], oss_sr)
                #print "%.1f\t%.3f\t%.3f" % (bpm, mag, std)
                onset_scores[j] += mag
                tempo_scores[j] += std
            #exit(1)
        #print candidate_bpms
        #print onset_scores
        #print tempo_scores
        best_i = tempo_scores.argmax()
        best_bpm = candidate_bpms[best_i]
        return best_bpm, 0


    bhisto = numpy.zeros(defs.BPM_MAX)
    #bpms_max = numpy.zeros( len(candidate_bpms) )
    #bpms_std = numpy.zeros( len(candidate_bpms) )
    for i in xrange(overlapped.shape[0]):
        onset_scores = numpy.zeros(len(candidate_bpms))
        tempo_scores = numpy.zeros(len(candidate_bpms))
        #for j, bpm in enumerate(candidate_bpms[i]):
        for j, bpm in enumerate(candidate_bpms):
            mag, std = calc_pulse_trains(bpm, overlapped[i], oss_sr)
            #bpms_max[i] += mag
            #bpms_std[i] += std
            ### correct up to here
            #print i, bpm, mag, std
            tempo_scores[j] = mag
            onset_scores[j] = std
        tempo_scores /= tempo_scores.sum()
        onset_scores /= onset_scores.sum()

        tempo_scores = tempo_scores + onset_scores
        tempo_scores /= tempo_scores.sum()

        # find best 2 scores
        besti = tempo_scores.argmax()
        #bestbpm = candidate_bpms[i][besti]
        bestbpm = candidate_bpms[besti]
        beststr = tempo_scores[besti]
        #tempo_scores[besti] = 0.0
        #second_besti = tempo_scores.argmax()
        #second_bestbpm = candidate_bpms[i][second_besti]
        #second_beststr = tempo_scores[second_besti]

        if i >= (defs.BP_WINDOWSIZE / defs.BP_HOPSIZE):
            bhisto[ int(bestbpm) ] += beststr
            #bhisto[ int(second_bestbpm*4) ] += second_beststr

        #print bestbpm, '\t', beststr, '\t',
        #print second_bestbpm, '\t', second_beststr

    #b, a = scipy.signal.butter(4, 0.5)
    #filt = scipy.signal.filtfilt(b, a, bhisto)
    

    if plot:
        pylab.figure()
        pylab.plot(numpy.arange(len(bhisto)), bhisto,
            label="marsyas")
        #pylab.plot(numpy.arange(len(bhisto))/4.0, filt,
        #    label="extra filtered")
        pylab.title("bhisto")
        pylab.legend()

    bpm1 = bhisto.argmax()
    bhisto[bpm1] = 0.0
    bpm2 = bhisto.argmax()
    return bpm1, bpm2
Example #11
0
def beat_period_detection(defs, oss_sr, oss_data, plot=False):
    ### 1) Overlap
    overlapped = overlap.sliding_window(
        #numpy.append(
        #    numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE),
        #    oss_data[:-2*defs.BH_HOPSIZE]),
        oss_data,
        defs.BH_WINDOWSIZE, defs.BH_HOPSIZE, zeroPad=True)
    #beat_period_sr = oss_sr / defs.BH_HOPSIZE

    ### 2) Generalized Autocorrelation
    autocorr = autocorrelation(overlapped)

    minlag = int(oss_sr*60.0 / defs.BPM_MAX)
    maxlag = int(oss_sr*60.0 / defs.BPM_MIN) + 1

    num_frames = autocorr.shape[0]
    #win_size = autocorr.shape[1]

    ### 3) Enhance Harmonics
    harmonic_enhanced = numpy.zeros( autocorr.shape )
    for i in xrange( num_frames ):
        auto = autocorr[i]
        stretched = numpy.zeros( defs.BH_WINDOWSIZE )
        for j in xrange( 512 ):
            stretched[j] = auto[2*j] + auto[4*j]
        harmonic_enhanced[i] = (
            auto + stretched
            )

    ### 4) Pick peaks
    peaks = numpy.zeros( (num_frames, 10) )
    for i in xrange( num_frames ):
        these_peaks = find_peaks(defs, harmonic_enhanced[i],
            number=10, peak_neighbors=1, minsample=minlag,
            maxsample=maxlag)
        peaks[i,:] = these_peaks

    ### 5) Evaluate pulse trains
    tempo_lags = numpy.zeros(num_frames)
    for i in xrange(num_frames):
        cands = peaks[i]
        onset_scores = numpy.zeros(len(cands))
        tempo_scores = numpy.zeros(len(cands))
        for j, cand in enumerate(cands):
            if cand == 0:
                continue
            lag = int(round(cand))
            mag, var = calc_pulse_trains(lag, overlapped[i], oss_sr)
            tempo_scores[j] = mag
            onset_scores[j] = var
        tempo_scores /= tempo_scores.sum()
        onset_scores /= onset_scores.sum()

        combo_scores = tempo_scores + onset_scores
        combo_scores /= combo_scores.sum()

        # find best score
        besti = combo_scores.argmax()
        bestlag = round(cands[besti])

        tempo_lags[i] = bestlag

    if defs.CHECK_REFERENCE:
        ref = numpy.loadtxt(
            "reference/BEATS-5-pulse.txt")
        delta = tempo_lags - ref
        maxerr = numpy.abs(delta).max()
        if maxerr < 1e-12:
            print "Beat pulse detection ok, maximum deviation %.2g" % maxerr
        else:
            pylab.figure()
            pylab.title("Beat pulse detection: this - reference")
            pylab.plot(delta)
            pylab.show()
            exit(1)
    return tempo_lags
def beat_histogram(oss_sr, oss_data, plot=False):
    ### overlap
    overlapped = overlap.sliding_window(
        numpy.append(
            numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE),
            oss_data),
        #oss_data,
        defs.BH_WINDOWSIZE, defs.BH_HOPSIZE)
    #beat_histogram_sr = oss_sr / defs.BH_HOPSIZE

    ### autocorrelation
    autocorr = autocorrelation(overlapped)

    ### beat histogram
    Hn = numpy.zeros( (autocorr.shape[0], 4*defs.BPM_MAX) )
    for i in xrange( autocorr.shape[0] ):
        if i > 0 and i != (defs.BH_WINDOWSIZE / defs.BH_HOPSIZE):
            Hn[i] = Hn[i-1]
        prev_Hni = 4*defs.BPM_MAX-1
        pprev_Hni = prev_Hni
        sumamp = 0.0
        count = 1

        for j in xrange(1, autocorr.shape[1]):
            factor = 8/2
            Hni = int((oss_sr * 60.0 * factor / (j+1)) + 0.5);
            #bpm = autocorr_bpms[i]
            if Hni < 4*defs.BPM_MAX and Hni > 40:
                amp = autocorr[i][j]
                if amp < 0:
                    amp = 0
                if prev_Hni == Hni:
                    sumamp += amp
                    count += 1
                else:
                    sumamp += amp
                    Hn[i][prev_Hni] += sumamp / float(count)
                    sumamp = 0.0
                    count = 1
                ### linear interpolate not-set bins
                if pprev_Hni - prev_Hni > 1:
                    x0 = prev_Hni
                    x1 = pprev_Hni
                    y0 = Hn[i][prev_Hni]
                    y1 = Hn[i][pprev_Hni]
                    for k in xrange(prev_Hni+1, pprev_Hni):
                        Hn[i][k] = y0 + (y1-y0)*(k-x0)/(x1-x0)
                    #print x0, x1, y0, y1, Hn[i][pprev_Hni-1]
                pprev_Hni = prev_Hni
                prev_Hni = Hni
    #numpy.savetxt('bh.txt', Hn[0])

    #for a in range(0, 20):
    #    numpy.savetxt("bh-combo-%i.txt" % a, Hn[a])

    #if plot:
    #    pylab.figure()
    #    Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0
    #    pylab.plot(Hn_bpms, summed_beat_histograms)
    #    pylab.title("Beat histogram")

    ### time stretch, add
    harmonic_strengthened_bh = numpy.zeros( Hn.shape )
    for i in xrange( Hn.shape[0] ):
        ### unchecked direct translation of marsyas
        stretched = numpy.zeros( Hn.shape[1] )
        factor = 0.5
        numSamples = Hn.shape[1]
        for t in xrange( Hn.shape[1] ):
            ni = t*factor
            li = int(ni) % numSamples
            ri = li + 1
            w = ni - li
            if ri < numSamples:
                stretched[t] = Hn[i][li] + w * (Hn[i][ri] - Hn[i][li])
            else:
                stretched[t] = Hn[t]
        harmonic_strengthened_bh[i] = (
            Hn[i]
            + stretched
            )

        numpy.savetxt("foo-%i.txt" % i, harmonic_strengthened_bh[i])

    #for a in range(0, 20):
    #    numpy.savetxt("bh-combo-%i.txt" % a, harmonic_strengthened_bh[a])

    #if plot:
    #    Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0
    #    pylab.plot(Hn_bpms, harmonic_strengthened_bh)

    ### pick top 8 candidates
    #peaks = []
    #for i in xrange( Hn.shape[0] ):
    #    these_peaks = find_peaks(harmonic_strengthened_bh[i],
    #        number=8, width=11)
    #    peaks.append(these_peaks)

    #summed = numpy.sum(harmonic_strengthened_bh, axis=0)
    #summed = numpy.sum(Hn, axis=0)

    if plot:
        pylab.figure()
        pylab.plot(numpy.arange(len(Hn))/4.0, Hn)


#    folded_hist = numpy.zeros(60*4)
#    for i in xrange(1, len(summed)-1):
#        bpm = i/4.0
#        j = i
#        while bpm < 15:
#            bpm *= 2
#            j *= 2
#        while bpm > 30:
#            bpm /= 2.0
#            j /= 2.0
#        #j = int(round(j))
#        j = int(j)
#        #print "%i\tto\t%i" % (i, j)
#        if j >= len(folded_hist):
#            continue
#        folded_hist [j] += summed[i]
#


    ### zzz confirmed up to here
    peaks = []
    for i in xrange( Hn.shape[0] ):
        these_peaks = find_peaks(harmonic_strengthened_bh[i],
            number=8, peak_neighbors=11)
        peaks.append(these_peaks / 4.0)
        #bpms = numpy.array(these_peaks)/4.0
    #    numpy.savetxt("bh-peaks-%i.txt" % i, bpms)


    #candidate_bpms = [ Hn_bpms[i] for i in peaks ]
    #print candidate_bpms
    #for p in peaks:
    #    print numpy.array(p)/4
    #if plot:
    #    pylab.figure()
    #    pylab.plot(numpy.arange(30*4, 60*4)/4.0, folded_hist[30*4:])
    #    pylab.show()
    return peaks
def onset_strength_signal(defs, wav_sr, wav_data, plot=False):
    ### overlapping time data
    # add extra window of zeros at beginning to match marsyas
    overlapped = overlap.sliding_window(
        numpy.append(
            numpy.zeros(defs.OSS_WINDOWSIZE - defs.OSS_HOPSIZE),
            wav_data),
        #wav_data,
        defs.OSS_WINDOWSIZE, defs.OSS_HOPSIZE)
    oss_sr = wav_sr / float(defs.OSS_HOPSIZE)
    if defs.OPTIONS_ONSET == 0:
        rms = numpy.sqrt( numpy.mean(overlapped**2, axis=1))
        #dif = numpy.clip( rms[1:] - rms[:-1], 0, numpy.Inf)
        #return oss_sr, dif
        return oss_sr, rms


    windowed = overlapped * marsyas_hamming(
        #scipy.signal.get_window( "hamming",
        defs.OSS_WINDOWSIZE)

    ### log-magnitude of FFT
    ffts = scipy.fftpack.fft(windowed, defs.OSS_WINDOWSIZE,  axis=1)
    ffts_abs = abs(ffts)[:,:ffts.shape[1]/2 + 1]
    # extra scaling to match Marsyas FFT output
    ffts_abs /= defs.OSS_WINDOWSIZE
    logmag = numpy.log(1.0 + 1000.0 * ffts_abs)

    #numpy.savetxt('log0.txt', logmag[0])
    #numpy.savetxt('log1.txt', logmag[1])

    ### flux
    flux = numpy.zeros( ffts_abs.shape[0] ) # output time signal
    prev = numpy.zeros( ffts_abs.shape[1] )
    for i in xrange( 0, ffts_abs.shape[0] ):
        diff = logmag[i] - prev
        diffreduced = diff[1:] # to match Marsyas
        diffclipped = diffreduced.clip(min=0)
        prev = numpy.copy(logmag[i])
        flux[i] = sum(diffclipped)
        #if i < 2:
        #    print diffclipped

    #numpy.savetxt('flux.txt', flux)
    ### clear out first window
    #flux[0] = 0.0
    if defs.OPTIONS_ONSET == 1:
        return oss_sr, flux
        

    if plot:
        ts = numpy.arange( len(flux) ) / oss_sr
        pylab.figure()
        #pylab.plot( ts, flux)
    ### filter
    if defs.OSS_LOWPASS_CUTOFF > 0:
        b = scipy.signal.firwin(defs.OSS_LOWPASS_N,
            defs.OSS_LOWPASS_CUTOFF / (oss_sr/2.0) )
        filtered_flux = scipy.signal.lfilter(b, 1.0, flux)

        #b, a = scipy.signal.butter(2, 0.1 / (oss_sr/2.0),
        #    btype="high")
        #filtered_flux = scipy.signal.filtfilt(b, a, flux)
    else:
        filtered_flux = flux


    if plot:
        ts = numpy.arange( len(filtered_flux) ) / oss_sr
        pylab.plot( ts, filtered_flux)
        pylab.title("Onset strength signal")

    ts = numpy.arange( len(filtered_flux) ) / oss_sr
    #numpy.savetxt('filtered.txt',
    #    numpy.vstack( (ts, filtered_flux)).transpose() )
    #numpy.savetxt('flux.txt',
    #    numpy.vstack( (ts, flux)).transpose() )

    if defs.OPTIONS_ONSET == 3:
        b, a = scipy.signal.butter(5, 5 / (oss_sr/2.0))
        mean_flux = scipy.signal.filtfilt(b, a, filtered_flux)
        cutoff_flux = (filtered_flux - mean_flux).clip(min=0)

        #pylab.plot( ts, mean_flux)
        #pylab.plot( ts, cutoff_flux)


        #numpy.savetxt('cutoff.txt',
        #    numpy.vstack( (ts, cutoff_flux)).transpose() )
        return oss_sr, cutoff_flux
    #pylab.show()
    #exit(1)

    return oss_sr, filtered_flux
Example #14
0
def beat_histogram(defs, oss_sr, oss_data, plot=False):
    ### overlap
    overlapped = overlap.sliding_window(
        #numpy.append(
        #    numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE),
        #    oss_data[:-2*defs.BH_HOPSIZE]),
        oss_data,
        defs.BH_WINDOWSIZE, defs.BH_HOPSIZE)
    #beat_histogram_sr = oss_sr / defs.BH_HOPSIZE
    #for i in range(len(overlapped[0])):
    #    print overlapped[0][i]
    #exit(1)

    ### autocorrelation
    autocorr = autocorrelation(overlapped)

    ### beat histogram
    Hn = numpy.zeros( (autocorr.shape[0], 4*defs.BPM_MAX) )
    for i in xrange( autocorr.shape[0] ):
        #if i > 0 and i != (defs.BH_WINDOWSIZE / defs.BH_HOPSIZE):
        #    Hn[i] = Hn[i-1]
        prev_Hni = 4*defs.BPM_MAX-1
        pprev_Hni = prev_Hni
        sumamp = 0.0
        count = 1

        for j in xrange(1, autocorr.shape[1]):
            factor = 8/2
            Hni = int(oss_sr * 60.0 * factor / (j+1) + 0.5);
            #bpm = autocorr_bpms[i]
            if Hni < 4*defs.BPM_MAX:
                amp = autocorr[i][j]
                #print j, Hni, amp
                if amp < 0:
                    amp = 0
                if prev_Hni == Hni:
                    sumamp += amp
                    count += 1
                else:
                    sumamp += amp
                    Hn[i][prev_Hni] = sumamp / float(count)
                    sumamp = 0.0
                    count = 1
                ### linear interpolate not-set bins
                if pprev_Hni - prev_Hni > 1:
                    x0 = prev_Hni
                    x1 = pprev_Hni
                    y0 = Hn[i][prev_Hni]
                    y1 = Hn[i][pprev_Hni]
                    for k in xrange(prev_Hni+1, pprev_Hni):
                        Hn[i][k] = y0 + (y1-y0)*(k-x0)/(x1-x0)
                    #print x0, x1, y0, y1, Hn[i][pprev_Hni-1]
                pprev_Hni = prev_Hni
                prev_Hni = Hni
    #numpy.savetxt('bh.txt', Hn[0])

    #for a in range(0, 20):
    #    numpy.savetxt("bh-combo-%i.txt" % a, Hn[a])

    #if plot:
    #    pylab.figure()
    #    Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0
    #    pylab.plot(Hn_bpms, summed_beat_histograms)
    #    pylab.title("Beat histogram")

    ### time stretch, add
    harmonic_strengthened_bh = numpy.zeros( Hn.shape )
    for i in xrange( Hn.shape[0] ):
        ### unchecked direct translation of marsyas
        factor2 = 0.5
        factor4 = 0.25
        stretched = numpy.zeros( Hn.shape[1] )
        numSamples = Hn.shape[1]
        for t in xrange( Hn.shape[1] ):
            ni = t*factor2
            li = int(ni) % numSamples
            ri = li + 1
            w = ni - li
            #print "%i\t%i\t%f\t%f" % (li, ri, w, ni)
            #zzz
            if ri < numSamples:
                stretched[t] += Hn[i][li] + w * (Hn[i][ri] - Hn[i][li])
            else:
                stretched[t] += Hn[t]

            ni = t*factor4
            li = int(ni) % numSamples
            ri = li + 1
            w = ni - li
            if ri < numSamples:
                stretched[t] += Hn[i][li] + w * (Hn[i][ri] - Hn[i][li])
            else:
                stretched[t] += Hn[t]
        harmonic_strengthened_bh[i] = (
            Hn[i]
            + stretched
            )

        if defs.WRITE_BH:
            samps = numpy.arange(defs.BH_WINDOWSIZE)
            numpy.savetxt("out/aq-%i.txt" % (i+1),
                numpy.vstack((samps, autocorr[i])).transpose())
            bpms = numpy.arange(4*defs.BPM_MAX)/4.0
            numpy.savetxt("out/bh-%i.txt" % (i+1),
                numpy.vstack((bpms, Hn[i])).transpose())
            numpy.savetxt("out/hbh-%i.txt" % (i+1),
                numpy.vstack((bpms, harmonic_strengthened_bh[i])).transpose())

    #for a in range(0, 20):
    #    numpy.savetxt("bh-combo-%i.txt" % a, harmonic_strengthened_bh[a])

    #if plot:
    #    Hn_bpms = numpy.arange( 4*defs.BPM_MAX) / 4.0
    #    pylab.plot(Hn_bpms, harmonic_strengthened_bh)

    ### pick top 8 candidates
    #peaks = []
    #for i in xrange( Hn.shape[0] ):
    #    these_peaks = find_peaks(harmonic_strengthened_bh[i],
    #        number=8, width=11)
    #    peaks.append(these_peaks)

    #summed = numpy.sum(harmonic_strengthened_bh, axis=0)
    #summed = numpy.sum(Hn, axis=0)

    if plot:
        pylab.figure()
        sHn = numpy.sum(Hn, axis=0)
        sHBH = numpy.sum(harmonic_strengthened_bh, axis=0)
        pylab.plot(numpy.arange(len(sHn))/4.0, sHn, label="sum")
        pylab.plot(numpy.arange(len(sHBH))/4.0, sHBH, label="enhanced")
        if defs.OPTIONS_BH == 3:
            b, a = scipy.signal.butter(1, 0.1)
            filtered = scipy.signal.filtfilt(b, a, sHBH)
            pylab.plot(numpy.arange(len(filtered))/4.0, filtered, label="filtered")
        pylab.title("Summed beat histogram")


#    folded_hist = numpy.zeros(60*4)
#    for i in xrange(1, len(summed)-1):
#        bpm = i/4.0
#        j = i
#        while bpm < 15:
#            bpm *= 2
#            j *= 2
#        while bpm > 30:
#            bpm /= 2.0
#            j /= 2.0
#        #j = int(round(j))
#        j = int(j)
#        #print "%i\tto\t%i" % (i, j)
#        if j >= len(folded_hist):
#            continue
#        folded_hist [j] += summed[i]
#


    if defs.WRITE_BH:
        combo_peaks = open('out/beat_histogram.txt', 'w')
    peaks = []
    for i in xrange( Hn.shape[0] ):
        these_peaks = find_peaks(defs, harmonic_strengthened_bh[i],
            number=10, peak_neighbors=1)
        if defs.WRITE_BH:
            gnd = 120
            has_gnd = False
            tl = []
            for b in these_peaks:
                tl.append("%.2f" % (b/4.0))
                if gnd*0.96*4 <= b <= gnd*1.04*4:
                    #print "yes"
                    has_gnd = True
            text = "  ".join(tl)
            combo_peaks.write( text + "\n")
            if has_gnd:
                these_peaks = list(these_peaks)
                these_peaks.append(0)
            else:
                these_peaks = list(these_peaks)
                these_peaks.append(gnd*4)
                #these_peaks.append(0)
                #print these_peaks
                N = len(overlapped[i])
                ts = (numpy.arange( N ) + N*i/16.0 ) / oss_sr
                numpy.savetxt("out/bad-bh-%i.txt" % (i+1),
                    numpy.vstack( (ts, overlapped[i])).transpose() )
                defs.extra.append(i)
            bpms = numpy.array(these_peaks)/4.0
            bpms_strengths = [harmonic_strengthened_bh[i][4*b] for b in bpms]
            numpy.savetxt("out/bh-peaks-%i.txt" % (i+1),
                numpy.vstack((bpms, bpms_strengths)).transpose())
        peaks.append( numpy.array(these_peaks) / 4.0)
    if defs.WRITE_BH:
        combo_peaks.close()

    #cand_peaks = find_peaks(sHn,
    #        number=8, peak_neighbors=11) / 4.0
    #pylab.plot(numpy.arange(len(sHn))/4.0, sHn)
    #pylab.show()
    #pylab.plot(cand_peaks)
    return peaks
def beat_phase(oss_sr, oss_data, candidate_bpms_orig, plot=False):
    ### overlap
    overlapped = overlap.sliding_window(
        numpy.append(numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE),
                     oss_data),
        #oss_data,
        defs.BP_WINDOWSIZE,
        defs.BP_HOPSIZE)
    #beat_histogram_sr = oss_sr / defs.BP_HOPSIZE

    #print candidate_bpms_orig
    candidate_bpms = candidate_bpms_orig
    #for bpm in candidate_bpms_orig:
    #    #print bpm, base
    #    candidate_bpms.add(bpm)
    #candidate_bpms = list(candidate_bpms)
    #candidate_bpms.sort()
    #print candidate_bpms

    bhisto = numpy.zeros(defs.BPM_MAX)
    #bpms_max = numpy.zeros( len(candidate_bpms) )
    #bpms_std = numpy.zeros( len(candidate_bpms) )
    for i in xrange(overlapped.shape[0]):
        onset_scores = numpy.zeros(len(candidate_bpms))
        tempo_scores = numpy.zeros(len(candidate_bpms))
        for j, bpm in enumerate(candidate_bpms[i]):
            mag, std = calc_pulse_trains(bpm, overlapped[i], oss_sr)
            #bpms_max[i] += mag
            #bpms_std[i] += std
            ### correct up to here
            #print i, bpm, mag, std
            tempo_scores[j] = mag
            onset_scores[j] = std
        tempo_scores /= tempo_scores.sum()
        onset_scores /= onset_scores.sum()

        tempo_scores = tempo_scores + onset_scores
        tempo_scores /= tempo_scores.sum()

        # find best 2 scores
        besti = tempo_scores.argmax()
        bestbpm = candidate_bpms[i][besti]
        beststr = tempo_scores[besti]
        tempo_scores[besti] = 0.0
        second_besti = tempo_scores.argmax()
        second_bestbpm = candidate_bpms[i][second_besti]
        second_beststr = tempo_scores[second_besti]

        if i >= (defs.BP_WINDOWSIZE / defs.BP_HOPSIZE):
            bhisto[int(bestbpm)] += beststr
            #bhisto[ int(second_bestbpm*4) ] += second_beststr

        #print bestbpm, '\t', beststr, '\t',
        #print second_bestbpm, '\t', second_beststr

    #b, a = scipy.signal.butter(4, 0.5)
    #filt = scipy.signal.filtfilt(b, a, bhisto)

    if plot:
        pylab.plot(numpy.arange(len(bhisto)) / 4.0, bhisto, label="marsyas")
        #pylab.plot(numpy.arange(len(bhisto))/4.0, filt,
        #    label="extra filtered")
        pylab.title("bhisto")
        pylab.legend()

    bpm1 = bhisto.argmax()
    bhisto[bpm1] = 0.0
    bpm2 = bhisto.argmax()
    return bpm1, bpm2
Example #16
0
def beat_phase(defs, oss_sr, oss_data, candidate_bpms_orig, plot=False):
    ### overlap
    overlapped = overlap.sliding_window(
        #numpy.append(
        #    numpy.zeros(defs.BH_WINDOWSIZE - defs.BH_HOPSIZE),
        #    oss_data[:-2*defs.BH_HOPSIZE]),
        oss_data,
        defs.BP_WINDOWSIZE, defs.BP_HOPSIZE)
    #beat_histogram_sr = oss_sr / defs.BP_HOPSIZE
    
    if defs.WRITE_BP:
        bp_accum = open("out/bp-accum.txt", "w")
    #print candidate_bpms_orig
    candidate_bpms = candidate_bpms_orig
    bphase = numpy.zeros(defs.BPM_MAX)
    for i in xrange(overlapped.shape[0]):
        cands = candidate_bpms[i]

        onset_scores = numpy.zeros(len(cands))
        tempo_scores = numpy.zeros(len(cands))
        for j, bpm in enumerate(cands):
            if bpm == 0:
                continue
            mag, var = calc_pulse_trains(bpm, overlapped[i], oss_sr)
            tempo_scores[j] = mag
            onset_scores[j] = var
        if defs.WRITE_BP:
            numpy.savetxt("out/bp-%i.txt" % (i+1),
                numpy.vstack((cands, tempo_scores, onset_scores)).transpose())
        tempo_scores /= tempo_scores.sum()
        onset_scores /= onset_scores.sum()

        combo_scores = tempo_scores + onset_scores
        combo_scores /= combo_scores.sum()

        # find best score
        besti = combo_scores.argmax()
        bestbpm = round(cands[besti])
        beststr = combo_scores[besti]


        bphase[ int(bestbpm) ] += beststr
            
        if defs.WRITE_BP:
            #numpy.savetxt("out/bp-%i.txt" % (i+1),
            #    numpy.vstack((cands, tempo_scores, onset_scores, combo_scores)).transpose())
            #numpy.savetxt("out/bp-peak-%i.txt" % (i+1),
            #    numpy.vstack((int(bestbpm), beststr)).transpose())
            text = "%i\t%.15f\n" % (int(bestbpm), beststr)
            bp_accum.write(text)

    if defs.WRITE_BP:
        bp = open('out/beat_phase.txt', 'w')
        for b in bphase:
            if b == 0:
                text = "0\n"
            else:
                text = "%.5f\n" % b
            bp.write(text)
        bp.close()

    if plot:
        pylab.figure()
        pylab.plot(numpy.arange(len(bphase)), bphase,
            label="marsyas")
        pylab.title("bphase")
        pylab.legend()

    bpm = bphase.argmax()
    #bpm_strength = bphase[bpm]

    if defs.CHECK_REFERENCE:
        calc = bphase
        ref = numpy.loadtxt(
            "reference/%s/beat_phase.txt" % defs.basename)
        delta = calc - ref
        maxerr = numpy.abs(delta).max()
        if maxerr < 1e-6:
            print "BP ok, maximum deviation %.2g" % maxerr
        else:
            pylab.figure()
            pylab.title("BP: calculated - reference")
            pylab.plot(delta)
            pylab.figure()
            pylab.plot(calc)
            pylab.plot(ref)
            pylab.show()
            exit(1)

    if defs.WRITE_BP:
        bp_accum.close()
    return bpm, bphase