def filterByBasefrq(src, basefrq, width):
    peaksPos = findpeaks(src, spacing=50, limit=max(src) * 0.05)
    peaks = src[peaksPos]  # 峰值大小
    tar = np.copy(src)
    num = min(int(len(src) / basefrq), 30)
    for i in np.arange(num):
        frq = i * basefrq
        tar[frq - width:frq + width] = min(src[frq - width], src[frq + width])
    return tar
Exemple #2
0
def subpeakAmpLimiting(dataClip, space, limit):
    peaks = findpeaks(dataClip, spacing=space, limit=max(dataClip) * limit)
    if len(peaks) == 0:
        return dataClip
    dots = np.copy(dataClip[peaks])
    dots[np.argmax(dots)] = 0
    maxval = max(dots)
    # 如果等于0 说明只有一个峰
    if maxval > 0:
        # dataClip = 3
        np.where(dataClip < maxval, dataClip, maxval)
    return dataClip
Exemple #3
0
    def subpeak_amplimiting(dataclip, space, limit):
        """

        :param dataclip:输入
        :param space:寻峰宽度
        :param limit:寻峰阈值
        :return:次高峰值限制幅度结果
        """
        peaks = findpeaks(dataclip, spacing=space, limit=max(dataclip) * limit)
        if len(peaks) == 0:
            return dataclip
        dots = np.copy(dataclip[peaks])
        dots[np.argmax(dots)] = 0
        maxval = max(dots)
        # 如果等于0 说明只有一个峰
        if maxval > 0:
            dataclip = np.where(dataclip < maxval, dataclip, maxval)
        return dataclip
Exemple #4
0
def getPitch(dataClip,Fs,nfft):
    pitch=0
    dataClip[0:int(30*nfft/Fs)]=0
    #print(frame*nfft/Fs) #当前时刻
    fftData=fft(dataClip)[0:int(len(dataClip)/2)]
    if showTestView: 
        plt.subplot(121)
        plt.plot(np.arange(len(dataClip)), dataClip)
    cepstrum=MaxMinNormalization(np.abs(fftData)*2/nfft,0,1)
    cutoff=int(Fs/2/1200)
    #cepstrum[0:cutoff]=0
    cepstrum=MaxMinNormalization(cepstrum,0,1)
    if showTestView:
        plt.subplot(122)
        plt.plot(np.arange(len(cepstrum)), cepstrum)
   
    length=len(cepstrum)
    peakind = signal.find_peaks_cwt(cepstrum, np.arange(1,20))
    peakind2=findpeaks(cepstrum, spacing=15, limit=0.05)
    if showTestView==1:
        print(peakind)
        print(peakind2)
    # 把 corlor 设置为空,通过edgecolors来控制颜色
    if showTestView==1:
        plt.scatter(peakind2, cepstrum[peakind2], color='', marker='o', edgecolors='r', s=100)
    
    peaks=[]
    pos=cutoff
    maxpos=np.argmax(cepstrum[pos:-1])+pos#最高峰位置
    #检测半峰
    simiPos=int(maxpos/2)
    rad=int(simiPos/2)
    simiMax=np.argmax(cepstrum[simiPos-rad:simiPos+rad])+simiPos-rad#半峰位置
    bias=abs(simiPos-simiMax)/rad#偏离度10%
    if bias<0.2:
        #半峰与最高峰之间的最小值
        simiMin=np.min(cepstrum[simiMax:maxpos])
        #与半峰最小值差值
        dist=cepstrum[simiMax]-simiMin
        #差值比例
        dist=dist/(cepstrum[maxpos]-simiMin)
        if(dist>0.66):
            #1 2
            #return Fs/2/simiMax//
            #四分检测
            
            fourPos1=int(simiMax/2)#四分之一峰
            p0=fourPos1
            Xi=np.array([2,4])
            Yi=np.array([simiMax,maxpos])
            para=leastsq(error,p0,args=(Xi,Yi)) #把error函数中除了p以外的参数打包到args中
            fourPos1=int(para[0])
            fourPos2=int(para[0]*3)
            rad=int(fourPos1/2)
            
            fourMax1=np.argmax(cepstrum[fourPos1-rad:fourPos1+rad])+fourPos1-rad#四分峰位置1
            bias=abs(fourPos1-fourMax1)/rad#偏离度10%
            if bias<0.2:
                #半峰与四分峰之间的最小值
                fouMin1=np.min(cepstrum[fourMax1:simiMax])
                #与半峰最小值差值
                dist=cepstrum[fourMax1]-fouMin1
                #差值比例
                dist=dist/(cepstrum[simiMax]-fouMin1)
                if(dist>0.66):
                    #寻找四分3峰
                    fourMax2=np.argmax(cepstrum[fourPos2-rad:fourPos2+rad])+fourPos2-rad#四分峰位置1
                    bias=abs(fourPos2-fourMax2)/rad#偏离度10%
                    if bias<0.2:
                        #添加四分峰
                        peaks.append([len(peaks)+1,fourMax1])
                        peaks.append([len(peaks)+1,simiMax])
                        peaks.append([len(peaks)+1,fourMax2])
            if len(peaks)<1:
                peaks.append([len(peaks)+1,simiMax])
    #不存在半峰才检测三分峰         
    if len(peaks)<1:
        thd1=0#第一个三分峰的位置
        thd2=0#第二个三分峰的位置
        #三分峰值检测
        thrPos=int(maxpos*2/3)
        rad=int((maxpos-simiPos)/2)
        thrMax=np.argmax(cepstrum[thrPos-rad:thrPos+rad])+thrPos-rad#三分峰位置
        bias=abs(thrPos-thrMax)/rad#偏离度10%
        if bias<0.2:
            #2/3峰与最大峰之间的最小数
            thrMin=np.min(cepstrum[thrMax:maxpos])
            #与最小值差值
            dist=cepstrum[thrMax]-thrMin
            #差值比例
            dist=dist/(cepstrum[maxpos]-thrMin)
            if(dist>0.66):
                #return Fs/2/simiMax
                #寻找1 如果寻找不到1 则取消2
                thd1=thrMax
                #三分峰2检测 (做回归)
                p0=maxpos/3
                Xi=np.array([2,3])
                Yi=np.array([thd1,maxpos])
                para=leastsq(error,p0,args=(Xi,Yi)) #把error函数中除了p以外的参数打包到args中
                thrPos2=int(para[0]*1)
                rad=int((thd1-thrPos2)/2)
                #print(rad)
                #print(thrPos2)
                thrMax2=np.argmax(cepstrum[thrPos2-rad:thrPos2+rad])+thrPos2-rad#三分峰位置
                bias=abs(thrPos2-thrMax2)/rad#偏离度10%
                #print(bias)
                if bias<0.2:
                    #与2/3峰之间的最小值
                    thrMin2=np.min(cepstrum[thrMax2:thrMax])
                    #与最小值差值
                    dist=cepstrum[thrMax]-thrMin2
                    #差值比例
                    dist=dist/(cepstrum[thrMax2]-thrMin2)
                    if(dist>0.66):
                        thd2=thrMax2
                    else:
                        thd1=0
                        thd2=0 
                else:
                    #1:
                    #return Fs/2/maxpos
                    thd1=0
                    thd2=0
        if thd1>0:
             peaks.append([len(peaks)+1,thd2])
             peaks.append([len(peaks)+1,thd1])
             #print(thd1)
             #print(thd2)
    peaks.append([len(peaks)+1,maxpos])
    #每做一次线性回归 找下一个峰,直至找出右侧所有峰位置
    getNextPeaks(peaks,cepstrum,0.1,0.25,0)#递归求右侧波峰
    lenPeaks=len(peaks)
    if showTestView:
        if lenPeaks>0:
            print(peaks)
    rs=[]    
    if lenPeaks>1:
        #线性拟合求基频,根据找到的所有二次fft峰求二次fft的基频,此基频求倒数然后乘以采样率就是原始信号的基频,对原始信号的高频部分分辨率不足
        #,但原始信号高频部分在第一次fft中有好的频率分辨率,因此后期可以弥补
        #harmonicIDs=np.arange(lenPeaks)+1#设置波峰ID
        p0=peaks[lenPeaks-1][1]/lenPeaks#初始化参数
        Xi=np.array(peaks)[:,0]
        Yi=np.array(peaks)[:,1]
        para=leastsq(error,p0,args=(Xi,Yi)) #把error函数中除了p以外的参数打包到args中
        peaksfindWidth=int(nfft/2/para[0]*0.6)
        peakindofFFT=findpeaks(dataClip, spacing=peaksfindWidth, limit=max(dataClip[int(30*nfft/Fs):-1])/10)
        if showTestView==1:
            plt.subplot(121)
            plt.scatter(peakindofFFT, dataClip[peakindofFFT], color='', marker='o', edgecolors='r', s=100)
            plt.show()
        rs= [Fs/2/para[0],Fs/2/peaks[0][1]]
    else:
        if lenPeaks==1:
            if showTestView==1:
                plt.show()
            rs= [0,0]
        else:
            plt.show()
            rs= [0,0]
    return rs
Exemple #5
0
def getPitchDeScan(dataClip, Fs, nfft, showTestView):
    pitch = 0
    dataClip[0:int(30 * nfft / Fs)] = 0
    dataClip = subpeakAmpLimiting(dataClip, int(30.0 / Fs * nfft), 0.1)  # 次峰限幅
    if showTestView:
        plt.subplot(231)
        plt.plot(np.arange(len(dataClip)), dataClip, label='amp-frq')
    lowCutoff = int(40 * 441000.0 / Fs)  # 最低截止频率对应的坐标
    highCutoff = int(1400 * 441000.0 / Fs)  # 最高截止频率对应的坐标
    peakSearchPixes = int(3 * 441000 / Fs)  # 寻峰间距
    peakSearchAmp = 0.1  # 寻峰高度
    # 线性内插重新采样
    processingX = np.arange(0, min(int(
        nfft / Fs * 4000), len(dataClip)))  # 最大采集到4000Hz,不包括最大值,此处为尚未重采样的原始频谱
    processingY = dataClip[processingX]  # 重采样的fft
    lenProcessingX = len(processingX)  # 待处理频谱长度
    finterp = interp1d(processingX, processingY, kind='linear')  # 线性内插配置
    x_pred = np.linspace(
        0, processingX[lenProcessingX - 1] * 1.0,
        int(processingX[lenProcessingX - 1] * 441000 / nfft) + 1)
    maxProcessingX = x_pred[len(x_pred) - 1]
    resampY = finterp(x_pred)
    lenResampY = len(resampY)
    # print(len(resampY))
    if showTestView == 1:
        plt.subplot(232)
        plt.plot(np.arange(len(resampY)), resampY, label='rs_Amp-frq')
    maxResampY = max(resampY[lowCutoff:-1]) / 2  # 待测频率内的最大值
    # 测试梳状变换
    # pixes=10
    num = highCutoff  # 栅栏变换后的长度
    combTrans = np.zeros(num)  # 存放栅栏变换的结果
    indexComb = np.arange(lowCutoff, highCutoff, 0.1)  # 栅栏变换索引
    for k in np.arange(1, highCutoff, 1):
        combTrans[k] = np.sum(
            [resampY[i] for i in np.arange(0, lenResampY - 1, k)])
    if showTestView == 1:
        plt.subplot(233)
        plt.plot(np.arange(len(combTrans)), combTrans, label='combTrans')
    deSamp = [combTrans[m]
              for m in np.arange(0, len(combTrans), 10)]  # 10倍数降采样
    deSamp[0] = 1000
    if showTestView == 1:
        plt.subplot(234)
        plt.plot(np.arange(len(deSamp)), deSamp, label='DsCombTrans')
    baseLine = getBaseLineFromScan(deSamp, num)  # 通过扫描线算法求基准曲线
    if showTestView == 1:
        plt.subplot(235)
        plt.plot(np.arange(len(baseLine)), baseLine, label='baseline')
    trueTrans = combTrans - baseLine
    trueTrans[0:lowCutoff] = 0
    if showTestView == 1:
        plt.subplot(236)
        plt.plot(np.arange(len(trueTrans)), trueTrans, label='trueTrans')
    if (sum(dataClip) < 1):
        return [0 / 10.0, resampY, trueTrans]
    pitch = max(trueTrans) / sum(dataClip)

    # 频率采样变换后寻峰
    combTransPeaks = findpeaks(trueTrans,
                               spacing=peakSearchPixes,
                               limit=max(trueTrans) * peakSearchAmp)
    peaks = trueTrans[combTransPeaks]  # 峰值大小
    if (len(peaks) == 0):
        return [0 / 10.0, resampY, trueTrans]
    maxindex = np.argmax(peaks)
    maxfrq = combTransPeaks[maxindex]  # 最高峰值位置

    # 寻找1hz以内的最大的峰
    combThr = 6 * 441000 / Fs  # 寻峰宽度
    decThr = 0.65  # 递减阈值
    preBaseFrq = maxfrq
    for n in range(2, 10, 1):
        newfrq = getNearPeaks(trueTrans, combTransPeaks, peaks, n * maxfrq,
                              combThr, preBaseFrq, decThr, showTestView)
        if (newfrq > 0):
            preBaseFrq = newfrq
        else:
            continue
    pitch = preBaseFrq
    if showTestView == 1:
        plt.scatter(combTransPeaks,
                    trueTrans[combTransPeaks],
                    color='',
                    marker='o',
                    edgecolors='r',
                    s=100)
        plt.show()
    return [pitch / 10.0, resampY, trueTrans]
Exemple #6
0
    def getpitch(self, dataclip, fs, nfft, showtestview):
        """
        音高估计
        :param dataclip:输入fft
        :param fs:采样率
        :param nfft:窗口大小
        :param showtestview:是否显示figure
        :return:频率,插值采样后的输入,梳状统计向量
        """
        dataclip[0:int(30 * nfft / fs)] = 0
        dataclip = BaseFrqDetector.subpeak_amplimiting(dataclip,
                                                       int(30.0 / fs * nfft),
                                                       0.1)  # 次峰限幅
        lowcutoff = int(32.5 * 441000.0 / fs)  # 最低截止频率对应的坐标
        highcutoff = int(1400 * 441000.0 / fs)  # 最高截止频率对应的坐标
        peaksearchpixes = int(3 * 441000 / fs)  # 寻峰间距
        peaksearchamp = 0.1  # 寻峰高度
        # 线性内插重新采样
        processingx = np.arange(
            0, min(int(nfft / fs * 4000),
                   len(dataclip)))  # 最大采集到4000Hz,不包括最大值,此处为尚未重采样的原始频谱
        processingy = dataclip[processingx]  # 重采样的fft
        lenprocessingx = len(processingx)  # 待处理频谱长度
        finterp = interp1d(processingx, processingy, kind='linear')  # 线性内插配置
        x_pred = np.linspace(
            0, processingx[lenprocessingx - 1] * 1.0,
            int(processingx[lenprocessingx - 1] * 441000 / nfft) + 1)
        resampy = finterp(x_pred)
        lenresampy = len(resampy)

        # pixes=10
        num = highcutoff  # 栅栏变换后的长度
        combtrans = np.zeros(num)  # 存放栅栏变换的结果

        # 梳状变换, 2019-03-10 16:54:45
        for k in np.arange(lowcutoff, highcutoff, 1):
            combtrans[k] = sum(resampy[::k])
        combtrans[0:lowcutoff] = max(combtrans)
        # 如果有去扫描参数,则去扫描
        if self.isdescan is True:
            # 用于降低采样
            desamp = [combtrans[m]
                      for m in np.arange(0, len(combtrans), 10)]  # 10倍数降采样
            desamp[0] = np.max(desamp)
            baseline = BaseFrqDetector.getbaselinefromscan(desamp,
                                                           num)  # 通过扫描线算法求基准曲线
            truetrans = combtrans - baseline
        else:
            truetrans = combtrans
        truetrans[0:lowcutoff] = 0

        if sum(dataclip) < 1:
            return [0 / 10.0, resampy, truetrans]
        # 频率采样变换后寻峰
        combtranspeaks = findpeaks(truetrans,
                                   spacing=peaksearchpixes,
                                   limit=max(truetrans) * peaksearchamp)
        peaks = truetrans[combtranspeaks]  # 峰值大小
        if len(peaks) == 0:
            return [0 / 10.0, resampy, truetrans]
        maxindex = np.argmax(peaks)
        maxfrq = combtranspeaks[maxindex]  # 最高峰值位置
        # 寻找1hz以内的最大的峰
        combthr = 6 * 441000 / fs  # 寻峰宽度
        decthr = 0.65  # 递减阈值
        prebasefrq = maxfrq
        for n in range(2, 10, 1):
            newfrq = BaseFrqDetector.getnearpeaks(truetrans, combtranspeaks,
                                                  peaks, n * maxfrq, combthr,
                                                  prebasefrq, decthr,
                                                  showtestview)
            if newfrq > 0:
                prebasefrq = newfrq
            else:
                continue
        pitch = prebasefrq
        return [pitch / 10.0, resampy, truetrans]