Forums > MaxMSP

Ranking (fft frames) using only vanilla objects? (mp3-ification)

April 13, 2013 | 1:31 pm

I’ve been using this custom external for the ranking of fft frames to produce an mp3 type compression. I really dig the sound of it, particularly when used with bit/sample reduction or other extreme distortion.

Now what I have works great, but it’s mac only (which makes sharing the patch difficult), and is also 32bit. So I want to try to remove the dependency altogether, if possible.

Now I kind of understand sorting algorithms (framerank~ uses combsort if I understand correctly), but I have no idea how this kind of sorting is handled in Max, much less fft max.

Here is the patch and external.

And here is the .c from the xcode project:

//////////////////////////////////////////////////////////////////////

#include "ext.h"
#include "z_dsp.h"
#include

/*
framerank~ is an object to average the values of a specific number of fft frames.
*/

void *this_class;

typedef struct _framerank
{
t_pxobject x_obj;

long *indices;

} t_framerank;

void *framerank_new (long windowsize, long size);
t_int *framerank_perform(t_int *w);
void framerank_dsp(t_framerank *x, t_signal **sp, short *count);
void framerank_free(t_framerank *x);
void framerank_assist (t_framerank *x, void *b, long m, long a, char *s);

int main(void)
{
setup((t_messlist **) &this_class, (method) framerank_new, (method)framerank_free, (short)sizeof(t_framerank), 0L, A_DEFLONG, A_DEFLONG, 0);
addmess((method)framerank_dsp, "dsp", A_CANT, 0);
addmess ((method)framerank_assist, "assist", A_CANT, 0);
dsp_initclass();

return 0;
}

void *framerank_new(long windowsize, long size)
{
t_framerank *x = (t_framerank *)newobject(this_class);

dsp_setup((t_pxobject *)x, 1);
outlet_new(x, "signal");

x->indices = 0;

return (x);
}

void framerank_free(t_framerank *x)
{
dsp_free(&x->x_obj);
if (x->indices)
free (x->indices);
}

void combsort_indices_float (long *indices, float *data, long num_points)
{
long gap = num_points;
long swaps = 1;
long index;
long gap_index;
long i;

while (gap > 1 || swaps)
{
if (gap > 1)
{
gap = (gap * 10) / 13;
if (gap == 9 || gap == 10)
gap = 11;
if (gap < 1) gap = 1;
}

for (i = 0, swaps = 0; i + gap < num_points; i++)
{
index = indices[i];
gap_index = indices[i + gap];
if (data[index] < data[gap_index])
{
indices[i] = gap_index;
indices[i + gap] = index;
swaps = 1;
}
}
}
}

t_int *framerank_perform(t_int *w) // Here we just store the incoming vals if we are taking a sample and then decide when to output
{
float *in = (float *)(w[1]);
float *out = (float *)(w[2]);
int vectsize = w[3];
t_framerank *x = (t_framerank *)(w[4]);

long *indices = x->indices;
long i;

if (x->x_obj.z_disabled)
goto out;

for (i = 0; i < vectsize; i++)
indices[i] = i;

combsort_indices_float(indices, in, vectsize);

for (i = 0; i < vectsize; i++)
out[indices[i]] = i + 1;

out:
return w + 5;
}

void framerank_dsp(t_framerank *x, t_signal **sp, short *count)
{
free (x->indices);
x->indices = malloc (sizeof(long) * sp[0]->s_n);

dsp_add(framerank_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x);
}

void framerank_assist(t_framerank *x, void *b, long m, long a, char *s)
{
if (m == ASSIST_OUTLET)
sprintf(s,"(signal) Ranking");
else
sprintf(s,"(signal) FFT Data In");
}

Attachments:
  1. mp3.zip

April 13, 2013 | 11:57 pm

Ok, thinking about this further I’m thinking I might be able to get there doing some kind of spectral gate, where only bins above a certain threshold pass through. Though not exactly ordered, it’s unlikely they would have the same magnitudes, so adjusting the threshold should drop out bins one at a time.

Basically like the spectral gate in the MSP examples.

Though this doesn’t sound as interesting as framerank. With a low setting in framerank you get all these fft/bubbly kind of things, where as the spectral gate sounds very gate-y regardless.

Not sure what’s different about those two approaches though.


April 14, 2013 | 11:30 pm

Here’s a comparison between the two.

Attachments:
  1. Archive.zip

Viewing 3 posts - 1 through 3 (of 3 total)