Skip to content
Snippets Groups Projects
freqwave.c 15.28 KiB
#include <genfft.h>
#include <stdlib.h>
#include <string.h>
#include "par.h"

#define NINT(x) ((int)((x)>0.0?(x)+0.5:(x)-0.5))

#ifndef COMPLEX
typedef struct _complexStruct { /* complex number */
    float r,i;
} complex;
#endif/* complex */

/**
* compute wavelets in frequency domain, used in makewave
*
*   AUTHOR:
*           Jan Thorbecke (janth@xs4all.nl)
*           The Netherlands 
**/


void verr(char *fmt, ...);
void vwarn(char *fmt, ...);
void vmess(char *fmt, ...);
float gauss2time(float t, float f);
float gauss1time(float t, float f);
float gauss0time(float t, float f);
float gauss2freq(float f, float freq);
float gauss1freq(float f, float freq);
float gauss0freq(float f, float freq);
void hilbertTrans(float *data, int nsam);

void freqwave(float *wave, int nt, float dt, float fp, float fmin, float flef, float frig, float fmax, float t0, float db, int shift, int cm, int cn, char *w, float scale, int scfft, int inverse, float eps, float alpha, int verbose)
{
    int        it, iof, nfreq, nf, i, j, sign, optn, stored;
    int        ifmin1, ifmin2, ifmax1, ifmax2;
    float      df, fact, alfa, f, max, freq, att, ampl, phase;
    float      tt, dum;
    float    *rwave, *amplitude;
    complex    *cwave, tmp, *mpwave;

    optn    = optncr(nt);
    nfreq    = 1+(optn/2);
    df        = 1.0/(dt*optn);
    iof     = MAX(NINT(fmax/df), NINT(fp/df));
    att        = pow(10.0, db/20.0);

    if (iof > nfreq) verr("characterizing frequency aliased");

    cwave     = (complex *)malloc(nfreq*sizeof(complex));
    rwave     = (float *)malloc((optn+2)*sizeof(float));

    stored = 0;
    
    if (strstr(w, "g0") != NULL) {
        i = NINT(fmax/df);
        for (iof = i; iof > 0; iof--) {
            f = iof*df;
            if((gauss0freq(fmax, f) < att)&&(stored != 1)) {
                freq = f;
                stored = 1;
            }
        }
        if (stored == 0) verr("No valid wavelet found.");
        stored = 0;
        if (shift == 1) {
            for (i = 0; i < optn; i++) {
                if ((fabs(gauss0time((float)i*dt,freq))<1e-3)&&(stored != 1)) {
                    t0 = (float)i*dt;
                    stored = 1;
                }
            }
        }
        for (iof = 0; iof < nfreq; iof++) {
            f = iof*df;
            fact = f*f/(freq*freq);
            fact = exp(-fact);
            cwave[iof].r = fact*cos(2.0*M_PI*f*t0);
            cwave[iof].i = -fact*sin(2.0*M_PI*f*t0);
        }
        if (verbose >= 1) {
            vmess("Gaussian wavelet");
            vmess("----------------");
            vmess("Number of time samples .. = %d", nt);
            vmess("time step ............... = %f (s)", dt);
            vmess("maximum frequency at  ... = %f (Hz)",fmax);
            vmess("with attenutation ....... = %f", att);
            vmess("time shift .............. = %f (s)", t0);
        }
    }
    else if (strstr(w, "g1") != NULL) {
        if (fp < 0.0) {
            i = NINT(fmax/df);
            for (iof = i; iof > 0; iof--) {
                f = iof*df;
                if((gauss1freq(fmax, f) < att)&&(stored != 1)) {
                    freq = f;
                    stored = 1;
                }
            }
            if (stored == 0) verr("No valid wavelet found.");
        }
        else freq = fp;
        alfa = sqrt(2.0)*freq;
        stored = 0;

        if (shift == 1) {
            for (i = 1; i < optn; i++) {
                tt=(float)i*dt;
                dum = fabs(gauss1time(tt,freq))+fabs(gauss1time((tt+dt),freq));
                if ((dum<1e-4)&&(stored != 1)) {
                    t0 = (float)i*dt;
                    stored = 1;
                }
            }
        }

        for (iof = 0; iof < nfreq; iof++) {
            f = iof*df;
            fact = f*f/(alfa*alfa);
            fact = f*exp(-fact)/alfa;
            cwave[iof].r = fact*sin(2.0*M_PI*f*t0);
            cwave[iof].i = fact*cos(2.0*M_PI*f*t0);
        }
        if (verbose >= 1) {
            vmess("Derivative of Gaussian wavelet");
            vmess("------------------------------");
            vmess("Number of time samples .. = %d",nt);
            vmess("time step ............... = %f (s)",dt);
            if (fp < 0) {
                vmess("maximum frequency at  ... = %f (Hz)",fmax);
                vmess("with attenutation ....... = %f", att);
            }
            vmess("frequency peak at ....... = %f Hz", freq);
            vmess("time shift .............. = %f (s)", t0);
        }
    }
    else if (strstr(w, "cs") != NULL) {
        freq = acos((float)(cm-cn)/(float)(cm+cn))/(2.0*M_PI*dt);
        fact = 1.0/(cos(freq*2.0*M_PI*dt)+sin(freq*2.0*M_PI*dt));
        if (shift == 1) t0 = (cn+cm)*dt;

        for (iof = 0; iof < nfreq; iof++) {
            f = 2.0*M_PI*iof/(float)nt;
            ampl = pow((1.0-cos(f)), cn/2.0)*pow((1.0+cos(f)), cm/2.0);
            phase = atan((fact*sin(f))/(1.0+fact*cos(f)));
            cwave[iof].r = ampl*cos(phase-f*nt*t0);
            cwave[iof].i = ampl*sin(phase-f*nt*t0);
        }
        if (verbose >= 1) {
            vmess("Neidell Type of wavelet");
            vmess("-----------------------");
            vmess("Number of time samples .. = %d", nt);
            vmess("time step ............... = %f (s)", dt);
            vmess("frequency peak at ....... = %f Hz", freq);
            vmess("time shift .............. = %f (s)", t0);
        }
    }
    else if (strstr(w, "fw") != NULL) {
        ifmin1 = (int) (fmin/df);
        ifmin2 = (int) (flef/df);
        ifmax2 = (int) (frig/df);
        ifmax1 = (int) (fmax/df);
        for (j = 0; j < ifmin1; j++) {
            cwave[j].r = 0.0;
            cwave[j].i = 0.0;
        }
        for (j = ifmin1; j < ifmin2; j++) {
            cwave[j].r  = (cos(M_PI*(j-ifmin2)/(ifmin1-ifmin2))+1.0)/2.0;
            cwave[j].i = 0.0;
        }
        for (j = ifmin2; j < ifmax2; j++) {
            cwave[j].r = 1.0;
            cwave[j].i = 0.0;
        }
        for (j = ifmax2; j < ifmax1; j++) {
            cwave[j].r  =(cos(M_PI*(j-ifmax2)/(ifmax1-ifmax2))+1.0)/2.0;
            cwave[j].i = 0.0;
        }
        for (j = ifmax1; j < nfreq; j++) {
            cwave[j].r = 0.0;
            cwave[j].i = 0.0;
        }
        if (shift == 1) {
            sign = 1;
            cr1fft(cwave, rwave, optn, sign);
            max = rwave[0]*rwave[0];
            for (i = 1; i < optn; i++) {
                if (rwave[i] < 0.0) { it=i; break;}
            }
            it = it;
            dum = 0.0;
            for (j = 0; j < it; j++) 
                dum += fabs(rwave[j]);
            max = dum;
            for (i = 1; i < optn/2; i++) {
                dum = dum - fabs(rwave[i-1]) + fabs(rwave[i+it-1]);
                if ((dum)>(0.03*max*att/it)) {
                    t0 = (float)i*dt;
                }
            }
        }
        for (iof = 0; iof < nfreq; iof++) {
            f = iof*df;
            tmp.r = cwave[iof].r*cos(2.0*M_PI*f*t0);
            tmp.i = -cwave[iof].r*sin(2.0*M_PI*f*t0);
            cwave[iof].r = tmp.r;
            cwave[iof].i = tmp.i;
/* older version has multiplication with dt changed in april 2014
            cwave[iof].r = dt*tmp.r;
            cwave[iof].i = dt*tmp.i; */
        }

        if (verbose >= 1) {
            vmess("Flat spectrum wavelet");
            vmess("---------------------");
            vmess("Number of time samples .. = %d", nt);
            vmess("time step ............... = %f (s)", dt);
            vmess("maximum frequency ....... = %f Hz", fmax);
            vmess("left cut-off frequency .. = %f Hz", flef);
            vmess("right cut-off frequency . = %f Hz", frig);
            vmess("minimum frequency ....... = %f Hz", fmin);
            vmess("time shift .............. = %f (s)", t0);
        }

    }
    else if (strstr(w, "mon") != NULL) {
        for (j = 0; j < nfreq; j++) {
            cwave[j].r = 0.0;
            cwave[j].i = 0.0;
        }
        i = NINT(fp/df);
        cwave[i].r = 0.5*cos(2.0*M_PI*i*df*t0);
        cwave[i].i = -0.5*sin(2.0*M_PI*i*df*t0);

        if (verbose >= 1) {
            vmess("Monochromatic wavelet");
            vmess("---------------------");
            vmess("Number of time samples .. = %d", nt);
            vmess("time step ............... = %e (s)", dt);
            vmess("frequency ............... = %f Hz", i*df);
            vmess("time shift .............. = %e (s)", t0);
        }
    }
    else if (strstr(w, "sqrtg2") != NULL) {
        if (fp < 0.0) {
            i = NINT(fmax/(2.0*df));
            for (iof = i; iof > 0; iof--) {
                f = iof*df;
                if((gauss2freq(fmax, f) < att)&&(stored != 1)) {
                    freq = f;
                    stored = 1;
                }
            }
            if (stored == 0) verr("No valid wavelet found.");
        }
        else freq = fp;
        stored = 0;

        if (shift == 1) {
            for (i = 0; i < optn; i++) {
                tt=(float)i*dt;
                dum = fabs(gauss2time(tt,freq))+fabs(gauss2time((tt+dt),freq));
                if ((dum<1e-3)&&(stored != 1)) {
                    t0 = (float)i*dt;
                    stored = 1;
                }
            }
        }
                
        for (iof = 0; iof < nfreq; iof++) {
            f = iof*df;
            fact = f/(freq);
            fact *= exp(-0.5*fact*fact);
            cwave[iof].r = fact*cos(2.0*M_PI*f*t0);
            cwave[iof].i = -fact*sin(2.0*M_PI*f*t0);
        }
        if (verbose >= 1) {
            vmess("Sqrt of Second derivative of Gaussian wavelet");
            vmess("-------------------------------------");
            vmess("Number of time samples .. = %d", nt);
            vmess("time step ............... = %f (s)", dt);
            if (fp < 0) {
                vmess("maximum frequency at  ... = %f (Hz)",fmax);
                vmess("with attenutation ....... = %f", att);
            }
            vmess("frequency peak at ....... = %f Hz", freq);
            vmess("time shift .............. = %f (s)", t0);
        }
    }
    else  {
        if (fp < 0.0) {
            i = NINT(fmax/(2.0*df));
            for (iof = i; iof > 0; iof--) {
                f = iof*df;
                if((gauss2freq(fmax, f) < att)&&(stored != 1)) {
                    freq = f;
                    stored = 1;
                }
            }
            if (stored == 0) verr("No valid wavelet found.");
        }
        else freq = fp;
        stored = 0;

        if (shift == 1) {
            for (i = 0; i < optn; i++) {
                tt=(float)i*dt;
                dum = fabs(gauss2time(tt,freq))+fabs(gauss2time((tt+dt),freq));
                if ((dum<1e-3)&&(stored != 1)) {
                    t0 = (float)i*dt;
                    stored = 1;
                }
            }
        }
        for (iof = 0; iof < nfreq; iof++) {
            f = iof*df;
            fact = f*f/(freq*freq);
            fact *= exp(-fact);
            cwave[iof].r = fact*cos(2.0*M_PI*f*t0);
            cwave[iof].i = -fact*sin(2.0*M_PI*f*t0);
        }
        if (verbose >= 1) {
            vmess("Second derivative of Gaussian wavelet");
            vmess("-------------------------------------");
            vmess("Number of time samples .. = %d", nt);
            vmess("time step ............... = %f (s)", dt);
            if (fp < 0) {
                vmess("maximum frequency at  ... = %f (Hz)",fmax);
                vmess("with attenutation ....... = %f", att);
            }
            vmess("frequency peak at ....... = %f Hz", freq);
            vmess("time shift .............. = %f (s)", t0);
        }
    }
    if (inverse==1) {
        vmess("inverse with eps  ....... = %f (s)", eps);
        for (iof = 1; iof < nfreq; iof++) {
            fact = cwave[iof].r*cwave[iof].r + cwave[iof].i*cwave[iof].i;
            cwave[iof].r = cwave[iof].r/(fact+eps);
            cwave[iof].i = -cwave[iof].i/(fact+eps);
        }
        cwave[0].r = 0.0;
        cwave[0].i = 0.0;
    }

    /* minimum phase calculation */
    if (inverse==2) {
        vmess("minimum phase calculation ");
        nf = (2*(nfreq-1));
        mpwave = (complex *)calloc(nf,sizeof(complex));
        
        fprintf(stderr,"nf=%d\n", nf);
        amplitude = (float *)calloc(2*nf,sizeof(float));
        for (iof = 0; iof < nfreq; iof++) {
            fact = sqrt(cwave[iof].r*cwave[iof].r + cwave[iof].i*cwave[iof].i);
            if (fact > 0.0) amplitude[iof] = log(fact);
            else amplitude[iof] = 0.0;
            amplitude[nf+iof] = fact;
        }
        hilbertTrans(amplitude, nf);
        for (iof = 0; iof < nfreq; iof++) {
            fact = amplitude[nf+iof];
            fprintf(stderr,"amplitude[%d] = %f phase = %f\n", iof, fact, amplitude[iof]);
            if (fact != 0.0) {
                mpwave[iof].r = (float) fact*cos(amplitude[iof]);
                mpwave[iof].i = (float) -fact*sin(amplitude[iof]);
            }
            else { 
                mpwave[iof].r=0.0;
                mpwave[iof].i=0.0;
            }
        }
        for (iof = nf-1; iof > nfreq; iof--) {
            mpwave[iof].r=mpwave[nf-iof].r;
            mpwave[iof].i=-1.0*mpwave[nf-iof].i;
        }
        cc1fft(mpwave, nf, 1);
        for (i = 0; i < nt; i++) rwave[i] = mpwave[i].r;

        free(amplitude);
        free(mpwave);
    }
    else {
        sign = 1;
        cr1fft(cwave, rwave, optn, sign);
    }

    max = rwave[0];
    for (i = 0; i < nt; i++) if (rwave[i] > max) max = rwave[i];
    max = scale/max;
    if (scale == 0) {
        if (scfft == 0) max = 1.0/(float)nt;
        else max = df;
    }
    //fprintf(stderr,"scaling factor back FFT=%e\n", max);
    for (i = 0; i < nt; i++) {
		wave[i]= rwave[i]*max*exp(alpha*i*dt);
	}

    free(cwave);
    free(rwave);

    return;
}

float gauss2time(float t, float f)
{
    float value;

    value = ((1.0-2.0*M_PI*M_PI*f*f*t*t)*exp(-M_PI*M_PI*f*f*t*t));
    return value;
}

float gauss1time(float t, float f)
{
    float value;

    value = (-t*exp(-M_PI*M_PI*f*f*t*t))*(sqrt(2.0)*f*M_PI*exp(0.5));
    return value;
}

float gauss0time(float t, float f)
{
    float value;

    value = exp(-M_PI*M_PI*f*f*t*t);
    return value;
}

float gauss2freq(float f, float freq)
{
    float     value;

    value = f*f/(freq*freq);
    value *= exp(1.0)*exp(-value);

    return value;
}

float gauss1freq(float f, float freq)
{
    float     value;

    value = f*f/(2.0*freq*freq);
    value = sqrt(2.0*exp(1))*f*exp(-value)/(sqrt(2.0)*freq);

    return value;
}

float gauss0freq(float f, float freq)
{
    float     value;

    value = f*f/(freq*freq);
    value = exp(-value);

    return value;
}



void hilbertTrans(float *data, int nsam)
{
    int     optn, j, sign, nfreq;
    float   scale;
    complex *cdata;

    optn = optncr(nsam);
    nfreq = optn/2+1;
    fprintf(stderr,"Hilbert optn=%d nsam=%d nfreq=%d\n", optn, nsam, nfreq);
    cdata = (complex *)malloc(optn*sizeof(complex));
    if (cdata == NULL) verr("memory allocation error for cdata");

    for(j = 0; j < nsam; j++){
        cdata[j].r = data[j];
        cdata[j].i = 0.0;
    }
    for(j = nsam; j < optn; j++){
        cdata[j].r = 0.0;
        cdata[j].i = 0.0;
    }
    sign = -1;
    cc1fft(&cdata[0], optn, sign);

    for(j = nfreq; j < optn; j++){
        cdata[j].r = 0.0;
        cdata[j].i = 0.0;
    }

    sign = 1;
    cc1fft(&cdata[0], optn, sign);

    scale= 1.0/(float)optn;
    for (j = 0 ; j < nsam ; j++) data[j] = cdata[j].i*scale;

    free(cdata);

    return;
}