I haven't tried it, but you could be overtaxing the dsp if you are
performing the fft on external memory at 48k Fs. just glancing at the
code, it looks like they are using both the pm and dm bus which
enables them to fetch and write in one cycle. I haven't looked at the
sdram configuration on the chip, but I think it might be only tied to
the dm bus. So if you put both on dm, external or not, you can't
read/write in one cycle.
my guess. Are you using the ezkit?
Klaus Koch <klauskoch@gmx.com> wrote in message news:<Xns942FC3C28ABC5none@195.114.230.36>...
> Hello Bernhard,
>
> the code I've posted performs the fft / ifft only once and then plays
> that transformed and inverse transformed sample infinitely. It doesn't
> operate on streamed data, It just fills the buffer, then does the fft
> and ifft and loops the original data on the left channel and the fft /
> ifft data on the right channel, so I can compare the two signals.
>
> My problem was (which I forgot to mention) that the ifft data was
> totally noisy and "cracky". It sounded like the bitcrusher effect in
> Cubase.
>
> A few hours ago I figured out what was going wrong: the fft / ifft from
> Analog Devices doesn't seem to operate on data located in external
> memory / sdram. If I define the fft buffers to be located in the
> internal memory everything works fine.
>
> My question now is: is it possible to use the fft (cfft, rfft) / ifft
> from the adsp 21161 with data which is located in sdram ? Everytime I
> use the external ram for my buffers the fft routines work with, the
> signal gets completely crackled and noisy. Using internal ram everything
> works fine.
>
> I've slightly rewritten the code. The buffer - definitions are as
> follows:
>
> // seg_dmdata is mapped to sdram
> section("seg_dmdata") float pbuffer_out_data[BUFFER_SIZE];
> section("seg_dmdata") float pbuffer_in_data [BUFFER_SIZE];
>
> // seg_fft is mapped to internal ram, e.g. seg_pmco
> section("seg_fft") complex_float pbuffer_fft_in_data [BUFFER_FFT_SIZE];
> section("seg_fft") complex_float pbuffer_fft_out_data[BUFFER_FFT_SIZE];
>
> This works. Only the input buffers are in sdram. But if I define the
> pbuffer_fft_... data like this
>
> // located in sdram
> section("seg_dmdata") complex_float pbuffer_fft_in_data
> [BUFFER_FFT_SIZE];
> section("seg_dmdata") complex_float pbuffer_fft_out_data
> [BUFFER_FFT_SIZE];
>
> I get problems.
>
> Maybe I can't locate the buffers in external ram because it's to slow
> for the optimized fft routines for 21161 (the help says they need to
> fetch data in one cycle) ? Is there a workaround for this problem or
> have I just done something wrong ? I just thought if it wouldn't be
> possible to use sdram data, why does Analog Devices provide fft
> functions for e.g. 65536 samples (which I can't use with internal memory
> data).
>
> Thank you in advance,
> Klaus
>
>
>
>
> PS: here is the code once again (this variant works)
>
>
> Main.h -----------------------------------------------------------------
>
> ////////////////////////////////////////////////////////////////////////
> // headers
> #include "ADDS_21161_EzKit.h"
>
> #include <def21161.h>
> #include <signal.h>
> #include <filter.h>
>
> #pragma align 1024
>
>
> ////////////////////////////////////////////////////////////////////////
> // buffer
> #define BUFFER_SIZE 0x50000
> #define BUFFER_FFT_SIZE 2048
>
> int buffer_in_index = 0,
> buffer_out_index = 0;
>
> section("seg_dmdata") float pbuffer_out_data[BUFFER_SIZE];
> section("seg_dmdata") float pbuffer_in_data [BUFFER_SIZE];
>
> section("seg_fft") complex_float pbuffer_fft_in_data [BUFFER_FFT_SIZE];
> section("seg_fft") complex_float pbuffer_fft_out_data[BUFFER_FFT_SIZE];
>
>
>
> ////////////////////////////////////////////////////////////////////////
> // states
> enum TState {
> state_fill = 0,
> state_fft,
> state_play
> };
>
> int state = 0;
>
>
>
> ////////////////////////////////////////////////////////////////////////
> // forward declarations
> void processSamples (int);
> void fftBuffer ();
>
>
>
>
>
>
>
> Main.c -----------------------------------------------------------------
>
>
> ////////////////////////////////////////////////////////////////////////
> // headers
> #include "Main.h"
>
>
>
> ////////////////////////////////////////////////////////////////////////
> // main
> void main()
> {
> /////////////////////////////////////////////////////////////////
> Setup_ADSP21161N();
> Setup_SDRAM();
>
> Setup_AD1836();
> Init_AD1852_DACs();
>
> Program_SPORT02_TDM_Registers();
> Program_SPORT02_DMA_Channels();
>
> interruptf(SIG_SP0I, processSamples);
>
> *(int *) SP02MCTL |= MCE;
>
> ////////////////////////////////////////////////////////////////
> while(state != state_fft);
> fftBuffer();
> state = state_play;
>
> while(true)
> asm("idle;");
> }
>
>
>
> ////////////////////////////////////////////////////////////////////////
> // isr
> void processSamples(int sig_int)
> {
> float current_sample_left,
> current_sample_right;
>
>
> Receive_Samples();
>
>
> /////////////////////////////////////////////////////////////////
> if(state == state_fill) {
> pbuffer_in_data[buffer_in_index] = (Left_Channel_In1 / 2.) +
> (Right_Channel_In1 / 2.);
>
> if(++buffer_in_index >= BUFFER_SIZE) {
> state = state_fft;
> buffer_in_index = 0;
> }
> }
>
> //////////////////////////////////////////////////////////////////
> else if(state == state_play) {
> current_sample_left = pbuffer_out_data[buffer_out_index];
> current_sample_right= pbuffer_in_data [buffer_out_index];
>
> Left_Channel_Out0 =
> Left_Channel_Out1 = current_sample_left;
>
> Right_Channel_Out0 =
> Right_Channel_Out1 = current_sample_right;
>
> if(++buffer_out_index >= BUFFER_SIZE)
> buffer_out_index = 0;
> }
>
>
> Transmit_Samples();
> }
>
>
> ////////////////////////////////////////////////////////////////////////
> // fft
> void fftBuffer() {
> int fft_cnt = 0,
> cnt;
>
> complex_float* pbuffer_result_data;
>
> for(fft_cnt = 0; fft_cnt < BUFFER_SIZE; fft_cnt += BUFFER_FFT_SIZE)
> {
> // copy input buffer
> for(cnt = 0; cnt < BUFFER_FFT_SIZE; cnt++) {
> pbuffer_fft_in_data[cnt].re=pbuffer_in_data[fft_cnt + cnt];
> pbuffer_fft_in_data[cnt].im=0;
> }
>
> // i/fft
> cfft2048(pbuffer_fft_in_data, pbuffer_fft_out_data);
> pbuffer_result_data = ifft2048(pbuffer_fft_out_data,
> pbuffer_fft_in_data);
>
> // write output buffer
> for(cnt = 0; cnt < BUFFER_FFT_SIZE; cnt++)
> pbuffer_out_data[fft_cnt + cnt]=pbuffer_result_data[cnt].re;
> }
> }
Reply by Klaus Koch●November 10, 20032003-11-10
Hello Bernhard,
the code I've posted performs the fft / ifft only once and then plays
that transformed and inverse transformed sample infinitely. It doesn't
operate on streamed data, It just fills the buffer, then does the fft
and ifft and loops the original data on the left channel and the fft /
ifft data on the right channel, so I can compare the two signals.
My problem was (which I forgot to mention) that the ifft data was
totally noisy and "cracky". It sounded like the bitcrusher effect in
Cubase.
A few hours ago I figured out what was going wrong: the fft / ifft from
Analog Devices doesn't seem to operate on data located in external
memory / sdram. If I define the fft buffers to be located in the
internal memory everything works fine.
My question now is: is it possible to use the fft (cfft, rfft) / ifft
from the adsp 21161 with data which is located in sdram ? Everytime I
use the external ram for my buffers the fft routines work with, the
signal gets completely crackled and noisy. Using internal ram everything
works fine.
I've slightly rewritten the code. The buffer - definitions are as
follows:
// seg_dmdata is mapped to sdram
section("seg_dmdata") float pbuffer_out_data[BUFFER_SIZE];
section("seg_dmdata") float pbuffer_in_data [BUFFER_SIZE];
// seg_fft is mapped to internal ram, e.g. seg_pmco
section("seg_fft") complex_float pbuffer_fft_in_data [BUFFER_FFT_SIZE];
section("seg_fft") complex_float pbuffer_fft_out_data[BUFFER_FFT_SIZE];
This works. Only the input buffers are in sdram. But if I define the
pbuffer_fft_... data like this
// located in sdram
section("seg_dmdata") complex_float pbuffer_fft_in_data
[BUFFER_FFT_SIZE];
section("seg_dmdata") complex_float pbuffer_fft_out_data
[BUFFER_FFT_SIZE];
I get problems.
Maybe I can't locate the buffers in external ram because it's to slow
for the optimized fft routines for 21161 (the help says they need to
fetch data in one cycle) ? Is there a workaround for this problem or
have I just done something wrong ? I just thought if it wouldn't be
possible to use sdram data, why does Analog Devices provide fft
functions for e.g. 65536 samples (which I can't use with internal memory
data).
Thank you in advance,
Klaus
PS: here is the code once again (this variant works)
Main.h -----------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
// headers
#include "ADDS_21161_EzKit.h"
#include <def21161.h>
#include <signal.h>
#include <filter.h>
#pragma align 1024
////////////////////////////////////////////////////////////////////////
// buffer
#define BUFFER_SIZE 0x50000
#define BUFFER_FFT_SIZE 2048
int buffer_in_index = 0,
buffer_out_index = 0;
section("seg_dmdata") float pbuffer_out_data[BUFFER_SIZE];
section("seg_dmdata") float pbuffer_in_data [BUFFER_SIZE];
section("seg_fft") complex_float pbuffer_fft_in_data [BUFFER_FFT_SIZE];
section("seg_fft") complex_float pbuffer_fft_out_data[BUFFER_FFT_SIZE];
////////////////////////////////////////////////////////////////////////
// states
enum TState {
state_fill = 0,
state_fft,
state_play
};
int state = 0;
////////////////////////////////////////////////////////////////////////
// forward declarations
void processSamples (int);
void fftBuffer ();
Main.c -----------------------------------------------------------------
////////////////////////////////////////////////////////////////////////
// headers
#include "Main.h"
////////////////////////////////////////////////////////////////////////
// main
void main()
{
/////////////////////////////////////////////////////////////////
Setup_ADSP21161N();
Setup_SDRAM();
Setup_AD1836();
Init_AD1852_DACs();
Program_SPORT02_TDM_Registers();
Program_SPORT02_DMA_Channels();
interruptf(SIG_SP0I, processSamples);
*(int *) SP02MCTL |= MCE;
////////////////////////////////////////////////////////////////
while(state != state_fft);
fftBuffer();
state = state_play;
while(true)
asm("idle;");
}
////////////////////////////////////////////////////////////////////////
// isr
void processSamples(int sig_int)
{
float current_sample_left,
current_sample_right;
Receive_Samples();
/////////////////////////////////////////////////////////////////
if(state == state_fill) {
pbuffer_in_data[buffer_in_index] = (Left_Channel_In1 / 2.) +
(Right_Channel_In1 / 2.);
if(++buffer_in_index >= BUFFER_SIZE) {
state = state_fft;
buffer_in_index = 0;
}
}
//////////////////////////////////////////////////////////////////
else if(state == state_play) {
current_sample_left = pbuffer_out_data[buffer_out_index];
current_sample_right= pbuffer_in_data [buffer_out_index];
Left_Channel_Out0 =
Left_Channel_Out1 = current_sample_left;
Right_Channel_Out0 =
Right_Channel_Out1 = current_sample_right;
if(++buffer_out_index >= BUFFER_SIZE)
buffer_out_index = 0;
}
Transmit_Samples();
}
////////////////////////////////////////////////////////////////////////
// fft
void fftBuffer() {
int fft_cnt = 0,
cnt;
complex_float* pbuffer_result_data;
for(fft_cnt = 0; fft_cnt < BUFFER_SIZE; fft_cnt += BUFFER_FFT_SIZE)
{
// copy input buffer
for(cnt = 0; cnt < BUFFER_FFT_SIZE; cnt++) {
pbuffer_fft_in_data[cnt].re=pbuffer_in_data[fft_cnt + cnt];
pbuffer_fft_in_data[cnt].im=0;
}
// i/fft
cfft2048(pbuffer_fft_in_data, pbuffer_fft_out_data);
pbuffer_result_data = ifft2048(pbuffer_fft_out_data,
pbuffer_fft_in_data);
// write output buffer
for(cnt = 0; cnt < BUFFER_FFT_SIZE; cnt++)
pbuffer_out_data[fft_cnt + cnt]=pbuffer_result_data[cnt].re;
}
}
Reply by Bernhard Holzmayer●November 10, 20032003-11-10
Hi Klaus,
a short glance to your code raises a question:
If I interpret this right, it does the following:
1. wait until the ISR has filled the buffer
2. perform a fft on the buffer
3. set state -> play which circularly transmits
the output buffer (during ISR)
4. wait -wait -wait ...
am I missing something, or do you perform only
a single fft on one buffer once?!
I'd guess that this should read like:
However, this code might lose a lot of samples,
because it tries to do the fft/ifft in a single cycle
(if it's thought to work on a streaming basis)
Bernhard
Reply by Klaus Koch●November 8, 20032003-11-08
Hi,
I'm working with a Analog Devices 21161 EZKIT board. I'm a beginner on
the dsp subject and having problems with fft / inverse fft.
I used the talkthrough - example provided with the visual dsp environment
to fill a buffer with the audio signal coming from line-in input. After
filling it, it will be repeated infinite. My idea now was to fft this
buffer after it has been filled and then do a inverse fft. I thought if
doing the fft / inverse, the signal should be the same like the original
input signal (?). But this does not seem to be the case and I just don't
know what is going wrong.
Could please someone take a look at the following code, especially at the
fftBuffer() function or post an example for doing a fft / ifft for the
21161 or a similar kit ?
Regards,
Klaus Koch
-------------------------------------------------------------------------
Main.h
/////////////////////////////////////////////////////////////////////////
#include "ADDS_21161_EzKit.h"
#include <def21161.h>
#include <signal.h>
#include <filter.h>
////////////////////////////////////////////////////////////////////////
int buffer_size = 0x20000;
int buffer_in_index = 0;
float* pbuffer_in_data;
int buffer_out_index = 0;
float* pbuffer_out_data;
int buffer_fft_size = 4096;
complex_float* pbuffer_fft_in_data;
complex_float* pbuffer_fft_out_data;
/////////////////////////////////////////////////////////////////////////
enum TState {
state_fill = 0,
state_fft,
state_play
};
int state = 0;
/////////////////////////////////////////////////////////////////////////
void processSamples (int);
-------------------------------------------------------------------------
Main.c
/////////////////////////////////////////////////////////////////////////
#include "Main.h"
/////////////////////////////////////////////////////////////////////////
void main()
{
Setup_ADSP21161N();
Setup_SDRAM();
Setup_AD1836();
Init_AD1852_DACs();
Program_SPORT02_TDM_Registers();
Program_SPORT02_DMA_Channels();
interruptf(SIG_SP0I, processSamples);
*(int *) SP02MCTL |= MCE;
pbuffer_in_data = (float*) 0x00200000;
pbuffer_out_data = (float*) ((long) pbuffer_in_data +
(buffer_size * sizeof(float)));
pbuffer_fft_in_data = (complex_float*) ((long) pbuffer_out_data
+ (buffer_size * sizeof(float)));
pbuffer_fft_out_data = (complex_float*) ((long)
pbuffer_fft_in_data + (buffer_fft_size * sizeof(complex_float)));
while(state != state_fft);
fftBuffer();
state = state_play;
while(true)
asm("idle;");
}
/////////////////////////////////////////////////////////////////////////
void processSamples(int sig_int)
{
float current_sample_left,
current_sample_right;
Receive_Samples();
if(state == state_fill) {
pbuffer_in_data[buffer_in_index] = (Left_Channel_In1 / 2) +
(Right_Channel_In1 / 2);
if(++buffer_in_index >= buffer_size) {
state = state_fft;
buffer_in_index = 0;
}
}
else if(state == state_play) {
current_sample_left = pbuffer_out_data[buffer_out_index];
current_sample_right= pbuffer_in_data [buffer_out_index];
Left_Channel_Out0 =
Left_Channel_Out1 = current_sample_left;
Right_Channel_Out0 =
Right_Channel_Out1 = current_sample_right;
if(++buffer_out_index >= buffer_size)
buffer_out_index = 0;
}
Transmit_Samples();
}
/////////////////////////////////////////////////////////////////////////
void fftBuffer() {
int fft_cnt,
cnt;
complex_float* pbuffer_result_data;
for(fft_cnt = 0; fft_cnt < buffer_size; fft_cnt += buffer_fft_size) {
// copy input buffer
for(cnt = 0; cnt < buffer_fft_size; cnt++) {
pbuffer_fft_in_data[cnt].re = pbuffer_in_data[fft_cnt + cnt];
pbuffer_fft_in_data[cnt].im = 0;
}
// i/fft
cfft4096(pbuffer_fft_in_data, pbuffer_fft_out_data);
pbuffer_result_data = ifft4096(pbuffer_fft_out_data,
pbuffer_fft_in_data);
// write output buffer
for(cnt = 0; cnt < buffer_fft_size; cnt++)
pbuffer_out_data[fft_cnt + cnt] = pbuffer_result_data
[cnt].re;
}
}