MSP external inside pfft

CarmineCella's icon

Hi all,

I'm writing a Max external called sparkle~ and I have a problem.

It's a tool for frequency processing: in the first version I was doing
windowing and overlapping my self,
taking and giving audio data, such as:

adc~ 1
!
!
sparkle~ (overlapp add, windowing, fft, ifft, cartopol, poltocar, ... all
inside)
!
!
dac~ 1

Then, for some reasons, i decided to make it work inside a pfft~ subpatch
like this:

fftin~ 1
!
!
cartopol~
!
!
sparkle~ (not windowing nor overlapping anymore, just data processing)
!
!
poltocar~
!
!
fftout~ 1

Here it is my problem:

the resynthesis is not good as I get when I was doing the overlap myself
(is like filtered). I suppose I'm loosing data because in the
perfom function of the external I only have access to vector-sized buffers
not to FFT-sized buffer (as I'm supposing should happen inside pfft~).
But if I try to access more data everything crashes, as if it were not
allocated.

Can anyone give me a hint to solve the problem?

Thanks a lot, Carmine

Emmanuel Jourdan's icon

It's hard to tell without looking at the code. Basically what you get in your perform method is the unwindowed vector of real / imaginary for each window. As an example here it what zsa.centroid's perform looks like:

void zsa_centroid_perform64(t_zsa_centroid *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
{
    double *r            = ins[0];
    double *i            = ins[1];
    double *freqout        = outs[0];
    long j, n            = sampleframes;
    double binsize        = x->x_sr / (sampleframes * 2);
    double centroid        = 0;
    double sommeAmp        = 0;
    double sommeIndex    = 0;
    double tmp;

    for (j = 0; j < n; j++) {
        tmp = r[j]*r[j] + i[j]*i[j];    // amplitude energy
        sommeAmp += tmp;
        sommeIndex += tmp * j;
    }

    if (sommeAmp)
        centroid = sommeIndex / sommeAmp * binsize;
    else
        centroid = 0.;

    while (n--) {
        *freqout++ = centroid;
    }
}

You might need to do something different to take care of the number of overlaps. Zsa.centroid's outputs needs to be divided by the number of overlaps before being sent out pfft~ out objects to have the correct value.

CarmineCella's icon

Hi Emmanuel,

thanks for your answer. I'll try to clean up a bit my code and I'll post it.
Anyway, here what I am assuming inside pfft:

1. the signal passed to any fftin~ is already composed and windowed properly
2. inside my external I can use up to N image&real samples (as specified in the parameters of pfft)
3. is up to me the normalization for the signal before passing it to fftout~

is this right?

I'll keep you update. Best, Carmine

Emmanuel Jourdan's icon

1. yep
2. yep (looking at numins and numouts should give you the number of bins)
3. probably

Cheers,
ej

CarmineCella's icon

Hi Emmanuel,

I finally solved the problem. In fact I was doing all in the right way, but I was using in a wrong way pfft~ : I was assuming the full-spectrum mode without setting the specific flag. I then changed the invocation of pfft~ in the following way:

pfft~ sparkle_obj 2048 4 0 1

and everything started working!

Thanks anyway for your help.
Cheers, Carmine

Emmanuel Jourdan's icon

Cool. Thanks for the update. Looking forward to hearing sparkle magic ;-)