Make Uzi work like Metro
Hi,
Trying to get Uzi working like Metro, so that Uzi will keep banging for a specified amount of time (start/stop) rather than for a number of bangs.
I can't seem to get it working though. I just want to get the counter object to keep counting until the uzi has finished (ie after 2 seconds delay).
Here's the patch Im using:
I get a stackoverflow, but I'm not sure where it's coming from.
Seems Uzi isnt working quite as expected. This patch seems correct, but it causes a stackoverflow for some reason. I doesn't stackoverflow if I use a deferlow, but I need this to be as fast as possible.
In general, you may not feed an object back into itself to retrigger itself. This causes "stack overflow" because the object is, in effect, adding to Max's stack of things to do recursively and infinitely. By sending the output of uzi back into its own input (even if passing through a gate), you're establishing a recursive loop that prevents Max from doing anything other than adding more tasks to the stack. So, avoid recursion.
You might think that, after two seconds the gate would close and all would be well, but the scheduled 'bang' (to close the gate) never is given a chance to execute because, as it were, time is never being allowed to progress because the infinite recursion locks Max into an endless loop of immediate tasks.
The uzi object is useful for when you want to accomplish a finite number of tasks literally as fast as possible, as fast as the computer is able to accomplish them, all "immediately" as far as the scheduler is concerned. Since in practice "as fast as possible" is less than one microsecond (my aging MacBook Pro appears to take about 60 nanoseconds per uzi output), what useful information would you hope to see in the Max window after Max tried to count as fast as possible for two seconds?
So, in practice, you can either try to do things as fast as possible (if that's really what you want), or you can schedule them to happen at a particular known rate, with something like a metro object. You wrote initially that you are "trying to get Uzi working like Metro," so why not just use a metro?
Hi Christopher,
Thanks. What I'm trying to achieve is to read a file byte by byte using the filein object into a byte array. The problem is that filein needs to be queried for each byte, (there is no way of dumping out all bytes at once), so I have to query byte 1,2,3 etc.
So, I can then use an Uzi index to count into the filein object, but I don't know the total number of bytes in the file, because filein doesn't give this, so I don't know how much to give the Uzi count so that it finishes on time.
I realise I can do this easily in js but it's not fast enough. I'm starting to think of taking the only way is to take it into the java world
if you have the spat library from ircam, there is a spat.fileinfo which give sthe size in bytes of any file. I'm surprised it doesn't exist in Max though. If you feel confident and using osx, you could try a solution using shell - surely there is a command that gives the size of a file ? Other than that i'm sure there must be a way with native max to get the size of a file... maybe force it into a buffer~ or sfplay~ then get size infos ? maybe it's easy in javascript to just get the size of a file, then use filein to read it ?
You can use the filein object to read bytes. It generates a bang from the middle outlet when the end of the file is reached, so you can send a break message to the uzi from that.
Oh well, file in is not even allowing me to run a 500,000 byte file through uzi. Totally locks everything up, so no go anyway. I guess it's java time now :)
unlike metro, uzi can not be told to run for a specific amount of time, because you can not know in advance how fast it can output data.
yet you could just use a del and a gate to turn its output off.
well that's to be expected. You could read perhaps 500 bytes at a time and trigger it with a metro, which would take 1 seconds for half a million messages at a 1 ms scheduler rate. You are not going to get better performance in max as it is an interpretative language. but if you load the data into buffer~, you could process it at audio rate.
I've now taken this out to Java, and I'm getting my byte array into Max just fine, but when I try to store it with a dict I lose all the data.
In order to store it I have to "prepend set mydictkey". It is at this point that I lose all the data, if the file size (byte array list ) is large. If the file size is small it works just fine. I'm guessing I'm hitting a limit somewhere... I have no way of telling where though, because max either doesnt send any data at all, or just crashes the patch (if I try to break up the byte array into more manageable chunks usin zl delace)
I'm starting to think that this is impossible without a c external, interfacing with dict directly, since java has no access to dict.
What exactly are you trying to do? Load a large binary file, byte-wise, into a dictionary?
Hi Mzed,
Yep, that's it. I'm trying to load the byte array into a dictionary, but as soon as I put the byte array list into a max object (such as [prepend]), it goes over the maximum limit and I lose all the data. I should add that this is not a huge file, it's 0.5mb in size.
This seems to work, but it's quite slow. I didn't stick around to test any reasonable memory limit.
I think Javascript might be the next best option.
Why does this need to be in a dictionary? You could use "spool" and filein and read the bytes directly from disk as needed.
javascript is still really slow, because you have to still loop over every byte, with a function such as this:
function readbytes(s)
{
var f = new File(s);
var i,a,c;
if (f.isopen) {
c = f.eof;
for (i=0;i
a = f.readbytes(1); //
post("byte_count[" + f.position + "]: " + a + "n");
}
f.close();
} else {
post("could not open file: " + s + "n");
}
}
With java, I get the byte array instantly. I just cant do anything with it in Max... Maybe the best way is just to overwrite the dict file on disk???