Esempio n. 1
0
def absZ_test(sr):
    """Feed a signal at given sample rate
    to the detectorbank and take the absolute value
    of the response.
    
    Return the result, and max error comparing
    the abzZ method results and numpy.abs() results."""
    f = np.array([200])
    t = np.linspace(0, f[0]*2*np.pi, sr)
    audio = np.sin(t)
    #audio = np.append(audio, np.zeros(sr))

    z = np.zeros((len(f),len(audio)), dtype=np.complex128)
    method = DetectorBank.runge_kutta
    f_norm = DetectorBank.freq_unnormalized
    a_norm = DetectorBank.amp_normalized
    d = 0.0001
    bandwidth = np.zeros(len(f))
    det_char = np.array(list(zip(f, bandwidth)))
    gain = 25
    det = DetectorBank(sr, audio.astype(np.float32), 4, det_char, 
                    method|f_norm|a_norm, d, gain)

    det.getZ(z)

    r = np.zeros(z.shape)
    _ = det.absZ(r, z)

    return r, np.amax(np.abs(r-np.abs(z)))
Esempio n. 2
0
 def makeDetectorBank(self):
     """ Make DetectorBank from given parameters """
     
     sr = self.getSampleRate()
     bandwidth_cents = float(self.bandwidthEdit.text())
     dmp = float(self.dampingEdit.text())
     gain = float(self.gainEdit.text())
     edo = float(self.edoEdit.text())
     lwr = self.lwrEdit.text()
     upr = self.uprEdit.text()
     
     lwr, pitchOffset = getNoteNum(lwr, edo)
     upr, _ = getNoteNum(upr, edo)
     upr += 1 # include upr note in DetectorBank
     
     # make and fill frequency and bandwidth arrays
     freq = np.zeros(int(upr-lwr))
     bw = np.zeros(len(freq))
     for i in range(len(freq)):
         k = lwr+i
         freq[i] = 440*2**(k/edo)
         # if non-minimum bandwidth detectors requested, find B in Hz
         if bandwidth_cents != 0:
             bw[i] = centsToHz(freq[i], bandwidth_cents, edo)
             
     # combine into stacked array
     det_char = np.stack((freq,bw), axis=1)
     
     # (almost) empty input buffer
     buffer = np.zeros(1, dtype=np.float32)
     
     # DetectorBank features
     method = DetectorBank.runge_kutta
     f_norm = DetectorBank.freq_unnormalized
     a_norm = DetectorBank.amp_unnormalized
     
     self.db = DetectorBank(sr, buffer, 4, det_char, method|f_norm|a_norm, 
                             dmp, gain)
     
     # create empty output array
     self.z = np.zeros((int(self.db.getChans()),self.buflen), 
                       dtype=np.complex128)
     
     self.r = np.zeros(self.z.shape)
     
     print("Made DetectorBank with {} channels, with a sample rate of {}Hz"
           .format(self.db.getChans(), self.db.getSR()))
     
     return pitchOffset
    def _get_max(self, f, dbp):
        # make DetectorBank, get responses and return max value in response

        f = np.array([f])
        size = len(f)
        bandwidth = np.zeros(size)
        det_char = np.array(list(zip(f, bandwidth)))

        det = DetectorBank(self.sr, self.audio.astype(np.float32), 0, det_char,
                           *dbp)

        # get output
        z = np.zeros((size, len(self.audio)), dtype=np.complex128)
        r = np.zeros(z.shape)
        det.getZ(z, size)
        m = det.absZ(r, z)

        return m
Esempio n. 4
0
def plot_complex(f0, a_norm, do_plots):

    sr = 48000

    dur = 3
    t = np.linspace(0, 2 * np.pi * f0 * dur, sr * dur)
    audio = np.sin(t)
    audio = np.append(audio, np.zeros(sr))

    method = DetectorBank.runge_kutta
    f_norm = DetectorBank.freq_unnormalized

    d = 0.0001
    gain = 5
    f = np.array([f0])
    bandwidth = np.zeros(len(f))
    det_char = np.array(list(zip(f, bandwidth)))

    det = DetectorBank(sr, audio.astype(np.float32), 4, det_char,
                       method | f_norm | a_norm, d, gain)

    z = np.zeros((len(f), len(audio)), dtype=np.complex128)
    det.getZ(z)

    r = np.zeros(z.shape)
    det.absZ(r, z)

    # number of oscillations to plot
    nOsc = 5
    # signal may have been modulated by DetectorBank
    # detFreq is the frequency the detector is actually operating at, therefore
    # the frequency of the orbits
    detFreq = det.getW(0) / (2 * np.pi)
    # number of samples in nOsc
    sOsc = int(nOsc / detFreq * sr)

    t0 = (dur * sr) - sOsc  # int(0.0 * sr)
    t1 = dur * sr  # int(nOsc/f[0] * sr)

    x = z[0].real[t0:t1]
    y = z[0].imag[t0:t1]

    c = ['darkmagenta']

    a, b = getEllipseParams(x, y)
    e = np.sqrt(a**2 - b**2) / a

    if do_plots:
        plt.plot(x, y, c[0])
        plt.grid()

        plt.title('{}Hz'.format(f0))
        plt.xlabel('real')
        plt.ylabel('imag')

        plt.show()
        plt.close()

    return e
def get_response(sr, audio, f, bw=0, damping=0.0001):
    """ Get DetectorBank output
    
        Parameters
        ----------
        sr : int
            Sample rate
        audio : array
            Input samples
        f : one-element array
            Frequency to test, in an array
        bw : float
            Bandwidth. Default is minimum bandwidth
        damping : float
            Damping factor. Default is 0.0001
    """
    
    method = DetectorBank.runge_kutta
    f_norm = DetectorBank.freq_unnormalized
    a_norm = DetectorBank.amp_unnormalized
    gain = 1
    
    bandwidth = np.zeros(len(f))
    det_char = np.array(list(zip(f, bandwidth)))
     
    z = np.zeros((len(f),len(audio)), dtype=np.complex128)    
    r = np.zeros(z.shape) 
    
    det = DetectorBank(sr, audio, 4, det_char, method|f_norm|a_norm, damping, 
                       gain)
    
    det.getZ(z) 
    det.absZ(r, z)
    
    return r[0]
Esempio n. 6
0
    def _get_maxima(self, progress):
        # make DetectorBank, get responses and return max value in response

        size = len(self.f)

        maxima = np.zeros(size)

        # don't need all responses at once - just get max for each frequency
        # run in blocks of numPerRun channels to try and speed it up a bit

        numPerRun = 100

        numBlocks = int(np.ceil(size / numPerRun))
        count = 0

        i0, i1 = 0, 0

        more = True
        while more:
            i0 = i1
            i1 += numPerRun
            if i1 >= size:
                i1 = size
                more = False

            if progress:
                print('Running block {} of {}'.format(count, numBlocks),
                      end='\r')
#                print('{:.0f}%'.format(100*(i0/size)), end='\r')

            freq = self.f[i0:i1]
            bandwidth = np.zeros(len(freq))
            det_char = np.column_stack((freq, bandwidth))

            det = DetectorBank(self.sr, self.audio.astype(np.float32), 4,
                               det_char, *self.dbp)

            # get output
            z = np.zeros((len(freq), len(self.audio)), dtype=np.complex128)
            r = np.zeros(z.shape)
            det.getZ(z)
            det.absZ(r, z)

            for n in range(len(freq)):

                if np.isinf(np.max(r[n])):
                    file = 'debug/{:.0f}Hz.csv'.format(freq[n])
                    np.savetxt(file, r[n], delimiter='\t')

                maxima[i0 + n] = np.max(r[n])

            count += 1

#            maxima[n] = m

        return maxima
Esempio n. 7
0
def getMax(f0, sr, method, f_norm):
    """ Get maximum abs value in response. Also returns internal detector
        frequency (which will be different from f0 if search normalisation is
        used)
        
        Parameters
        ----------
        fo : float
            Centre frequency
        sr : int
            Sample rate
        method : DetectorBank Feature
            Numerical method
        f_norm : DetectorBank Feature
            Frequency normalisation
    
        Returns
        -------
        z value at point which is max value in |z|, max value in |z|,
        frequency used by detector 
    """

    f = np.array([f0])
    b = np.zeros(len(f))
    det_char = np.array(list(zip(f, b)))
    d = 0.0001
    amp = 5
    a_norm = DetectorBank.amp_unnormalized

    audio = make_audio(f0, 1, 4, sr)

    det = DetectorBank(sr, audio.astype(np.float32), 4, det_char,
                       method | f_norm | a_norm, d, amp)

    z = np.zeros((len(f), len(audio)), dtype=np.complex128)
    r = np.zeros(z.shape)

    det.getZ(z)
    m = det.absZ(r, z)

    i = np.where(r[0] == m)[0][0]
    mz = z[0][i]

    f_adjusted = det.getW(0) / (2 * np.pi)

    return mz, m, f_adjusted
    def _get_abs_z(self, freq, bandwidth, dbp):
        # make a DetectorBank with the given parameters and return |z|

        size = len(freq)
        bw = np.zeros(size)
        bw.fill(bandwidth)

        det_char = np.array(list(zip(freq, bw)))

        det = DetectorBank(self.sr, self.audio.astype(np.float32), 0, det_char,
                           *dbp)

        # get output
        z = np.zeros((size, len(self.audio)), dtype=np.complex128)
        r = np.zeros(z.shape)
        det.getZ(z, size)
        det.absZ(r, z)

        return r
Esempio n. 9
0
def get_responses(sr, audio, f):
    
    method = DetectorBank.runge_kutta
    f_norm = DetectorBank.freq_unnormalized
    a_norm = DetectorBank.amp_normalized
    gain = 25
    d = 0.0001
    bandwidth = np.zeros(len(f))
    #bandwidth.fill(5)  # uncomment for degerate detectors
    det_char = np.array(list(zip(f, bandwidth)))
     
    z = np.zeros((len(f),len(audio)), dtype=np.complex128)    
    r = np.zeros(z.shape) 
    
    det = DetectorBank(sr, audio, 4, det_char, method|f_norm|a_norm, d, gain)
    
    det.getZ(z) 
    det.absZ(r, z)
    
    return r
Esempio n. 10
0
def getResponses(sr, mode, method, f_norm):
    """ Get DetectorBank responses
    
        Parameters
        ----------
        sr : int
            sample rate
        mode : {'a', 'low', 'high'}
            frequency range
        method : DetectorBank Feature
            DetectorBank numerical method
        f_norm : DetectorBank Feature
            DetectorBank frequency normalisaion
            
        Returns
        -------
        2D array of |z| values
    """

    f = getFrequencies(mode)

    audio = make_audio(f, np.ones(len(f)), sr)

    d = 0.0001
    gain = 5
    a_norm = DetectorBank.amp_unnormalized
    bandwidth = np.zeros(len(f))
    det_char = np.array(list(zip(f, bandwidth)))

    z = np.zeros((len(f), len(audio)), dtype=np.complex128)
    r = np.zeros(z.shape)

    det = DetectorBank(sr, audio.astype(np.float32), 4, det_char,
                       method | f_norm | a_norm, d, gain)

    det.getZ(z)
    det.absZ(r, z)

    return r
    def _get_abs_z(self, freq, flc):
        # make a DetectorBank with the given parameters and return |z|

        size = len(freq)
        bw = np.zeros(size)
        bw.fill(flc)

        det_char = np.array(list(zip(freq, bw)))

        # NB have changed DetectorBank code to regard det_char as freq,fLc
        # pairs instead of freq,bw pairs
        # all that is required to do this is change AbstractDetector::getLyapunov
        # to simply return the value it is passed
        # i.e. we pretend that 'bandwidth' values are Lyapunov coeff
        det = DetectorBank(self.sr, self.audio.astype(np.float32), 0, det_char,
                           *self.dbp)

        # get output
        z = np.zeros((size, len(self.audio)), dtype=np.complex128)
        r = np.zeros(z.shape)
        det.getZ(z, size)
        det.absZ(r, z)

        return r
Esempio n. 12
0
import numpy as np
from detectorbank import DetectorBank

# array of frequencies (corresponding to 88 key piano)
f = np.array(list(440 * 2**(k/12) for k in range(-48, 40)))
bandwidth = np.zeros(len(f))
det_char = np.stack((f, bandwidth), axis=1)

# detectorbank  parameters
sr = 48000
method = DetectorBank.runge_kutta
f_norm = DetectorBank.freq_unnormalized
a_norm = DetectorBank.amp_normalized
damping = 0.0001
gain = 25

# construct a DetectorBank, giving an empty array as input
det = DetectorBank(sr, np.zeros(1).astype(np.float32), 0, det_char, 
                   method|f_norm|a_norm, damping, gain)

# save the DetectorBank as '88 key piano, RK4, f un, a nrm'
det.saveProfile('88 key piano, RK4, f un, a nrm')
Esempio n. 13
0
def getLyapunov(fd, f0, sr, plot=True, b=None):

    freq = np.array([f0 - fd, f0, f0 + fd])

    if b is None:
        b = get_b(2 * fd)
    print('Frequency difference: {}Hz; Bandwidth: {}Hz'.format(fd, 2 * fd))
    print('First Lyapunov coefficient: {:.3f}'.format(b))

    method = DetectorBank.runge_kutta
    f_norm = DetectorBank.freq_unnormalized
    a_norm = DetectorBank.amp_unnormalized
    gain = 1
    damping = 0.0001
    dbp = (method | f_norm | a_norm, damping, gain)

    audio = make_input(f0, sr, 3)
    audio *= 25

    size = len(freq)
    bw = np.zeros(size)
    bw.fill(b)

    det_char = np.array(list(zip(freq, bw)))

    # NB have changed DetectorBank code to regard det_char as freq,fLc
    # pairs instead of freq,bw pairs
    # all that is required to do this is change AbstractDetector::getLyapunov
    # to simply return the value it is passed
    # i.e. we pretend that 'bandwidth' values are Lyapunov coeff
    det = DetectorBank(sr, audio.astype(np.float32), 0, det_char, *dbp)

    # get output
    z = np.zeros((size, len(audio)), dtype=np.complex128)
    r = np.zeros(z.shape)
    det.getZ(z, size)
    det.absZ(r, z)

    t = np.linspace(0, r.shape[1] / sr, r.shape[1])
    c = ['blue', 'darkmagenta', 'red']

    mx_centre = np.max(r[np.where(freq == f0)[0][0]])

    maxima = np.array([np.max(k) for k in r])
    ratio = maxima / mx_centre
    ratio_db = 20 * np.log10(ratio)

    for k in range(r.shape[0]):

        print('{:.0f}Hz; max = {:.4f}; ratio = {:.4f}; {:.4f}dB'.format(
            freq[k], maxima[k], ratio[k], ratio_db[k]))

        if plot:
            line, = plt.plot(t, r[k], c[k])

    mean = (ratio_db[0] + ratio_db[2]) / 2
    diff = abs(-3 - mean)
    print('Mean ampltiude: {:.4f}dB'.format(mean))
    print('Difference from -3dB: {:.4f}dB'.format(diff))

    if plot:
        plt.show()
        plt.close()
def plotMean(audio, sr, freq, onset, found, sp):

    sns.set_style('whitegrid')

    if audio.ndim > 1:
        audio = np.mean(audio, axis=1)

    offset = 1 / 4
    pad = np.zeros(int(sr * offset))
    #    pad.fill(audio[0])

    audio = np.append(pad, audio)

    params = getParams()
    method = params['method']
    f_norm = params['f_norm']
    a_norm = params['a_norm']
    d = params['damping']
    gain = params['gain']

    bw = params['real_bandwidth']
    edo = params['edo']

    f = makeBand(freq, bw, edo)

    bandwidth = np.zeros(len(f))
    det_char = np.array(list(zip(f, bandwidth)))

    det = DetectorBank(sr, audio.astype(np.float32), 4, det_char,
                       method | f_norm | a_norm, d, gain)

    z = np.zeros((len(f), len(audio)), dtype=np.complex128)
    det.getZ(z)

    r = np.zeros(z.shape)
    det.absZ(r, z)

    meanlog = np.zeros(len(audio))

    for n in range(len(meanlog)):
        mean = 0
        for k in range(det.getChans()):
            mean += zeroLog(r[k, n])
        meanlog[n] = mean

    t = np.linspace(0, len(audio) / sr, len(audio))

    t0 = 0.25
    t1 = 0.5

    i0 = int(sr * t0)
    i1 = int(sr * t1)

    plt.figure()
    plt.plot(t[i0:i1], meanlog[i0:i1])

    plt.axvline(onset + offset, color='lime')  # linestyle='--', )
    for t in found:
        plt.axvline(t + offset, linestyle='--', color='red')

    ax = plt.gca()
    xtx = ax.get_xticks()
    xtxlab = ['{:.0f}'.format(1000 * (item - offset)) for item in xtx]
    ax.set_xticklabels(xtxlab)

    #    plt.title('{:.3f}Hz'.format(freq))
    plt.xlabel('Time (ms)')
    #    plt.ylabel('Log(|z|)')
    plt.ylabel('Mean log')
    plt.grid(True)

    sp.plot(plt)
Esempio n. 15
0
def get_responses(file,
                  damping,
                  sp,
                  tp=None,
                  fp=None,
                  fn=None,
                  sl=None,
                  t0=None,
                  t1=None,
                  spa=None):

    sns.set_style('whitegrid')

    head, tail = os.path.split(file)
    base, ext = os.path.splitext(tail)

    # `base` is file name with data separated by dots
    # go backwards through each item and see if it is a note
    baselst = base.split('.')
    i = -1
    while True:
        # if we've gone as far back as we can without finding a note, exit
        if i <= -len(baselst):
            msg = 'Cannot parse note in filename {}'.format(tail)
            raise ValueError(msg)
        # check if the file is a (xylophone) glissandi
        if baselst[i].lower() == 'gliss':
            # assuming same xylophone used for all recordings
            if baselst[i + 1].lower() == 'up':
                k = get_note_num('F4')
                break
            elif baselst[i + 1].lower() == 'down':
                k = get_note_num('C8')
                break
#            note_n = list(range(k0, k1+1))
# try this item
        try:
            # get note number relative to A4 (for frequency calculation)
            k = get_note_num(baselst[i])
            break
        # if this item isn't a note, go backwards and try again
        except ValueError:
            i -= 1

    edo = 12
    method = DetectorBank.runge_kutta
    f_norm = DetectorBank.freq_unnormalized
    a_norm = DetectorBank.amp_unnormalized
    gain = 50

    bw = {1e-4: 0.922, 2e-4: 1.832, 3e-4: 2.752, 4e-4: 3.606, 5e-4: 4.86}

    f0 = 440 * 2**(k / edo)
    f = get_f(f0, b=bw[damping], edo=edo)

    print('Band size: {}'.format(len(f)))

    audio, sr = sf.read(file)

    if spa is not None:
        plot_audio(sr, audio, spa, t0, t1, tp=tp, fp=fp)

    bandwidth = np.zeros(len(f))
    det_char = np.array(list(zip(f, bandwidth)))
    det = DetectorBank(sr, audio.astype(np.float32), 4, det_char,
                       method | f_norm | a_norm, damping, gain)

    z = np.zeros((len(f), len(audio)), dtype=np.complex128)
    r = np.zeros(z.shape)
    det.getZ(z)
    det.absZ(r, z)

    c = [
        'black', 'blue', 'chocolate', 'cyan', 'darkmagenta', 'khaki',
        'deeppink', 'aquamarine', 'darkorange', 'firebrick', 'green',
        'lightslategrey', 'dodgerblue', 'magenta', 'mediumvioletred', 'orange',
        'pink', 'red', 'skyblue', 'lightgrey', 'yellow'
    ]

    centre_idx = c.index('green')
    centre_f = np.where(f == f0)[0][0]
    color_offset = centre_idx - centre_f

    print('Centre freq at index: {}'.format(centre_f))
    print('Colour offset: {}'.format(color_offset))

    t = np.linspace(0, r.shape[1] / sr, r.shape[1])
    if t0 is None:
        t0 = 0
    else:
        t0 = int(sr * t0)
    if t1 is None:
        t1 = len(audio)
    else:
        t1 = int(sr * t1)

    for k in range(r.shape[0]):
        plt.plot(t[t0:t1],
                 r[k][t0:t1],
                 color=c[(k + color_offset) % len(c)],
                 label='{:.3f}Hz'.format(f[k]))

    if tp is not None:
        for onset in tp:
            plt.axvline(onset, color='lime')
    if fp is not None:
        for onset in fp:
            plt.axvline(onset, color='mediumorchid', linestyle='--')
    if fn is not None:
        for onset in fn:
            plt.axvline(onset, color='indigo', linestyle='--')

    plt.xlabel('Time (s)')
    plt.ylabel('|z|', rotation='horizontal', labelpad=10)
    #    ax = plt.gca()
    #    ax.ticklabel_format(axis='y', style='sci', scilimits=(0,0))

    if sl is not None:
        colours = [c[k + color_offset] for k in range(r.shape[0])]
        labels = ['{:.3f} Hz'.format(f[k]) for k in range(r.shape[0])]
        sl.plot(labels=labels,
                colours=colours,
                ncol=1,
                title='Detector frequencies')


#    else:
#        plt.legend()

    plt.grid(True)

    sp.plot(plt)
def run(which, outdir):
    
    # get parameters
    parameters = get_dict()
    fname = parameters[which]['fname']
    file = os.path.join(parameters[which]['datapath'], fname + '.wav')
    
    # get paths to onsets.txt and to location to write results
    whichpath = os.path.join('results', which)
    savepath = os.path.join(whichpath, outdir)
       
    if os.path.exists(savepath):
        print('{} exists. Overwrite? [Y/n]'.format(savepath))
        answer = input()
        if answer not in ['', 'y', 'Y']:
            sys.exit(0)
    else:
        os.makedirs(savepath)
    
    # DetectorBank parameters
    audio, sr = sf.read(file)
    
    bandwidth = 0
    method = DetectorBank.runge_kutta
    f_norm = DetectorBank.freq_unnormalized
    a_norm = DetectorBank.amp_unnormalized
    d = 0.0001
    gain = 50
    
    r = parameters[which]['range']
    frequencies = np.array(list(440*2**(k/12) for k in r))
    
    band_types = ['1Hz-spaced', 'EDO']
    band_type = band_types[1]
    
    num = 21
    
    threshold = parameters[which]['threshold']
    
    print('Analysing {} with threshold of {}'.format(fname, threshold))
           
    # new way of making a NoteDetector
    nd = NoteDetector(sr, audio.astype(np.float32), frequencies, num, 
                      bandwidth, method|f_norm|a_norm, d, gain)
    
    # write file of OnsetDetector parameters that will be used here
    with open(os.path.join(savepath, 'ondet_params.txt'), 'w') as fileobj:
        
        fileobj.write(time.ctime(time.time()) + '\n\n')
        
        fileobj.write('Input: '+fname+'\n')
        fileobj.write('seg_len: 20ms, 100 segments\n')
        fileobj.write('With stop-start >= log(2) criterion\n')
        fileobj.write('Backtracking with local min\n')
        fileobj.write('Log threshold/seg avg.\n')
        fileobj.write('Critical band: {} detectors, {}\n'.format(num, band_type))
        fileobj.write('Threshold: {}\n'.format(threshold))
        fileobj.write('C++\n')
    
    # for each frequency the user asks for...
    for f0 in frequencies:
    
        fname = '{}Hz.txt'.format(int(f0))
        
        print('{:.0f}Hz'.format(f0))
    
        # make critical band freqs
        f = make_band(f0, band_type, num)
        
        # make a DetectorBank
        bandwidth = np.zeros(len(f))
        det_char = np.array(list(zip(f, bandwidth)))
        det = DetectorBank(sr, audio.astype(np.float32), 4, det_char,
                           method|f_norm|a_norm, d, gain)
        
        # use (now defunct) OnsetDetector
        od = OnsetDetector(det)
        # get onsets
        onsets = od.analyse(threshold)
        onsets = np.array(onsets)
        
        # write results to file
        with open(os.path.join(savepath, fname), 'w') as fileobj:
            fileobj.write('Onsets\n------\n')
            
            for onset in onsets:
                line = 'sample {:6d}, {:6.3f} seconds\n'.format(onset, onset/sr)
                fileobj.write(line)
            
            # no longer finding offset times
            fileobj.write('\nOffsets\n-------\n')
            
    # check returned onsets
    c = CheckOnsets(whichpath, savepath)
    precision, recall, fmeasure, precision_e, fmeasure_e = c.check(True, savepath)
Esempio n. 17
0
f_norm = DetectorBank.freq_unnormalized
a_norm = DetectorBank.amp_unnormalized
d = 0.0001
gain = 29

f0 = 440*2**(1/12)

hwidth = 10
step = 1
    
    
f = np.arange(f0-hwidth, f0+hwidth+step, step)

bandwidth = np.zeros(len(f))
det_char = np.array(list(zip(f, bandwidth)))
det = DetectorBank(sr, audio.astype(np.float32), 4, det_char, 
                   method|f_norm|a_norm, d, gain)

buflen = det.getBuflen()

channels = det.getChans()

z = np.zeros((len(f),len(audio)), dtype=np.complex128)
r = np.zeros(z.shape)
det.seek(0)
det.getZ(z)
m = det.absZ(r, z)

######## matching straight line and decaying exponential

## get portion of response that corresponds to single note
#t = np.linspace(0, len(audio), len(audio))
Esempio n. 18
0
method = DetectorBank.runge_kutta
f_norm = DetectorBank.freq_unnormalized
a_norm = DetectorBank.amp_unnormalized
d = 0.0001
gain = 50

# one critical band around 440Hz
f0 = 440 * 2**(-2 / 12)
hwidth = 10
step = 1
f = np.arange(f0 - hwidth, f0 + hwidth + step, step)

bandwidth = np.zeros(len(f))
det_char = np.array(list(zip(f, bandwidth)))
det = DetectorBank(sr, audio.astype(np.float32), 4, det_char,
                   method | f_norm | a_norm, d, gain)

p = Producer(det)
seg_len = sr // 2
cache = DetectorCache(p, 2, seg_len)

channels = det.getChans()
N = 1000
prep = Preprocessor(cache, seg_len, np.arange(channels, dtype=np.int_), N)

od = OnsetDetector(prep, np.arange(channels, dtype=np.int_), sr)

gradient = np.array([od.do_stuff(n) for n in range(det.getBuflen())])

onsets = od.onsets
offsets = od.offsets
Esempio n. 19
0
def plot_complex(f0, i, nOsc, end):

    d = 0.0001

    sr = 48000

    dur = 5
    t = np.linspace(0, 2 * np.pi * f0 * dur, sr * dur)
    audio = np.sin(t)
    audio = np.append(audio, np.zeros(sr))
    gain = 5

    method = DetectorBank.runge_kutta  #central_difference #
    f_norm = DetectorBank.freq_unnormalized
    a_norm = DetectorBank.amp_unnormalized
    d = 0.0001
    gain = 5
    f = np.array([f0])
    bandwidth = np.zeros(len(f))
    det_char = np.array(list(zip(f, bandwidth)))

    det = DetectorBank(sr, audio.astype(np.float32), 4, det_char,
                       method | f_norm | a_norm, d, gain)

    z = np.zeros((len(f), len(audio)), dtype=np.complex128)
    det.getZ(z)

    r = np.zeros(z.shape)
    det.absZ(r, z)

    # number of oscillations to plot
    # signal may have been modulated by DetectorBank
    # detFreq is the frequency the detector is actually operating at, therefore
    # the frequency of the orbits
    detFreq = det.getW(0) / (2 * np.pi)
    # number of samples in nOsc
    sOsc = int(nOsc / detFreq * sr)

    if end == 'first':
        t0 = 0
        t1 = sOsc
    elif end == 'last':
        t0 = (dur * sr) - sOsc
        t1 = dur * sr

    x = z[0].real[t0:t1]
    y = z[0].imag[t0:t1]

    c = ['darkmagenta']

    a, b = getEllipseParams(x, y)
    e = np.sqrt(a**2 - b**2) / a

    plt.plot(x, y, c[0])
    plt.grid(True)

    plt.xlabel('real')
    plt.ylabel('imag')

    fig = plt.gcf()
    fig.set_size_inches(8, 8)

    plt.show()
    plt.close()

    return e
f = np.array(list(440 * 2 ** (k/12) for k in range(-5,5)))
bandwidth = np.zeros(len(f))
# change the bandwidth of the last detector
bandwidth[2] = 7
# make 2D array of frequencies and bandwidths
det_char = np.stack((f, bandwidth), axis=1)
         
# detectorbank  parameters
method = DetectorBank.runge_kutta
f_norm = DetectorBank.freq_unnormalized
a_norm = DetectorBank.amp_normalized
damping = 0.0001
gain = 25
 
# construct DetectorBank
det = DetectorBank(sr, audio.astype(np.float32), 0, det_char,
                   method|f_norm|a_norm, damping, gain)

# make a producer
p = Producer(det)

# 2 segments, each containing sr (48000) abs(z) values
cache = DetectorCache(p, 2, sr)

# get the first abs(z) value from channel five
result = cache[5,0]
print(result)

# get the 100000th value from channel seven
# this causes a new segment to be generated (100000 > 2*sr)
result = cache[7,100000]
print(result)
y = y.astype(np.float32)


mthd = DetectorBank.runge_kutta
fnrm = DetectorBank.freq_unnormalized
anrm = DetectorBank.amp_normalized
d = 0.0001
bw = np.zeros(len(f))
det_char = np.array(list(zip(f, bw)))

ys = np.zeros(y.shape, dtype=np.dtype('float32'))
fsmode = FrequencyShifter.fft
fs = FrequencyShifter(y, sr, fsmode)
fs.shift(-3900, ys)

det = DetectorBank(sr, ys.astype(np.float32), 4, det_char, mthd|fnrm|anrm, d)

z = np.zeros((len(f),len(y)), dtype=np.complex128)   
n = det.getZ(z)

r = np.zeros(z.shape)  
m = det.absZ(r, z)


t = np.linspace(0, r.shape[1]/sr, r.shape[1])
#c = ['blue', 'red', 'green']
c = ['red', 'orange',  'darkmagenta', 'lawngreen', 'blue']
style = ['-.', ':', '-', '--', '--']
style = ['-', ':', '--']
        
t = np.linspace(0, len(y)/sr, len(y))
Esempio n. 22
0
    f_norm = DetectorBank.freq_unnormalized
    a_norm = DetectorBank.amp_unnormalized
    d = 0.0001
    gain = 50
    
    f0 = 440*2**(-2/12)
    
    # select and make critical band
    band_types = ['1Hz-spaced', 'EDO']
    band_type = band_types[1]
    num = 21 # 31 #
    f = make_band(f0, band_type, num)
    
    bandwidth = np.zeros(len(f))
    det_char = np.array(list(zip(f, bandwidth)))
    det = DetectorBank(sr, audio.astype(np.float32), 4, det_char,
                       method|f_norm|a_norm, d, gain)
    
    chans = det.getChans()
    p = Producer(det)
    cache = DetectorCache(p, 2, sr//2)
    
    r = np.zeros(len(audio))
    for i in range(len(r)):
        for k in range(chans):
            r[i] += np.log(cache[k,i]) #cache[k,i] # 
        r[i] /= chans
    
    t = np.linspace(0, len(audio)/sr, len(audio))
    
    plt.plot(t[i0:i1], r[i0:i1])
Esempio n. 23
0
class Visualizer(QMainWindow):
    
    def __init__(self):
        
        super().__init__()
        self.initUI()
        self._buflen = 1440 # 4096


    def initUI(self):
        
        # main window/layout
        window = QWidget()
        layout = QVBoxLayout()
        
        # layout for audio device and sample rate selection
        deviceLayout = QHBoxLayout()
        
        # make audio device selection box and list of available devices
        self.deviceBox = QComboBox()
        defaultDeviceInfo = QAudioDeviceInfo.defaultInputDevice()
        self.availableDevices = [defaultDeviceInfo]
        self.availableDevices += QAudioDeviceInfo.availableDevices(
                                                             QAudio.AudioInput)
        for device in self.availableDevices:
            self.deviceBox.addItem(device.deviceName())
            
        # make sample rate label and combobox
        sRateLabel = QLabel("Sample rate:")
        sRateLabel.setAlignment(Qt.AlignRight)
        
        # user can choose between 44.1 and 48kHz (valid DetectorBank rates)
        self.sRateBox = QComboBox()
        self.sRateBox.addItem("44100")
        self.sRateBox.addItem("48000")
        self.sRateBox.setCurrentIndex(1)
        
        # add device and sr widgets to device layout
        deviceLayout.addWidget(self.deviceBox)
        deviceLayout.addWidget(sRateLabel)
        deviceLayout.addWidget(self.sRateBox)
        
        # add device layout to main layout
        layout.addLayout(deviceLayout)
        
        # DetectorBank parameters layout
        # two rows of three parameters
        # each param needs label and edit, 
        # and a 'Start' button will be added at the bottom
        # so grid should be 3x6
        detBankParamLayout = QGridLayout()
        
        # label and lineedit for each
        bandwidthLabel = QLabel("Bandwidth (cents):")
        dampingLabel = QLabel("Damping:")
        gainLabel = QLabel("Gain:")
        edoLabel = QLabel("EDO:")
        lwrLabel = QLabel("Lower note:")
        uprLabel = QLabel("Upper note:")
        
        self.bandwidthEdit = QLineEdit("0")
        self.dampingEdit = QLineEdit("0.0001")
        self.gainEdit = QLineEdit("25")
        self.edoEdit = QLineEdit("12")
        self.lwrEdit = QLineEdit("A1")
        self.uprEdit = QLineEdit("A7")
        
        # store all in lists
        detBankParamLabels = [bandwidthLabel, dampingLabel, gainLabel, 
                              edoLabel, lwrLabel, uprLabel]
        
        detBankParamEdits = [self.bandwidthEdit, self.dampingEdit, 
                             self.gainEdit, self.edoEdit, self.lwrEdit, 
                             self.uprEdit]
         
        # fill first two rows of grid with labels and edits
        row = 0

        for row in range(2):
            widgetNum = 0
        
            for i in range((row*3), (row*3)+3):
                detBankParamLayout.addWidget(detBankParamLabels[i], row, 
                                             widgetNum)
                widgetNum += 1
                detBankParamLayout.addWidget(detBankParamEdits[i], row, 
                                             widgetNum)
                widgetNum += 1
            
        # align labels to the right (next to the edit)
        for i in range(len(detBankParamLabels)):
            detBankParamLabels[i].setAlignment(Qt.AlignRight)
                
        # button to make DetectorBank and start visualisation
        row += 1
        startButton = QPushButton("&Start!")
        detBankParamLayout.addWidget(startButton, row, 5)
        startButton.clicked.connect(self.start)
        
        # add grid of detbank params (and start button) to main layout
        layout.addLayout(detBankParamLayout)
        
        window.setLayout(layout)
        self.setCentralWidget(window)
        self.show()
        
        
    def initializeAudio(self, deviceInfo):
        """ Make a QAudioInput from the given device """
                
        # make buffers of 40ms of samples
        self.refRate = 0.04
        
        # mono, 32-bit float audio
        fmt = QAudioFormat()
        fmt.setSampleRate(self.getSampleRate())
        fmt.setChannelCount(1)
        fmt.setSampleSize(32)
        fmt.setSampleType(QAudioFormat.Float)
        fmt.setByteOrder(QAudioFormat.LittleEndian)
        fmt.setCodec("audio/pcm")
        
        if not deviceInfo.isFormatSupported(fmt):
            fmt = deviceInfo.nearestFormat(fmt)
            
        self.audioInput = QAudioInput(deviceInfo, fmt)
        self.audioInput.setBufferSize(4*self.buflen) # set size in bytes

        
    def startAudio(self):
        self.audioDevice = self.audioInput.start()
        self.audioDevice.readyRead.connect(self.updatePlot)
        
        
    def start(self):
        """ Initialise audio, make DetectorBank, open PlotData window and 
            start audio 
        """
        
        print('Initializing audio...')
        deviceIdx = self.deviceBox.currentIndex()
        device = self.availableDevices[deviceIdx]
        self.initializeAudio(device)
        
        print('Making DetectorBank...')
        pitchOffset = self.makeDetectorBank()
        
        print('Making PlotData object...')
        self.pd = PlotData(self.db.getChans(), pitchOffset)
#        self.pd.show()
        
        print('Starting audio...')
        self.startAudio()
        
    
    def updatePlot(self):
        
        # get data as float32
        # 4*buflen is number of bytes
        data = self.audioDevice.read(4*self.buflen)
        data = np.frombuffer(data, dtype=np.int16)
        data = np.array(data/2**15, dtype=np.dtype('float32'))
        
        # set DetectorBank input
        self.db.setInputBuffer(data)
          
        # fill z with detector output
        self.db.getZ(self.z)
        
#        self.db.absZ(self.r, self.z)
        
        self.pd.update(self.z)
        
#        self.close()
        
        
    def makeDetectorBank(self):
        """ Make DetectorBank from given parameters """
        
        sr = self.getSampleRate()
        bandwidth_cents = float(self.bandwidthEdit.text())
        dmp = float(self.dampingEdit.text())
        gain = float(self.gainEdit.text())
        edo = float(self.edoEdit.text())
        lwr = self.lwrEdit.text()
        upr = self.uprEdit.text()
        
        lwr, pitchOffset = getNoteNum(lwr, edo)
        upr, _ = getNoteNum(upr, edo)
        upr += 1 # include upr note in DetectorBank
        
        # make and fill frequency and bandwidth arrays
        freq = np.zeros(int(upr-lwr))
        bw = np.zeros(len(freq))
        for i in range(len(freq)):
            k = lwr+i
            freq[i] = 440*2**(k/edo)
            # if non-minimum bandwidth detectors requested, find B in Hz
            if bandwidth_cents != 0:
                bw[i] = centsToHz(freq[i], bandwidth_cents, edo)
                
        # combine into stacked array
        det_char = np.stack((freq,bw), axis=1)
        
        # (almost) empty input buffer
        buffer = np.zeros(1, dtype=np.float32)
        
        # DetectorBank features
        method = DetectorBank.runge_kutta
        f_norm = DetectorBank.freq_unnormalized
        a_norm = DetectorBank.amp_unnormalized
        
        self.db = DetectorBank(sr, buffer, 4, det_char, method|f_norm|a_norm, 
                                dmp, gain)
        
        # create empty output array
        self.z = np.zeros((int(self.db.getChans()),self.buflen), 
                          dtype=np.complex128)
        
        self.r = np.zeros(self.z.shape)
        
        print("Made DetectorBank with {} channels, with a sample rate of {}Hz"
              .format(self.db.getChans(), self.db.getSR()))
        
        return pitchOffset
        
    ## get and/or set various values
    def getSampleRate(self, returnType=int):
        return returnType(self.sRateBox.currentText())
    
    @property
    def refreshRate(self):
        return self._refRate
    
    @refreshRate.setter
    def refreshRate(self, value):
        self._refRate = value
        self.buflen = self._refRate * self.getSampleRate()
    
    @property
    def buflen(self):
        return self._buflen
        
    @buflen.setter
    def buflen(self, value):
        self._buflen = int(value)
Esempio n. 24
0
length = 2
t = np.linspace(0, 2 * np.pi * f0 * length, sr * length)
audio = np.sin(t)
audio = np.append(audio, np.zeros(sr))

#### plot figure

f = np.array([f0, f0 + 1, f0 + 2])

bandwidth = np.zeros(len(f))
det_char = np.array(list(zip(f, bandwidth)))

z = np.zeros((len(f), len(audio)), dtype=np.complex128)
r = np.zeros(z.shape)

det = DetectorBank(sr, audio, 4, det_char, method | f_norm | a_norm, d, amp)

det.getZ(z)
det.absZ(r, z)

t = np.linspace(0, len(audio) / sr, len(audio))
c = ['darkmagenta', 'orange', 'red']
style = ['-', ':', '--']
#t *= 1000
t0 = 0
t1 = len(audio)  # int(sr * 0.2) #
for k in range(len(r)):
    plt.plot(t[t0:t1], r[k][t0:t1], c[k], label=f[k])
    print('Det freq: {}Hz'.format(det.getW(k) / (2 * np.pi)))
#    plt.plot(t[t0:t1], r[k][t0:t1], 'black', label=f[k], linestyle=style[k])
Esempio n. 25
0
audio = audio/np.amax(audio)


# detectorbank  parameters
method = DetectorBank.runge_kutta
f_norm = DetectorBank.freq_unnormalized
a_norm = DetectorBank.amp_normalized
damping = 0.0001
# minimum bandwidth detectors
bandwidth = np.zeros(len(f))
#bandwidth[1] = 5
#bandwidth[2] = 7
#bandwidth.fill(5)
det_char = np.array(list(zip(f, bandwidth)))
gain = 5
det = DetectorBank(sr, audio.astype(np.float32), 4, det_char, 
                   method|f_norm|a_norm, damping, gain)

z = np.zeros((len(f),len(audio)), dtype=np.complex128)  
det.getZ(z)

r = np.zeros(z.shape)
m = det.absZ(r, z)

c = ['darkmagenta', 'red', 'blue', 'green']

t = np.linspace(0, r.shape[1]/sr, r.shape[1])
for k in range(r.shape[0]):
    line, = plt.plot(t, r[k], 'darkmagenta') 
    
ax = plt.gca()
plt.xlabel('Time (s)')
def get_rise_relax_times(d,
                         f0,
                         sr,
                         method,
                         f_norm,
                         a_norm,
                         gain,
                         plot_times,
                         sp=None):
    """ Get rise and relax times for a DetectorBank at five damping factors
    
        Parameters
        ----------
        d : list
            List of damping factors to test
        f0 : float
            Centre frequency
        sr : int
            Sample rate
        method : { DetectorBank.runge_kutta, DetectorBank.central_difference }
            DetectorBank method
        f_norm : { DetectorBank.freq_unnormalized, DetectorBank.search_normalized}
            DetectorBank frequency normalisation
        a_norm : { DetectorBank.amp_unnormalized, DetectorBank.amp_normalized}
            DetectorBank amplitude normalisation
        gain : float
            Input gain
        plot_times : bool
            Whether or not to plot the responses
        sp : list of SavePlot object
            If plot=True, please also provide a SavePlot object for rise and
            relax
            
        Returns
        -------
        Two lists of tuples: rise times and relax times.
        
        In each case, the tuples are the boundary times (10% time and 90% time
        or max time and 1/e time). The rise and relaxation times are the
        difference between these values.
    """

    # make input
    # 'dur' is tone duration
    # 2 seconds of silence will automatically be appended
    dur = 3
    audio = make_audio([f0], sr, dur)

    # make frequency/bandwidth pairs
    f = np.array([f0])
    b = np.zeros(len(f))
    det_char = np.array(list(zip(f, b)))

    # relaxation times
    rxtms = []
    # rise times
    rstms = []
    # rise time is time from 10% to 90% of final value
    r_min, r_max = 0.1, 0.9

    # if we're plotting, we'll have to store all the responses
    if plot_times:
        all_r = np.zeros((len(d), len(audio)))

        # also check there is a SavePlot object
        if sp is None:
            raise ValueError('Please provide a SavePlot object is you wish to '
                             'plot the responses')

    # get response for each damping factor
    for n in range(len(d)):

        z = np.zeros((len(f), len(audio)), dtype=np.complex128)
        r = np.zeros(z.shape)

        det = DetectorBank(sr, audio.astype(np.float32), 4, det_char,
                           method | f_norm | a_norm, d[n], gain)
        det.getZ(z)
        mx = det.absZ(r, z)

        if plot_times:
            all_r[n] = r

        # r is a 2D array. As there's only one channel, r[0] contains the output

        # rise time
        rise0 = np.where(r[0] >= r_min * mx)[0][0]
        rise1 = np.where(r[0] >= r_max * mx)[0][0]
        rstms.append((rise0, rise1))

        # relaxation time is time for amplitude to fall to 1/e of max
        rxamp = max(r[0]) / np.e
        # max is end of tone
        # NB can't say np.where(r[k]==mx), as this may return values before the
        # end of the tone
        mxtm = sr * dur
        # samples from max time to 1/e
        rxtm = np.where(r[0][mxtm:] <= rxamp)[0][0]
        rxtms.append((mxtm, mxtm + rxtm))

    if plot_times:
        plot(all_r, rstms, sr, len(audio), sp[0], t0=0, t1=1.1)
        plot(all_r, rxtms, sr, len(audio), sp[1], t0=2.95, t1=3.65)

    return rstms, rxtms