# ESP article Chirp Z transform questions/problems

Started by February 12, 2004
```I read the article and downloaded the code (below). Problem is every
compiler I have tried (CodeComposer, gnu, VisualC++) has problems with
the notations:

double[][] xxxx (I indicate occurrences in the code below with '<='

I did a little research and found Stroustroup actually says this is
illegal C/C++. And he gave examples of double[][2]-- but even his
example of the least index being known would not compile.

Anyone have any ideas how to get around this and still be able to use
indices instead of a bunch of ugly pointer code?

This is the only code I've really tried to use from the ESP magazine
and I'm surprised the publisher didn't check it out before publishing
the article....

Thanks,

Paul

/************Chirp Z Transform *****************
* N = # input samples. M = # output samples.
*
* fsam   = the sample frequency in Hz.
* fstart = the start frequency in Hz.
* fstop  = the stop frequency in Hz for the band over which the
transform is computed.
*
* (fstart - fstop)/M = new resolution
*
* Note: this method returns an array of length L.
* L = the returned transform length. L will always be larger than
M.
* See code for how L is determined
*
**********************************************/
public double[ ][ ] czt( double [ ][ ] array, <=================
int N, int M, double fStart, double fStop, double fSam )
{
int L;

/***Determine length of CZT output***/
if( (N+M) > 512){
L = 1024;
}else if( ((N+M) > 256) && ((N+M) <= 512) ){
L = 512;
}else if( ((N+M) > 128) && ((N+M) <= 256) ){
L = 256;
}else if( ((N+M) > 64 ) && ((N+M) <= 128) ){
L = 128;
}else if( ((N+M) > 32 ) && ((N+M) <= 64) ){
L = 64;
}else if( ((N+M) > 16 ) && ((N+M) <= 32) ){
L = 32;
}else{
L = 16;
}

double[ ][ ] g = new double[L][2];<=====================
double[ ][ ] h = new double[L][2];<=====================
double theta0;
double phi0;
double psi;
double a;
double b;
int n;
int k;

phi0 = 2.*Math.PI*(fStop-fStart)/fSam/(M-1);
theta0 = 2.*Math.PI*fStart/fSam;

/*** Create arc coefficients ***/
for( n = 0; n < M; n++ ){
h[n][0] = Math.cos( n*n/2.*phi0 );
h[n][1] = Math.sin( n*n/2.*phi0 );
}
for( n = M; n < L-N; n++ ){
h[n][0] = 0.;
h[n][1] = 0.;
}
for( n = L-N; n < L; n++){
h[n][0] = Math.cos( (L-n)*(L-n)/2.*phi0 );
h[n][1] = Math.sin( (L-n)*(L-n)/2.*phi0 );
}

/*** Prepare signal ***/
for( n = 0; n < N; n++ ){
g[n][0] = array[n][0];
g[n][1] = array[n][1];
}
for( n = N; n < L; n++ ){
g[n][0] = 0.;
g[n][1] = 0.;
}

double s;
double c;

for( n = 0; n < N; n++ ){
psi = n*theta0 + n*n/2.*phi0;
c =  Math.cos( psi);
s = -Math.sin( psi );
a = c*g[n][0] - s*g[n][1];
b = s*g[n][0] + c*g[n][1];
g[n][0] = a;
g[n][1] = b;
}
//use your favorite fft algorithm here.
g = fft_1d( g );   //fft of samples
h = fft_1d( h );   //fft of arc coeff

/** convolution in the time domain is multiplication in the
frequency domain **/
/** multiplication in the time domain is convolution in the
frequency domain **/
for( n = 0; n < L; n++ ){
c = g[n][0];
s = g[n][1];
a = c*h[n][0] - s*h[n][1];
b = s*h[n][0] + c*h[n][1];
g[n][0] = a/L;  /* for scaling purposes since
fft_1d does not use scale */
g[n][1] = b/L;
}

g = ifft_1d( g );   //use your favorite fft algorithm here.

for( k = 0; k < M; k++ ){
psi = k*k/2.*phi0;
c =  Math.cos( psi );
s = -Math.sin( psi );
a = c*g[k][0] - s*g[k][1];
b = s*g[k][0] + c*g[k][1];
g[k][0] = a;
g[k][1] = b;
}

return g;

}

```
```X-No-Archive: Yes

bo <pec@charter.net> wrote:

>compiler I have tried (CodeComposer, gnu, VisualC++) has problems with
>the notations:

Was a good article.  Could have used such when I was working with the
CZT.

>
>double[][] xxxx (I indicate occurrences in the code below with '<='
>
>I did a little research and found Stroustroup actually says this is
>illegal C/C++. And he gave examples of double[][2]-- but even his
>example of the least index being known would not compile.

I've seen this with some compilers, when declaring double dimension
arrays arguments in function prototypes, and the only fix was to
supply the actual value for both dimensions.  Don't know if that helps

>
>Anyone have any ideas how to get around this and still be able to use
>indices instead of a bunch of ugly pointer code?
>
>This is the only code I've really tried to use from the ESP magazine
>and I'm surprised the publisher didn't check it out before publishing
>the article....

Robert

( modify address for return email )

www.numbersusa.com
www.americanpatrol.com
```
```The variable declarations should be like:

double var[][2];

The syntax for the function return is annoying --something like double
(func[][2])(...args...).  I would do:

typedef double SAMPLE_ARRAY[][2]

SAMPLE_ARRAY var;

SAMPLE_ARRAY func(...args...);

```
```I have tried specifying only the latter dimension as 2 and CCS still
pukes on it. In the meantime, I have discovered that this code isn't
C++, but rather Java... so that explains why it won't compile :).
Rats! Does anyone know of a Java compiler for DSPs? I never heard of
this before.

Nevertheless, my goal is to convert to C.

I agree with Robert in that it was a good article. It would 've been
nice for the author to have provided some comments about how he
compiled and tested the code. Also the article/code-comments were
lacking in their description of how/what his "insert your favorite FFT
routine here calls" are expected to do. (e.g. FFT in
place--overwriting org data? and input params meaning as he used in
his calls.)  I'd give the article an 'A' or 'A-' because it would 've
taken so little to make it an 'A+' in my opinion.

Robert, you said this would 've help you in you prior CZT experience.
Any chance you'd share that experience and/or code?  and how you dealt
with 2d arrays?

Thanks for the help.

Regards,

Paul

On Thu, 12 Feb 2004 23:21:53 -0500, "Matt Timmermans"
<mt0000@sympatico.nospam-remove.ca> wrote:

>The variable declarations should be like:
>
>double var[][2];
>
>The syntax for the function return is annoying --something like double
>(func[][2])(...args...).  I would do:
>
>typedef double SAMPLE_ARRAY[][2]
>
>SAMPLE_ARRAY var;
>
>SAMPLE_ARRAY func(...args...);
>

```
```"bo" <pec@charter.net> wrote in message
news:pujp20p8nlm4hei4d7qus0280ji73c08re@4ax.com...
> I have tried specifying only the latter dimension as 2 and CCS still
> pukes on it.

Yes, but that's not the only difference between what you started with and
what I suggested.  Java allows dimensions after the type name, but C
requires them after the variable.

> Nevertheless, my goal is to convert to C.

It's mostly C already.   You have to fix the declarations, and the
references to Math.sin and Math.cos, and include the appropriate headers.
Nothing else jumps out as being obviously wrong, but there may be a few
small changes required.

You'll probably also want to allocate all the arrays outside of the function
and pass them in as arguments so you can reuse them across calls, because
dynamic memory allocation is pretty slow, especially in the worst case.

```