Forums > Dev

use post inside a perform routine (more precision)

January 23, 2009 | 5:11 pm

Hi,

I’ve read the two subjects ine the forum about posting into a perform routine method, but I’m still confused.

http://www.cycling74.com/forums/index.php?t=msg&goto=103347&rid=0&srch=outlet+perform+routine#msg_103347

My goal is to output the result of the computation of a detection algorithm that should occurs on each signal block.
So my object has one signal inlet and one control outlet.

I’d like to understand better if that I have to use a clock or a qelems.
Here are the requirements :
- output the value as soon as possible
- output one value per signal block

Here is what I would like to do :
- in the perform() function I call ComputeBlock()
- then in the perform fonction I would like to call a ReadAndPost() function that have to be executed out of the perform thread
- This ReadAndPost() function will read the result in memory and post it through the object outlet

Can you give the clues so I can write it the better way?

thx you very much.

(And Long Live Live For Max!)


January 26, 2009 | 11:29 am

As I recall, post() defers, so there’s nothing to stop you from calling post() directly from within your Perform method.

But have you understood what this means? At 44kHz and a typical vector size of, say, 512 samples, that would have you posting every 10ms. Who’s supposed to read at that speed? Never mind that even with modern processors, the Max window is not likely to keep up and will skip lines of text. In Max 4 the Max Window had a buffer of 32kB, which it’ll fill up in a couple of seconds. Try it and you’ll see what I mean.

There are alternative strategies you could use. I’ve just been called away but I’ll get back to you.


January 26, 2009 | 3:25 pm

I’m sorry, the mistake comes from me. I don’t want to post() anything, I want to outlet control value from the perform function.

The goal of my object is the implement an algorithm which extract a feature (like RMS energy) from the signal, and output it through a control outlet.

For now I’m still debugging the code so I don’t know if it’s working well. Here my code :

t_int *myobject_perform(t_int *w)
{
[some code...]

defer((t_pxobject *)oMyObject, (method)myObject_readAndOutput, NULL, 0, NULL);

}

void myObject_readAndOutput(t_myobject *oMyObject, t_symbol *s, long argc, t_atom *argv)
{
[some code to read the value of the feature]
outlet_float(oMyObject->energy,fRms);
}

Is it the proper way to do it?
Thx


January 26, 2009 | 11:05 pm

I know it’s only an example but you probably don’t need to know the "RMS energy" every 10ms either (or whatever this period is according to the user’s vector size). I think it would be better to accumulate and/or interpolate the data and output it at some other, controllable rate (like meter~ does for example).


January 27, 2009 | 10:11 am

Thanks for your answer, I understand your point.

But I still don’t have an answer to my question : how to output as fast as I can the result of a calculation from a perform function?

Let’s say it’s for a research purpose, and I really really really want to get one result per computed vector.

At the end I have mecanisme to output only the answer when it’s the right time. But I don’t want Max to do it, I just want max to output the value as fast as he can.


January 27, 2009 | 10:40 am

Quote: brunal2496 wrote on Tue, 27 January 2009 03:11
—————————————————-
> Thanks for your answer, I understand your point.
>
> But I still don’t have an answer to my question : how to output as fast as I can the result of a calculation from a perform function?
>
> Let’s say it’s for a research purpose, and I really really really want to get one result per computed vector.
>

I have recently done exactly this thing for a very similar reason (computing audio features/descriptors) – I used a clock. I think this will be the fastest way – and the speeds I am seeing reflect the hopsize (as expected) when the vector size is low enough.

I call the clock with delay 0 from the perform routine. As I understand it the clock is serviced in the scheduler thread, and hence this method is thread safe. I also prefer it to the approach of calling a clock every n milliseconds and checking if there is a new value, because as I understand it it will result in an output every time you have anew value, even if the timing between max/audio thread slips to some degree.

Although I have never implemented a method using defer or quelems, my understanding of these methods is that they could (or possibly even would) result in the output of the object being in a lower priority scheduler thread. Clocks are high priority I think (as metro I’m sure runs high priority) and for me outputting at high priority is important.

Either way – you can use timer (or better the cputimer patch in the cpuclock help file) to time the interval between outputs of your object to see if it conforms to what you are expecting.

In relation to your project as a whole – are you actually implementing RMS energy, or was that an example? It may be that there is an overlap with fairly extensive work that I have almost completed.

Regards,

Alex


January 27, 2009 | 5:37 pm

One simple alternative would be to call your ComputeBlock() at the beginning of your perform method and fill a DSP vector with the result. In your Max patch you could connect the output to a capture~ object of sufficient size. If necessary, massage the data with a regex-capable text editor after it’s been collected.

Clocks would be, of course, another way to go. Possibly the most appropriate for what you say you want to do.

Finally, a standard way to move between the MSP and Max message domains is to store the result of your ComputeBlock() function in a member in your object. Respond to bang messages (for instance) by sending the member’s stored value out a normal outlet. Set up a metro in your patch that bangs at an appropriate rate. With scheduler in interrupt you should get a decent synchronization with the audio rates.

The last idea is not perfect for your stated goals, but it’s easy to implement and will serve for many purposes.

HtH and never forget to think laterally!


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