454 lines · 12.0 KB · C
RawDownload
/*----------------------------------------------------------------------------    ChucK Concurrent, On-the-fly Audio Programming Language      Compiler and Virtual Machine     Copyright (c) 2004 Ge Wang and Perry R. Cook.  All rights reserved.      http://chuck.cs.princeton.edu/      http://soundlab.cs.princeton.edu/     This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.     This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.     You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307    U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// name: util_xform.c// desc: transforms//// authors: Ge Wang (gewang@cs.princeton.edu)//          Perry R. Cook (prc@cs.princeton.edu)//          FFT: CARL music distribution// date: 11.27.2003//-----------------------------------------------------------------------------#include "util_xforms.h"#include <stdlib.h>#include <math.h>    //-----------------------------------------------------------------------------// name: hanning()// desc: make window//-----------------------------------------------------------------------------void hanning( FLOAT * window, unsigned long length ){    unsigned long i;    double pi, phase = 0, delta;     pi = 4.*atan(1.0);    delta = 2 * pi / (double) length;     for( i = 0; i < length; i++ )    {        window[i] = (FLOAT)(0.5 * (1.0 - cos(phase)));        phase += delta;    }}    //-----------------------------------------------------------------------------// name: hamming()// desc: make window//-----------------------------------------------------------------------------void hamming( FLOAT * window, unsigned long length ){    unsigned long i;    double pi, phase = 0, delta;     pi = 4.*atan(1.0);    delta = 2 * pi / (double) length;     for( i = 0; i < length; i++ )    {        window[i] = (FLOAT)(0.54 - .46*cos(phase));        phase += delta;    }}    //-----------------------------------------------------------------------------// name: blackman()// desc: make window//-----------------------------------------------------------------------------void blackman( FLOAT * window, unsigned long length ){    unsigned long i;    double pi, phase = 0, delta;     pi = 4.*atan(1.0);    delta = 2 * pi / (double) length;     for( i = 0; i < length; i++ )    {        window[i] = (FLOAT)(0.42 - .5*cos(phase) + .08*cos(2*phase));        phase += delta;    }}    //-----------------------------------------------------------------------------// name: bartlett()// desc: make window//-----------------------------------------------------------------------------void bartlett( FLOAT * window, unsigned long length ){    unsigned long i;    FLOAT half = (FLOAT)length / 2;     for( i = 0; i < length; i++ )    {        if( i < half ) window[i] = i / half;        else window[i] = (length - i) / half;    }}    //-----------------------------------------------------------------------------// name: apply_window()// desc: apply a window to data//-----------------------------------------------------------------------------void apply_window( FLOAT * data, FLOAT * window, unsigned long length ){    unsigned long i;     for( i = 0; i < length; i++ )        data[i] *= window[i];} static FLOAT PI ;static FLOAT TWOPI ;void bit_reverse( FLOAT * x, long N ); //-----------------------------------------------------------------------------// name: rfft()// desc: real value fft////   these routines from the CARL software, spect.c//   check out the CARL CMusic distribution for more source code////   if forward is true, rfft replaces 2*N real data points in x with N complex //   values representing the positive frequency half of their Fourier spectrum,//   with x[1] replaced with the real part of the Nyquist frequency value.////   if forward is false, rfft expects x to contain a positive frequency //   spectrum arranged as before, and replaces it with 2*N real values.////   N MUST be a power of 2.////-----------------------------------------------------------------------------void rfft( FLOAT * x, long N, unsigned int forward ){    static int first = 1 ;    FLOAT c1, c2, h1r, h1i, h2r, h2i, wr, wi, wpr, wpi, temp, theta ;    FLOAT xr, xi ;    long i, i1, i2, i3, i4, N2p1 ;     if( first )    {        PI = (FLOAT) (4.*atan( 1. )) ;        TWOPI = (FLOAT) (8.*atan( 1. )) ;        first = 0 ;    }     theta = PI/N ;    wr = 1. ;    wi = 0. ;    c1 = 0.5 ;     if( forward )    {        c2 = -0.5 ;        cfft( x, N, forward ) ;        xr = x[0] ;        xi = x[1] ;    }    else    {        c2 = 0.5 ;        theta = -theta ;        xr = x[1] ;        xi = 0. ;        x[1] = 0. ;    }        wpr = (FLOAT) (-2.*pow( sin( 0.5*theta ), 2. )) ;    wpi = (FLOAT) sin( theta ) ;    N2p1 = (N<<1) + 1 ;        for( i = 0 ; i <= N>>1 ; i++ )    {        i1 = i<<1 ;        i2 = i1 + 1 ;        i3 = N2p1 - i2 ;        i4 = i3 + 1 ;        if( i == 0 )        {            h1r =  c1*(x[i1] + xr ) ;            h1i =  c1*(x[i2] - xi ) ;            h2r = -c2*(x[i2] + xi ) ;            h2i =  c2*(x[i1] - xr ) ;            x[i1] =  h1r + wr*h2r - wi*h2i ;            x[i2] =  h1i + wr*h2i + wi*h2r ;            xr =  h1r - wr*h2r + wi*h2i ;            xi = -h1i + wr*h2i + wi*h2r ;        }        else        {            h1r =  c1*(x[i1] + x[i3] ) ;            h1i =  c1*(x[i2] - x[i4] ) ;            h2r = -c2*(x[i2] + x[i4] ) ;            h2i =  c2*(x[i1] - x[i3] ) ;            x[i1] =  h1r + wr*h2r - wi*h2i ;            x[i2] =  h1i + wr*h2i + wi*h2r ;            x[i3] =  h1r - wr*h2r + wi*h2i ;            x[i4] = -h1i + wr*h2i + wi*h2r ;        }         wr = (temp = wr)*wpr - wi*wpi + wr ;        wi = wi*wpr + temp*wpi + wi ;    }     if( forward )        x[1] = xr ;    else        cfft( x, N, forward ) ;}    //-----------------------------------------------------------------------------// name: cfft()// desc: complex value fft////   these routines from CARL software, spect.c//   check out the CARL CMusic distribution for more software////   cfft replaces FLOAT array x containing NC complex values (2*NC FLOAT //   values alternating real, imagininary, etc.) by its Fourier transform //   if forward is true, or by its inverse Fourier transform ifforward is //   false, using a recursive Fast Fourier transform method due to //   Danielson and Lanczos.////   NC MUST be a power of 2.////-----------------------------------------------------------------------------void cfft( FLOAT * x, long NC, unsigned int forward ){    FLOAT wr, wi, wpr, wpi, theta, scale ;    long mmax, ND, m, i, j, delta ;    ND = NC<<1 ;    bit_reverse( x, ND ) ;        for( mmax = 2 ; mmax < ND ; mmax = delta )    {        delta = mmax<<1 ;        theta = TWOPI/( forward? mmax : -mmax ) ;        wpr = (FLOAT) (-2.*pow( sin( 0.5*theta ), 2. )) ;        wpi = (FLOAT) sin( theta ) ;        wr = 1. ;        wi = 0. ;         for( m = 0 ; m < mmax ; m += 2 )        {            /* register */ FLOAT rtemp, itemp ;            for( i = m ; i < ND ; i += delta )            {                j = i + mmax ;                rtemp = wr*x[j] - wi*x[j+1] ;                itemp = wr*x[j+1] + wi*x[j] ;                x[j] = x[i] - rtemp ;                x[j+1] = x[i+1] - itemp ;                x[i] += rtemp ;                x[i+1] += itemp ;            }             wr = (rtemp = wr)*wpr - wi*wpi + wr ;            wi = wi*wpr + rtemp*wpi + wi ;        }    }     // scale output    scale = (FLOAT)(forward ? 1./ND : 2.) ;    {        /* register */ FLOAT *xi=x, *xe=x+ND ;        while( xi < xe )            *xi++ *= scale ;    }}    //-----------------------------------------------------------------------------// name: bit_reverse()// desc: bitreverse places FLOAT array x containing N/2 complex values//       into bit-reversed order//-----------------------------------------------------------------------------void bit_reverse( FLOAT * x, long N ){    FLOAT rtemp, itemp ;    long i, j, m ;    for( i = j = 0 ; i < N ; i += 2, j += m )    {        if( j > i )        {            rtemp = x[j] ; itemp = x[j+1] ; /* complex exchange */            x[j] = x[i] ; x[j+1] = x[i+1] ;            x[i] = rtemp ; x[i+1] = itemp ;        }         for( m = N>>1 ; m >= 2 && j >= m ; m >>= 1 )            j -= m ;    }}    //-----------------------------------------------------------------------------// name: the_dct()// desc: type ii dct on N reals//-----------------------------------------------------------------------------void the_dct( FLOAT * x, unsigned long N, FLOAT * out, unsigned long Nout ){    unsigned long k, n;     // sanity check    assert( Nout <= N );    // zero out    memset( out, 0, sizeof(FLOAT)*Nout );     // go for it    for( k = 0; k < Nout; k++ )    {        for( n = 0; n < N; n++ )        {            out[k] += x[n] * cos( ONE_PI / N * k * (n + .5) );        }    }}     //-----------------------------------------------------------------------------// name: the_dct_matrix()// desc: type ii dct matrx on N reals//-----------------------------------------------------------------------------void the_dct_matrix( FLOAT ** out, unsigned long N ){    unsigned long k, n;     // go for it    for( k = 0; k < N; k++ )    {        for( n = 0; n < N; n++ )        {            out[k][n] = cos( ONE_PI / N * k * (n + .5) );        }    }}  //-----------------------------------------------------------------------------// name: the_dct_now()// desc: apply dct matrx on N reals//-----------------------------------------------------------------------------void the_dct_now( FLOAT * x, FLOAT ** matrix, unsigned long N,                  FLOAT * out, unsigned long Nout ){    unsigned long k, n;     // sanity check    assert( Nout <= N );    // zero out    memset( out, 0, sizeof(FLOAT)*Nout );     // go for it    for( k = 0; k < Nout; k++ )    {        for( n = 0; n < N; n++ )        {            out[k] = x[n] * matrix[k][n];        }    }}    //-----------------------------------------------------------------------------// name: the_inverse_dct()// desc: type iii dct, or inverse dct//-----------------------------------------------------------------------------void the_inverse_dct( FLOAT * x, unsigned long N, FLOAT * out, unsigned long Nout ){}  //-----------------------------------------------------------------------------// name: the_inverse_dct_matrix()// desc: generates the NxN DCT matrix//-----------------------------------------------------------------------------void the_inverse_dct_matrix( FLOAT ** out, unsigned long N ){    unsigned long k, n;     // go for it    for( k = 0; k < N; k++ )    {        for( n = 0; n < N; n++ )        {            out[k][n] = cos( ONE_PI / N * n * (k + .5) );        }    }}    //-----------------------------------------------------------------------------// name: the_inverse_dct_now()// desc: apply inverse dct matrx on N reals//-----------------------------------------------------------------------------void the_inverse_dct_now( FLOAT * x, FLOAT ** matrix, unsigned long N,                  FLOAT * out, unsigned long Nout ){    unsigned long k, n;     // sanity check    assert( Nout <= N );    // zero out    memset( out, 0, sizeof(FLOAT)*Nout );     // go for it    for( k = 0; k < Nout; k++ )    {        for( n = 0; n < N; n++ )        {            out[k] = x[0] / 2 + x[n] * matrix[k][n];        }    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t