Pourquoi est-ce que j'obtiens ce bruit crépitant lors de la mise à zéro des hautes fréquences?

8

J'ai récemment commencé à jouer avec la transformée de Fourier (après avoir passé quelques semaines à apprendre les mathématiques derrière elle). J'ai décidé d'essayer de pirater ensemble un filtre passe-bas sur la morsure sonore suivante:

En particulier, j'ai pris la transformée de Fourier, mis à zéro la moitié la plus élevée des fréquences, puis pris la transformée de Fourier inverse. Voilà ce que j'ai

Pourquoi y a-t-il ce bruit de crépitement?

JeremyKun
la source
De plus, je dois mentionner que je ne sais pas pourquoi j'applique un filtre passe-bas à un clip audio. C'est purement expérimental. Cette opération a-t-elle même un sens pour un clip audio?
JeremyKun
vous devriez rendre ces échantillons téléchargeables
endolith

Réponses:

11

Deux problèmes potentiels:

  1. Le filtrage dans le domaine fréquentiel (à l'aide d'une FFT) nécessite un chevauchement-ajout, un chevauchement-sauvegarde ou un algorithme associé. Cela est dû à la différence entre la convolution linéaire et circulaire. Sinon, vous obtenez un alias de domaine temporel
  2. Une partie du bruit ressemble à un simple écrêtage. Le filtrage peut en fait augmenter l'amplitude du domaine temporel pour certains échantillons et s'il dépasse la plage disponible, il se coupe ou s'enroule.
Hilmar
la source
1
Cela ressemblait à un détourage / un emballage pour moi.
heltonbiker
Que puis-je faire pour arrêter l'écrêtage / habillage? Dois-je tout simplement pas avoir fait cette opération en premier lieu?
JeremyKun
C'est définitivement un écrêtage. J'ai réduit l'amplitude du signal d'entrée et les grésillements ont disparu.
JeremyKun
7

Tout d'abord une note, les transformées de Fourier ne sont pas idéales pour les filtres passe-bas / passe-haut. Les filtres Butterworth sont un bon endroit pour commencer et suivre les filtres Chebyshev / Elliptiques si vous devenez plus ambitieux.

Il semble que vous tentiez d'implémenter un filtre idéal. Il n'y a aucun moyen de mettre en œuvre ces filtres «mur de briques» où nous coupons toutes les fréquences au-dessus / en dessous d'une valeur donnée. Tous les filtres bien développés diminueront de 1 à 0 autour de notre fréquence de coupure.

Les filtres idéaux ne sont théoriques que possibles et si vous aviez une transformation de Fourier continue, votre méthode ci-dessus fonctionnerait.

Mais nous faisons des transformées de Fourier discrètes donc il y a plus à s'inquiéter. Comme je ne suis pas sûr de la méthode de votre implémentation, je suppose que vous faites du fenêtrage, car le simple fait de retirer les fréquences est un moyen sûr de crépiter dans un DFT fenêtré.

Lors du fenêtrage dans un DFT, on pourrait penser que les amplitudes de fréquence entre les fenêtres sont relativement continues. Par exemple, si la fréquence de 400 Hz a une amplitude de 0,5 dans la fenêtre actuelle, dans la fenêtre suivante, l'amplitude sera proche de 0,5. Ce n'est malheureusement pas vrai, donc si nous supprimions simplement la fréquence de 400 Hz de notre DFT, nous pourrions entendre des bruits forts ou des fissures entre les fenêtres.

Un petit exemple: le taux de coupure est de 600 Hz. La fenêtre 1 joue un sinus de 800 Hz. La fenêtre 2 se connecte «en continu» à la fenêtre 1 et joue à 400 Hz. Ensuite, nous entendrons un pop entre la fenêtre car la fenêtre 1 sera silencieuse et la fenêtre 2 s'ouvrira immédiatement.

Une autre chose à garder à l'esprit est que nous ne pouvons représenter qu'une quantité finie de fréquences avec un DFT. Si nous avons un fichier audio avec une onde sinusoïdale d'une fréquence comprise entre deux de nos fréquences discrètes dans notre DFT, alors nous le représentons en fait avec beaucoup de nos fréquences discrètes. Donc, même si un exemple de fichier audio peut contenir une onde sinusoïdale inférieure à notre fréquence de coupure, si sa fréquence se situe entre nos fréquences DFT, nous pourrions en couper une partie et la déformer avec la méthode ci-dessus, car des fréquences plus élevées sont nécessaires pour représenter l'audio fichier.

J'espère que cela pourra aider

Matt Tytel
la source
Ah, je retire mon commentaire de fenêtrage (c'est plus un problème DFT en temps réel). La réponse de Hilmar semble plus exacte.
Matt Tytel
4

Il est en effet possible de faire comme vous le suggérez mais non sans quelques effets secondaires. Disons que nous formons un signal de test simples(t)=slow(t)+shigh(t) où:

slow(t)=cos(2πf0t)+cos(2πf1t+π3)

shigh(t)=12cos(2πf2t+0.2)

où nous disons que les deux f0,f1 sont en dessous d'une fréquence de coupure passe-bas choisie fcut tel que f0<f1<fcut, et nous choisissons f2>fcut. Nous pouvons bien sûr choisir les amplitudes comme nous le souhaitons et je viens de choisir celles ci-dessus pour garder les choses simples. En ayant deux contributions de fréquence en dessous de la fréquence de coupure et une au-dessus, il est facile de suivre et de comparer les signaux.

Dans ce qui suit, je suppose que nous avons N échantillons prélevés avec la fréquence fs>2f2. En réalité, nous choisissonsfs2f2pour rendre le signal observé lisse. On suppose également que nous ne considérons qu'un seul groupe d'échantillons de données. Si vous devez gérer plusieurs délais, consultez le document de Fred Harris intitulé "Sur l'utilisation de Windows pour l'analyse harmonique avec la transformation de Fourier discrète" de Proc. IEEE en 1978.

J'ai combiné un petit programme Python pour illustrer certains des concepts - le code est assez horrible mais je viens de prendre du vieux code que j'avais pour des problèmes similaires. Bien qu'il n'y ait pratiquement aucun commentaire, il devrait être assez facile à suivre en raison des petits modules. Ce sont deux fonctions dft / idft ; deux fonctions fshiftn / fshiftp pour décaler en fréquence le signal dans le domaine DFT pour le filtrage; une fonction dftlpass pour effectuer le filtrage dans le domaine DFT; une fonction zpblpass pour effectuer le filtrage en utilisant un filtre Butterworth; une fonction bbdftsig pour former le signal de test et effectuer le filtrage; et enfin une petite fonction tramepour tracer les signaux. A la fin du script, les différents paramètres sont définis et les différentes figures sont faites.

"""
   Test of DFT versus scipy.signal.butter filtering with respect to
   signal reconstruction.

"""

# import ############################################################ import #
import matplotlib as mpl;   mpl.rcParams['backend'] = 'Agg'
import matplotlib.pyplot as mplpp
import matplotlib.mlab as mplml
import numpy as np
import scipy.signal as sps


# initialize #################################################### initialize #
try:
    mpl.rc('text', usetex=False)
    mpl.rc('font', family='serif')
    mpl.rc('font', serif='STIXGeneral')
    mpl.rc('font', size=8)
except AttributeError:
    None


# dft ################################################################## dft #
def dft(xt, fs, t0):
    N, d = len(xt), -2j*np.pi/len(xt)
    w = np.arange(N, dtype=np.float).reshape((N,1))
    c = np.exp(d*t0*fs*w)
    W = np.exp(d*np.dot(w,np.transpose(w)))
    xf = np.multiply(c,np.dot(W,xt)) / float(N)
    f = w*fs/float(N)
    return xf, f


# idft ################################################################ idft #
def idft( X, FS, T0 ):
    N, d = len(X), 2j*np.pi/len(X)
    w = np.arange(N, dtype=float).reshape((N,1))
    cc = np.exp(d*T0*FS*w)
    Wc = np.exp(d*np.dot(w, np.transpose(w)))
    Y = np.dot(Wc, np.multiply(cc, X))
    return Y



# fshiftn ########################################################## fshiftn #
def fshiftn( xf, f ):
    assert type(f) == np.ndarray, "f must be a np.ndarray"
    assert f.shape[1] == 1, "f must be a column array"
    assert xf.shape[1] == 1, "xf must be a column array"
    assert sum(f<0) == 0, "All frequency components must be 0 or positive"

    # Determine sampling rate, tolerance, and allocate output array
    fs, tol = len(f)*(np.abs(f[1,0]-f[0,0])), 1.E-2
    fshift = np.zeros((len(f),1), dtype=float)
    xfshift = np.zeros((len(f),1), dtype=complex)

    # Determine index where f > fs/2
    Nm = np.floor(len(f)/2.0)
    Np = np.floor((len(f)-1.0)/2.0)

    # Compute output frequency array such that -fs/2 <= f < fs/2 and the
    # corresponding Fourier coefficients
    fshift[:Nm,0] = f[Np+1:,0] - fs
    fshift[Nm,0] = f[0,0]
    fshift[Nm+1:,0] = f[1:Np+1,0]

    xfshift[:Nm,0] = xf[Np+1:,0]
    xfshift[Nm,0] = xf[0,0]
    xfshift[Nm+1:,0] = xf[1:Np+1,0]

    return xfshift, fshift


# fshiftp ########################################################## fshiftp #
def fshiftp(xf, f):
    assert type(f) == np.ndarray, "f must be a np.ndarray"
    assert f.shape[1] == 1, "f must be a column array"
    assert xf.shape[1] == 1, "xf must be a column array"
    assert sum(f<0) > 0, "Some input frequencies must be negative"

    # Determine sampling rate, tolerance, and allocate output array
    fs, tol = len(f)*(np.abs(f[1,0]-f[0,0])), 1.E-2
    fshift = np.zeros((len(f),1), dtype=float)
    xfshift = np.zeros((len(f),1), dtype=complex)

    # Determine index where f > fs/2
    #Nx = np.floor((len(f)+1+tol)/2)
    Nm = np.floor(len(f)/2.0)
    Np = np.floor((len(f)-1.0)/2.0)

    # Compute output frequency array such that -fs/2 <= f < fs/2 and the
    # corresponding Fourier coefficients
    fshift[Np+1:,0] = f[:Nm:,0] + fs
    fshift[0,0] = f[Nm,0]
    fshift[1:Np+1:,0] = f[Nm+1:,0]

    xfshift[Np+1:,0] = xf[:Nm:,0]
    xfshift[0,0] = xf[Nm,0]
    xfshift[1:Np+1:,0] = xf[Nm+1:,0]

    return xfshift, fshift


# dftlpass ######################################################## dftlpass #
def dftlpass(xt, fs, fcut):
    # Perform Discrete Fourier Transform
    xf, f = dft(xt, fs, 0.0)

    # Shift frequencies to -fs/2 <= f < fs/2 ... and coefficients
    xfshift, fshift = fshiftn(xf, f)

    # Perform filtration
    xfshift = xfshift * (np.abs(fshift) <= fcut)

    # Re-shift frequencies to 0 <= f < fs ... and coefficients
    xfrecon, frecon = fshiftp(xfshift, fshift)

    # Perform inverse Discrete Fourier Transform
    yt = idft(xfrecon, fs, 0.0)
    return yt.real


# zpblpass ######################################################## zpblpass #
def zpblpass(xn, fcal, fs, fcut):
    bz, az = sps.butter(5, fcut/(fs/2))

    # Gain calibration
    Ncal = np.max([np.int(20*fs/fcal), 30000])
    Nguard = np.int(0.1*Ncal)    
    t = np.arange(Ncal) / fs
    x0_cal = 1.0 * np.cos(2*np.pi*fcal*t)
    yi_cal = sps.filtfilt(bz, az, 2.0*x0_cal*np.cos(2*np.pi*fcal*t))
    k = 1.0/np.mean(yi_cal[Nguard:Ncal-Nguard])

    # Scaled output
    yn = k * sps.filtfilt(bz, az, xn)
    return yn


# bbdftsig ######################################################## bbdftsig #
def bbdftsig(f0, f1, f2, fcut, fs, N):
    t = np.arange(N).reshape((N,1)) / fs
    s0 = np.sin(2*np.pi*f0*t)
    s1 = np.sin(2*np.pi*f1*t + 0.2)
    s2 = 0.7 * np.sin(2*np.pi*f2*t + np.pi/3.0)
    slow = s0 + s1
    s = slow + s2

    sf = dftlpass(s, fs, fcut)
    sfdftv = sf.reshape((N))
    sv = s.reshape((N))
    slowv = slow.reshape((N))

    sv = s.reshape((N))
    sfzpbv = zpblpass(sv, f1, fs, fcut)
    #sfzpbv = sfzpb.reshape((N))
    return sv, slowv, sfdftv, sfzpbv


# plotsigs ######################################################## plotsigs #
def plotsigs(s, slow, sfdft, sfzpb, Nstart, Nstop, fname):
    n = np.arange(s.shape[0])

    # Plot results
    mplpp.figure(1, (5.0,2.25))
    mplpp.clf()
    mplpp.plot(n[Nstart:Nstop], s[Nstart:Nstop], 'm-',
               n[Nstart:Nstop:4], s[Nstart:Nstop:4], 'mx',
               n[Nstart:Nstop], slow[Nstart:Nstop], 'g-',
               n[Nstart:Nstop:10], slow[Nstart:Nstop:10], 'gx',
               n[Nstart:Nstop], sfdft[Nstart:Nstop], 'r-',
               n[Nstart:Nstop:15], sfdft[Nstart:Nstop:15], 'rx',
               n[Nstart:Nstop], sfzpb[Nstart:Nstop], 'b-',
               linewidth=1.5)
    mplpp.legend([r'$s$', r'$s$', r'$s_{\rm low}$', r'$s_{\rm low}$',
                  r'DFT', r'DFT', r'ZPB'], loc='upper right')
    mplpp.ylabel(r'Signal')
    mplpp.xlabel(r'$n$')
    #mplpp.axis([-10.0, 10.0, 1.0E-2, 1.0E2])
    mplpp.grid(True)
    mplpp.savefig(fname, dpi=600,
                bbox_inches='tight', pad_inches=0.05)
    mplpp.close()


# __main__ ######################################################## __main__ #
if __name__ == '__main__':
    # Initialize
    f0 = 3.0
    f1 = 11.5
    f2 = 20.0
    fcut = 15.0
    fs = 1000.0
    N = 5000

    s, slow, sfdft, sfzpb = bbdftsig(f0, f1, f2, fcut, fs, N)
    n = np.arange(s.shape[0])

    # Fig. 1: full data set
    Nstart = 0
    Nstop = N
    fname = 'full.pdf'
    plotsigs(s, slow, sfdft, sfzpb, Nstart, Nstop, fname)

    # Fig. 2: beginning
    Nstart = 0
    Nstop = 150
    fname = 'beginning.pdf'
    plotsigs(s, slow, sfdft, sfzpb, Nstart, Nstop, fname)

    # Fig. 3: middle
    Nstart = np.floor(N/2.0) - 75
    Nstop = Nstart + 100
    fname = 'middle.pdf'
    plotsigs(s, slow, sfdft, sfzpb, Nstart, Nstop, fname)

    # Fig. 4: ending
    Nstart = N - 150
    Nstop = N
    fname = 'ending.pdf'
    plotsigs(s, slow, sfdft, sfzpb, Nstart, Nstop, fname)

Choisir N=5000 et fs=1000 nous donne une résolution en fréquence de fs/N=0.2Hz. Si nous choisissonsf0,f1,f2selon cela, nous pouvons obtenir un accord parfait en choisissant les fréquences comme indiqué ci-dessus. Si nous choisissons d'abord les fréquences qui sont sur la grille commef0=3, f1=11, f2=21 et nous avons fcut=15nous obtenons la première série de résultats. Les première, moyenne et dernière parties des signaux concernés sont présentées ci-dessous:

Début des signaux - sur le réseau Milieu des signaux - sur le réseau Fin des signaux - sur le réseau

Comme le montre la figure, nous avons l'entrée combinée scomme signal magenta; le signal vert comme nous ne pouvons le voir que sur les marquages ​​«x» estslow(le signal d'entrée brut lorsque nous incluons simplement le signal d'entrée en dessous de la fréquence de coupure); le signal rouge est celui que nous obtenons lors de l'utilisation du filtrage DFT; et le signal bleu est celui que nous obtenons du filtre Butterworth. Comme vu ci-dessus, nous obtenons un accord parfait entreslow et le signal filtré DFT - mais le filtre Butterworth a un certain impact sur le signal dans la bande (en particulier le composant à f1. Comme c'est assez typique pour ce type de traitement, nous avons quelques différences au début et à la fin de la séquence en raison des effets de bord et d'un accord assez bon entre les deux types de filtrage dans la section centrale.

Si nous changeons la fréquence f1 à f1=11.5 qui n'est pas sur la grille de fréquence (et en plus elle est assez proche de la fréquence de coupure), nous voyons des résultats différents comme indiqué ci-dessous.

Début des signaux - hors réseau Milieu des signaux - hors réseau Fin des signaux - hors réseau

Nous voyons maintenant des différences substantielles entre les signaux vert, bleu et rouge qui, dans la situation idéale, devraient être identiques. Au milieu du signal, ils sont tous assez bien d'accord - la DFT et la référenceslow d'accord mieux cependant.

Ainsi, en conclusion, il est possible d'utiliser le filtrage direct en forçant les coefficients de Fourier à zéro, ce qui est également parfois fait en détection compressive pour réduire le support d'un signal pour forcer la rareté sur un signal. Cependant, cela a des conséquences comme une augmentation des erreurs, en particulier aux bords du signal. En outre, ce qui précède est un meilleur cas où le signal entier est traité comme une séquence. Si le signal doit être divisé en intervalles de temps, cela devient compliqué car nous devons alors envisager un fenêtrage ou une autre technique pour assurer la continuité du signal entre les images. Donc, mon conseil est similaire à certains des autres articles en recommandant d'utiliser normalement un filtre Butterworth / Elliptic / .. ou autre.

Lars1
la source
0

La remise à zéro des cases dans une FFT peut en fait augmenter l'amplitude d'autres fréquences proches mais non centrées sur la case zero-ed ou ses cases adjacentes. Cette augmentation peut provoquer un écrêtage.

De plus, si vous effectuez la FFT en utilisant des blocs non-zéros (et non superposés) (par opposition à la chanson entière dans une grande FFT), toutes les modifications de données FFT se dérouleront de l'arrière vers l'avant de la séquence de domaine temporel dans chaque bloc, ajoutant ainsi d'autres discontinuités étranges aux mauvais endroits.

hotpaw2
la source
0

Voici un filtre passe-bande FFT à mise à zéro rapide et sale, avec le code FFT également.

void FFT(int n, int inverse, double *gRe, double *gIm, double *GRe, double *GIm)
{

    int m = 0;
    int p = 1;
    int j = 0;
    int i1=0;
    int k=0;
    double ca=0;
    double sa=0;
    int l1,l2,l3;
    double u1,u2;
    double t1 = 0;
    double t2 = 0;
    int i2=0;
    double z;
    /* Calculate m=log_2(n) */
    while(p < n)
    {
        p *= 2;
        m++;
    }
    /* Bit reversal */
    GRe[n - 1] = gRe[n - 1];
    GIm[n - 1] = gIm[n - 1];
    for(i1 = 0; i1 < n - 1; i1++)
    {
        GRe[i1] = gRe[j];
        GIm[i1] = gIm[j];
        k = n / 2;
        while(k <= j)
        {
            j -= k;
            k /= 2;
        }
        j += k;
    }
    /* Calculate the FFT */
    ca = -1.0;
    sa = 0.0;
    l1 = 1;
    l2 = 1;
    l3=0;
    for(l3 = 0; l3 < m; l3++)
    {
        l1 = l2;
        l2 *= 2;
        u1 = 1.0;
        u2 = 0.0;       
    for(j = 0; j < l1; j++)
        {
            i2=j;
            for(i2 = j; i2 < n; i2 += l2)
            {
                i1 = i2 + l1;
                t1 = u1 * GRe[i1] - u2 * GIm[i1];
                t2 = u1 * GIm[i1] + u2 * GRe[i1];
                GRe[i1] = GRe[i2] - t1;
                GIm[i1] = GIm[i2] - t2;
                GRe[i2] += t1;
                GIm[i2] += t2;
            }
            z =  u1 * ca - u2 * sa;
            u2 = u1 * sa + u2 * ca;
            u1 = z;
        }
        sa = sqrt((1.0 - ca) / 2.0);
        if(!inverse) sa =- sa;
        ca = sqrt((1.0 + ca) / 2.0);

    }
    /* Divide through n if it isn't the IDFT */
    if(!inverse)
    {
        int i3=0;
        for(i3 = 0; i3 < n; i3++)
        {
            GRe[i3] /= n;
            GIm[i3] /= n;
        }
    }
}


void mainfftBandPass(double *insamples, double *outsamples, unsigned long fftsize, long lowfreq, long highfreq, long srate)
{
    static double *inbuf=NULL;
    static double *realn=NULL;
    static double *imags=NULL;
    static double *spectr=NULL;
    static double *zer0=NULL;
    static double *olds=NULL;
    static double *infader=NULL;
    static double *outfader=NULL;
    int notched=(highfreq<lowfreq) ? 1 : 0;
    long incounter=0;
    /* treble is the highest baseband frequency */
    /* bass the the lowest baseband frequency */
    /* this function is called twice per FFT block */
    long midcounter=0;
    long outcounter=0;
    long bass=lowfreq*(fftsize/(double)srate);
    long treble=(highfreq)*(fftsize/(double)srate);
    static long halffft=2;
    static long old_fftsize=0;
    static short first=1;
    if(first==1 || fftsize!=old_fftsize)
    {
        if(inbuf)
             free(inbuf);
        if(realn)
            free(realn);
        if(imags)
            free(imags);
        if(spectr)
            free(spectr);
        if(zer0)
            free(zer0);
        if(olds)
            free(olds);
        if(infader)
            free(infader);
        if(outfader)
            free(outfader);
        infader=(double*)malloc(fftsize*sizeof(double));
        outfader=(double*)malloc(fftsize*sizeof(double));
        inbuf=(double*)malloc(fftsize*sizeof(double));
        realn=(double*)malloc(fftsize*sizeof(double));
        imags=(double*)malloc(fftsize*sizeof(double));
        spectr=(double*)malloc(fftsize*sizeof(double));
        zer0=(double*)malloc(fftsize*sizeof(double));
        olds=(double*)malloc(fftsize*sizeof(double));
        if((!inbuf) || (!realn) ||(!imags) ||(!spectr)||(!zer0)||(!ol   ds))
        {
            printf("Not enough memory for FFT!\n");
                    exit(1);
        }
        halffft=fftsize/2;
        long infade=0;
        long outfade=halffft;
        for(infade=0;infade<halffft;infade++)
        {
            outfade--;
            outfader[infade]=(0.5 * cos((infade) *  M_PI/(double)(halffft))+0.5);
            infader[outfade]=outfader[infade];
        }
        first=0;
    }
    memset(realn,0,sizeof(double)*fftsize);
    for(incounter=0;incounter<halffft;incounter++)
    {
        inbuf[incounter]=inbuf[incounter+halffft];
    }
    for(incounter=0;incounter<halffft;incounter++)
    {
        inbuf[incounter+halffft]=insamples[incounter];
    }
    for(incounter=0;incounter<fftsize;incounter++)
    {
        realn[incounter]=inbuf[incounter];
    }   
    memset(imags,0,sizeof(double)*fftsize);
    FFT(fftsize, 0, realn,imags, spectr,zer0);
    memset(realn,0,sizeof(double)*fftsize);
    memset(imags,0,sizeof(double)*fftsize);
    if(notched==0)
    {
        for(midcounter=bass;midcounter<treble;midcounter++)
        {
            realn[midcounter]=spectr[midcounter] * 2.0;
            imags[midcounter]= zer0[midcounter] * 2.0;
        }
        if(bass==0)
            realn[0]=spectr[0];

    }
    else if(notched==1)
    {
        for(midcounter=0;midcounter<halffft;midcounter++)
        {
            if((midcounter<treble) ||(midcounter>bass))
            {
                realn[midcounter]=spectr[midcounter] * 2.0;
                imags[midcounter]= zer0[midcounter] * 2.0;
            }
        }
        if(bass==0)
        {
            realn[0]=0;
        }
        else
        {
            realn[0]=spectr[0];
        }
    }
    FFT(fftsize, 1, realn, imags,spectr,zer0);
    for(outcounter=0;outcounter<halffft;outcounter++)
    {
        outsamples[outcounter]=(((spectr[outcounter] )*infader[outcounter])+(olds[outcounter+halffft]*outfader[outcounter])) ;
    }
    for(outcounter=0;outcounter<fftsize;outcounter++)
    {
        olds[outcounter]=spectr[outcounter];
    }
    memset(spectr,0,fftsize*sizeof(double));
    memset(zer0,0,fftsize*sizeof(double));
    old_fftsize=fftsize;
}

signed short mainbandpass(signed short input, double lowcut, double highcut,long rate,long fftsize)
{
    double retvalue=0;
    static double *insamp=NULL;
    static double *outsamp=NULL;
    static int first=1;
    static int q=0;
    if(first==1)
    {
            insamp=(double*)malloc(fftsize * sizeof(double));
            outsamp=(double*)malloc(fftsize * sizeof(double));
            if(insamp==NULL || outsamp==NULL)
            {
                   printf("Not enough memory for FFT buffers.\n");
                   exit(1);
            }
        memset(insamp,0,fftsize * sizeof(double));
        memset(outsamp,0,fftsize * sizeof(double));
        first=0;
    }

    insamp[q]=input;
    retvalue=outsamp[q];
    if(retvalue> 32767)
        retvalue=32767;
    if(retvalue <-32768)
        retvalue=-32768;
    q++;
    if(q>(fftsize/2)-1)
    {
        mainfftBandPass(insamp,outsamp, fftsize, lowcut,highcut,rate);
        q=0;
    }
    return (signed short)retvalue;
}

pour chaque échantillon de l'audio d'entrée, appelez passe-bande principal avec l'échantillon d'entrée et la plage de fréquences que vous souhaitez conserver en lowcut et highcut. Si le raccourci est supérieur au raccourci, le résultat sera un filtre de rejet de bande. Il y a une convolution circulaire, mais il n'y aura pas d'émissions hors bande, ce qui est bon pour les modems.

Brent Fisher
la source