Mengapa Saya Mendapatkan Suara Berderak tentang Mengabaikan Frekuensi Tinggi?

8

Saya baru-baru ini mulai bermain dengan transformasi Fourier (setelah menghabiskan beberapa minggu belajar tentang matematika di baliknya). Saya memutuskan untuk mencoba meretas filter low-pass pada gigitan suara berikut:

Secara khusus, saya mengambil transformasi Fourier, memusatkan 1/2 dari frekuensi tertinggi, dan kemudian mengambil transformasi Fourier terbalik. Ini yang saya dapat

Mengapa ada suara berderak itu?

JeremyKun
sumber
Juga, saya harus menyebutkan bahwa saya tidak tahu mengapa saya menerapkan filter low-pass ke klip suara. Ini murni eksperimental. Apakah operasi itu bahkan masuk akal untuk klip suara?
JeremyKun
Anda harus membuat sampel tersebut dapat diunduh
endolith

Jawaban:

11

Dua potensi masalah:

  1. Melakukan pemfilteran dalam domain frekuensi (menggunakan FFT) membutuhkan tumpang tindih-tambahkan, tumpang tindih-simpan, atau algoritma terkait. Ini disebabkan oleh perbedaan antara konvolusi linier dan sirkular. Kalau tidak, Anda mendapatkan alias domain-waktu
  2. Beberapa suara terdengar seperti kliping sederhana. Pemfilteran sebenarnya dapat meningkatkan amplitudo domain waktu untuk beberapa sampel dan jika itu melebihi kisaran yang tersedia, maka klip atau membungkusnya.
Hilmar
sumber
1
Terdengar seperti guntingan / pembungkus untuk saya.
heltonbiker
Apa yang bisa saya lakukan untuk menghentikan kliping / pembungkus? Haruskah saya tidak melakukan operasi ini sejak awal?
JeremyKun
Ini jelas kliping. Saya mengurangi amplitudo pada sinyal input dan suara berderak hilang.
JeremyKun
7

Pertama, sebagai catatan, transformasi fourier tidak ideal untuk filter low / high pass. Filter Butterworth adalah tempat yang baik untuk memulai dan mengikuti filter Chebyshev / Elliptical jika Anda menjadi lebih ambisius.

Sepertinya Anda mencoba menerapkan filter yang ideal. Tidak ada cara kita dapat menerapkan filter 'dinding bata' ini di mana kita memotong semua frekuensi di atas / di bawah nilai yang diberikan. Semua filter yang dikembangkan dengan baik akan meruncing dari 1 ke 0 di sekitar frekuensi cut-off kami.

Filter ideal hanya mungkin teoretis dan jika Anda memiliki Continuous Fourier Transform, metode Anda di atas akan berfungsi.

Tapi kami sedang melakukan Transformasi Fourier Diskrit sehingga ada lebih banyak yang perlu dikhawatirkan. Karena saya tidak yakin metode implementasi Anda, saya akan menebak bahwa Anda melakukan windowing karena hanya mengeluarkan frekuensi adalah cara pasti untuk mendapatkan cracking di DFT windowed.

Ketika windowing dalam DFT, orang mungkin berpikir bahwa amplitudo frekuensi antara windows relatif kontinu. misalnya jika frekuensi 400Hz memiliki amplitudo 0,5 di jendela saat ini yang di jendela berikutnya amplitudo akan mendekati 0,5. Sayangnya ini tidak benar, jadi jika kita hanya menghapus frekuensi 400Hz dari DFT kita, kita mungkin mendengar suara keras atau celah di antara windows.

Contoh kecil: Cut off rate 600Hz Window 1 memainkan sinus 800Hz Window 2 menghubungkan 'terus menerus' dengan window 1 dan memainkan 400Hz. Kemudian kita akan mendengar bunyi pop di antara jendela karena jendela 1 akan diam dan jendela 2 akan segera hidup.

Hal lain yang perlu diingat adalah bahwa kita hanya dapat mewakili jumlah frekuensi yang terbatas dengan DFT. Jika kita memiliki file audio dengan gelombang sinus frekuensi antara dua frekuensi diskrit kita di DFT kita, maka kita benar-benar merepresentasikannya dengan banyak frekuensi diskrit kita. Jadi meskipun contoh file audio mungkin mengandung gelombang sinus yang lebih rendah dari cutoff kami, jika frekuensinya di antara frekuensi DFT kami daripada kami mungkin memotong sebagian dan mengeluarkannya dengan metode di atas, karena frekuensi yang lebih tinggi diperlukan untuk mewakili audio mengajukan.

Semoga itu bisa membantu

Matt Tytel
sumber
Ah, saya menarik komentar windowing saya (Ini lebih merupakan masalah DFT real-time). Jawaban Hilmar tampaknya lebih akurat.
Matt Tytel
4

Memang mungkin untuk melakukan seperti yang Anda sarankan tetapi tidak tanpa beberapa efek samping. Katakanlah kita membentuk sinyal uji sederhana mana:s(t)=slow(t)+shigh(t)

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

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

di mana kami mengatakan bahwa kedua berada di bawah frekuensi cut-off lowpass yang dipilih sedemikian rupa sehingga , dan kami memilih . Kita tentu saja dapat memilih amplitudo seperti yang kita inginkan dan saya baru saja memilih yang di atas untuk menjaga hal-hal sederhana. Dengan memiliki dua kontribusi frekuensi di bawah frekuensi cut-off dan satu di atas membuatnya mudah untuk mengikuti dan membandingkan sinyal.f0,f1fcutf0<f1<fcutf2>fcut

Berikut ini saya berasumsi bahwa kami memiliki sampel diambil dengan frekuensi . Pada kenyataannya, kami memilih untuk membuat sinyal yang diamati menjadi halus. Juga diasumsikan bahwa kami hanya mempertimbangkan satu kumpulan sampel data. Jika Anda perlu menangani beberapa kerangka waktu, periksa kertas karya Fred Harris bernama "Pada Penggunaan Windows untuk Analisis Harmonik dengan Transformasi Fourier Diskrit" dari Proc. IEEE pada tahun 1978.Nfs>2f2fs2f2

Saya telah menggabungkan program Python kecil untuk menggambarkan beberapa konsep - kodenya cukup buruk tetapi saya hanya mengambil beberapa kode lama yang saya miliki untuk masalah yang sama. Meskipun hampir tidak ada komentar, itu harus cukup mudah diikuti karena modul kecil. Ada dua fungsi dft / idft ; dua fungsi fshiftn / fshiftp untuk mengubah frekuensi sinyal i DFT domain untuk penyaringan; sebuah fungsi dftlpass untuk melakukan pemfilteran dalam domain DFT; fungsi zpblpass untuk melakukan penyaringan dengan menggunakan filter Butterworth; fungsi bbdftsig untuk membentuk sinyal uji dan melakukan penyaringan; dan akhirnya sebuah fungsi plot keciluntuk merencanakan sinyal. Di akhir skrip, parameter yang berbeda diatur dan angka yang berbeda dibuat.

"""
   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)

Memilih dan memberi kita resolusi frekuensi Hz. Jika kita memilih sesuai dengan ini kita bisa mendapatkan persetujuan sempurna dengan memilih frekuensi seperti yang ditunjukkan di atas. Jika kita pertama-tama memilih frekuensi yang ada di grid sebagai , , dan kita memiliki kita mendapatkan set hasil pertama. Bagian pertama, tengah dan terakhir dari sinyal yang relevan ditunjukkan di bawah ini:N=5000fs=1000fs/N=0.2f0,f1,f2f0=3f1=11f2=21fcut=15

Awal sinyal - on-grid Tengah sinyal - on-grid Akhir dari sinyal - di-grid

Seperti yang terlihat dari gambar, kita memiliki input gabungan sebagai sinyal magenta; sinyal hijau seperti yang hanya bisa kita lihat dari tanda 'x' adalah (sinyal input mentah ketika kita hanya memasukkan sinyal input di bawah frekuensi cut-off); sinyal merah adalah sinyal yang kami dapatkan saat menggunakan filter DFT; dan sinyal biru adalah yang kita dapatkan dari filter Butterworth. Seperti yang terlihat di atas, kami memperoleh persetujuan sempurna antara dan sinyal DFT yang difilter - tetapi filter Butterworth memiliki beberapa dampak pada sinyal in-band (khususnya komponen disslowslowf1. Seperti yang cukup tipikal untuk jenis pengolahan ini, kami memiliki beberapa perbedaan di awal dan akhir urutan karena efek tepi dan kesepakatan yang cukup baik antara kedua jenis penyaringan di bagian tengah.

Jika kita mengubah frekuensi menjadi yang tidak ada di kisi frekuensi (dan lebih jauh itu cukup dekat dengan frekuensi cut-off), kita melihat beberapa hasil yang berbeda seperti yang ditunjukkan di bawah ini.f1f1=11.5

Awal sinyal - off-grid Tengah sinyal - off-grid Akhir dari sinyal - di luar jaringan

Sekarang kita melihat perbedaan besar antara sinyal hijau, biru dan merah yang dalam situasi ideal harus identik. Di tengah-tengah sinyal mereka semua setuju dengan cukup baik - DFT dan referensi setuju dengan yang terbaik.slow

Jadi kesimpulannya adalah mungkin untuk menggunakan penyaringan langsung dengan memaksa koefisien Fourier ke nol yang juga kadang-kadang dilakukan dalam penginderaan tekan untuk mengurangi dukungan sinyal untuk memaksa sparsity pada sinyal. Namun, ada konsekuensi dari ini sebagai peningkatan kesalahan khususnya di tepi sinyal. Selanjutnya, di atas adalah kasus terbaik di mana seluruh sinyal diperlakukan sebagai satu urutan. Jika sinyal harus dipecah dalam kerangka waktu maka akan menjadi rumit karena kita perlu mempertimbangkan beberapa teknik windowing atau lainnya untuk memastikan kontinuitas sinyal di antara frame. Jadi saran saya mirip dengan beberapa posting lain dalam merekomendasikan untuk menggunakan Butterworth / Elliptic / .. atau filter apa pun secara normal.

Lars1
sumber
0

Mem-nolkan nampan dalam FFT sebenarnya dapat meningkatkan amplitudo frekuensi lain yang dekat tetapi tidak terpusat pada nampan ed-nol atau nampan yang berdekatan. Peningkatan ini dapat menyebabkan kliping.

Selain itu, jika Anda melakukan FFT menggunakan blok yang tidak nol-empuk (dan tidak tumpang tindih) (yang bertentangan dengan seluruh lagu dalam satu FFT besar), setiap modifikasi data FFT akan membungkus dari belakang ke depan. urutan domain waktu di setiap blok, sehingga menambah diskontinuitas aneh lainnya di tempat yang salah.

hotpaw2
sumber
0

Berikut adalah filter bandpass FFT bin-zeroing cepat dan kotor, dengan kode FFT juga.

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;
}

untuk setiap sampel audio input, panggil mainbandpass dengan sampel input dan rentang frekuensi yang ingin Anda simpan dalam potongan rendah dan potongan tinggi. Jika pintasan lebih besar dari pintasan, hasilnya adalah filter band-reject. Ada konvolusi melingkar yang terjadi, tetapi tidak akan ada emisi pita yang bagus untuk modem.

Brent Fisher
sumber