[Csnd] Csound Java API: input with setChannel() not matching getChannel() output
Date | 2010-08-27 18:28 |
From | Jacob Joaquin |
Subject | [Csnd] Csound Java API: input with setChannel() not matching getChannel() output |
Hello everyone, I've written a Processing/Csoundo sketch to test creating, reading and writing from a table using CsoundPerformanceThread. I'm intentionally running a lot of number through to test the load on the system, and my results shows the input doesn't match the output roughly 2% - 3% of the time. I'm using CsoundPerformanceThread which supposedly protects memory and mutex locks thing down automatically. Though CsoundPerformanceThread has the method inputMessage(), it doesn't have methods for reading and writing tables directly. Which I'm guessing means that they are not thread safe. I have tried using mutex. Though the mutex used by CsoundPerformanceThread (* queueLock) is private according to the API. Since I haven't found a way to get that one, I created my own mutex with csnd.csoundCreateMutex(1) and tried wrapping Csoundo's table access methods like this: mutex.lock(); csound.TableSet(t, i, v); mutex.unlock(); I'm unsure this is even the proper way to use mutex. Enabling/disabling my implementation of mutex seems to have zero affect on the outcome. I've posted the main loop from my sketch towards the bottom. In a nutshell, this is what happens. Every time draw() is called, a zero-d f-table is generated. Then for each index in the f-table, the following happens: 1) A sine wave point is created. 2) The point is written to the current index of the f-table with cs.tableSet() 3) The value is then read from the f-table with cs.tableGet() 4) If the input != the output, an error message is printed. Most often, the output is 0.0, which indicates that setChn() was not called by the time getChn() grabbed its value from the f-table. Example: 0.0 != -0.5027427 @index 3825 5) Display the table, to look for the errors visually. Example: http://www.thumbuki.com/temp/CsoundoSetGetTableError.jpg Here's a key to my Csoundo methods: cs.event() calls CsoundPerformanceThead.inputMessage() cs.tableLength() csound.TableLength(); cs.tableGet() calls csound.TableGet(); cs.tableSet() calls csound.TableSet(); mutex.lock() calls csnd.csoundLockMutex(); mutex.unlock() calls csnd.csoundUnlockMutex(); Here's the code: void draw() { noStroke(); fill(0, 8); rect(0, 0, width, height); // Create empty table float size = pow(2, 12); cs.event("f 20 0 " + size + " 10 0"); int length = cs.tableLength(20); // Increment phase of sine table input int inc = 60; float phase = (float) (frameCount % inc) / inc * TWO_PI; // Create, write, read and draw sine waveform stroke(255, 255); beginShape(); for (int i = length - 1; i >= 0; i--) { // Generate sine data point and input into table float input = sin(TWO_PI * (float) i / (float) length + phase); cs.tableSet(20, length, input); // Read the from the table at the same index float output = cs.tableGet(20, length); // Print message if input != output if (output != input) { println(output + " != " + input + " @index " + i); bugs++; println("fail rate = " + ((float) bugs / (float) frameCount)); } // Draw wave form vertex((float) i / (float) (length - 1) * (float) width, height / 2.0 + height / 2.0 * output); } endShape(); } So I guess my question is, does this mean I have to abandon CsoundPerformanceThread in favor of csound.csoundPerformKsmps()? Or am I just completely botching this in my code? Really, anything any of you have to say would help. Best, Jake |
Date | 2010-08-27 18:52 |
From | jean-pierre lemoine |
Subject | [Csnd] Re: Csound Java API: input with setChannel() not matching getChannel() output |
Hello Jacob I think that if you want to protect csound execution fron any changes (change table, channel), and that these changes are not available as input message for CsoundPerformanceThread, you have to do what CsoundPerformanceThread does in the Perform method. Recreate it in Java this class, and extend the message system with new java classes for table and channels. I think also there is a mutex class in Java (java.util.concurrent) to help this tricky subject of thread synchronization. jp On Fri, Aug 27, 2010 at 7:28 PM, Jacob Joaquin |
Date | 2010-08-27 19:01 |
From | Victor Lazzarini |
Subject | [Csnd] Re: Re: Csound Java API: input with setChannel() not matching getChannel() output |
The main thing that you need to achieve is that the table access does not happen at the same time as PerformKsmps(). CsoundPerformanceThread() will call PerformKsmps() in a loop in its performance thread. It also calls a Performance callback. So you can use the Performance callback to call any functions that might not be called at the same time, or to implement your locks. The way it looks, your mutex are not protecting anything, because CsoundPerformanceThread just ignores it. I need to have a look at your situation a bit more closely for a more detailed diagnosis, but that looks like the case to me. Victor On 27 Aug 2010, at 18:52, jean-pierre lemoine wrote: > Hello Jacob > > I think that if you want to protect csound execution fron any changes > (change table, channel), and that these changes are not available as > input message for CsoundPerformanceThread, you have to do what > CsoundPerformanceThread does in the Perform method. > > Recreate it in Java this class, and extend the message system with new > java classes for table and channels. > > I think also there is a mutex class in Java (java.util.concurrent) to > help this tricky subject of thread synchronization. > > jp > > On Fri, Aug 27, 2010 at 7:28 PM, Jacob Joaquin > |
Date | 2010-08-28 00:40 |
From | Jacob Joaquin |
Subject | [Csnd] Re: Re: Re: Csound Java API: input with setChannel() not matching getChannel() output |
On Fri, Aug 27, 2010 at 11:01 AM, Victor Lazzarini |
Date | 2010-08-28 10:30 |
From | Victor Lazzarini |
Subject | [Csnd] Re: Re: Re: Re: Csound Java API: input with setChannel() not matching getChannel() output |
There is a helper class that should do the trick: CsoundCallbackWrapper, using directors. I am not sure how to use it, but it might be starting point for you. If you get it working, then you can basically do this: 1. Implement a function to get the table data into a list, protected by mutex. 2. In the performance callback read this list and call the csound table functions, protected by mutex This is similar to how CsoundPerformanceThread treats events. Victor On 28 Aug 2010, at 00:40, Jacob Joaquin wrote: > On Fri, Aug 27, 2010 at 11:01 AM, Victor Lazzarini > |
Date | 2010-08-28 10:56 |
From | Victor Lazzarini |
Subject | [Csnd] Re: Re: Re: Re: Re: Csound Java API: input with setChannel() not matching getChannel() output |
I don't know the Java syntax for this, but by looking at the C++ source I reckon what you have to do is: 1. Derive a class from CsoundCallbackWrapper 2. Implement one or more of the functions, which will be your callbacks Here you'll be looking to implement the CsoundCallbackWrapper::YieldCallback(), which is similar placed to PerformanceCallback, but instead of called by CsoundPerformanceClass, it is called by PerformKsmps() at ksmp boundaries. 3. Instantiate the object, pass it a Csound object. 4. Call its SetYieldCallback() method This should be all you need to do. Any " host data" your callback needs might be placed as class members to your derived class; you will not be able to use 'csoundHostData' to hold host data, because this mechanism already uses it to pass the callback wrapper class object to Csound. But you can just add any host data to your callback wrapper class. This is absolutely untested, since I really know no Java and for Python, which I use, I have wrapped things differently in the swig interface. Victor On 28 Aug 2010, at 10:30, Victor Lazzarini wrote: > There is a helper class that should do the trick: > CsoundCallbackWrapper, using directors. I am not sure how to use it, > but it > might be starting point for you. > > If you get it working, then you can basically do this: > > 1. Implement a function to get the table data into a list, protected > by mutex. > 2. In the performance callback read this list and call the csound > table functions, protected by mutex > > This is similar to how CsoundPerformanceThread treats events. > > Victor > > > On 28 Aug 2010, at 00:40, Jacob Joaquin wrote: > >> On Fri, Aug 27, 2010 at 11:01 AM, Victor Lazzarini >> |
Date | 2010-08-28 11:07 |
From | Victor Lazzarini |
Subject | [Csnd] Re: Re: Re: Re: Re: Re: Csound Java API: input with setChannel() not matching getChannel() output |
Further info: http://www.swig.org/Doc1.3/Java.html#java_directors_classes On 28 Aug 2010, at 10:56, Victor Lazzarini wrote: > I don't know the Java syntax for this, but by looking at the C++ > source I reckon what you have to do is: > > 1. Derive a class from CsoundCallbackWrapper > 2. Implement one or more of the functions, which will be your > callbacks > Here you'll be looking to implement the > CsoundCallbackWrapper::YieldCallback(), which is similar placed to > PerformanceCallback, but > instead of called by CsoundPerformanceClass, it is called by > PerformKsmps() at ksmp boundaries. > 3. Instantiate the object, pass it a Csound object. > 4. Call its SetYieldCallback() method > > This should be all you need to do. Any " host data" your callback > needs might be placed as class members to your derived class; you > will not > be able to use 'csoundHostData' to hold host data, because this > mechanism already uses it to pass the callback wrapper class object > to Csound. > But you can just add any host data to your callback wrapper class. > > This is absolutely untested, since I really know no Java and for > Python, which I use, I have wrapped things differently in the swig > interface. > > Victor > > On 28 Aug 2010, at 10:30, Victor Lazzarini wrote: > >> There is a helper class that should do the trick: >> CsoundCallbackWrapper, using directors. I am not sure how to use >> it, but it >> might be starting point for you. >> >> If you get it working, then you can basically do this: >> >> 1. Implement a function to get the table data into a list, >> protected by mutex. >> 2. In the performance callback read this list and call the csound >> table functions, protected by mutex >> >> This is similar to how CsoundPerformanceThread treats events. >> >> Victor >> >> >> On 28 Aug 2010, at 00:40, Jacob Joaquin wrote: >> >>> On Fri, Aug 27, 2010 at 11:01 AM, Victor Lazzarini >>> |
Date | 2010-08-28 11:15 |
From | Andres Cabrera |
Subject | [Csnd] Re: Re: Re: Re: Re: Re: Re: Csound Java API: input with setChannel() not matching getChannel() output |
But in any case for most applications the simplest way is just to register a callback for the CsPerformanceThread. This callback is called whenever a performKsmps finishes and is waited for before calling another performKsmps. But I'm not sure if this is also available for java... Cheers, Andres On Sat, Aug 28, 2010 at 11:07 AM, Victor Lazzarini |
Date | 2010-08-28 16:28 |
From | Victor Lazzarini |
Subject | [Csnd] Re: Re: Re: Re: Re: Re: Re: Re: Csound Java API: input with setChannel() not matching getChannel() output |
The problem is registering the callback. The mechanism allows only Csound class callbacks. Victor On 28 Aug 2010, at 11:15, Andres Cabrera wrote: > But in any case for most applications the simplest way is just to > register a callback for the CsPerformanceThread. This callback is > called whenever a performKsmps finishes and is waited for before > calling another performKsmps. But I'm not sure if this is also > available for java... > > Cheers, > Andres > > On Sat, Aug 28, 2010 at 11:07 AM, Victor Lazzarini > |
Date | 2010-08-28 16:32 |
From | Victor Lazzarini |
Subject | [Csnd] Re: Re: Re: Re: Re: Re: Re: Re: Re: Csound Java API: input with setChannel() not matching getChannel() output |
In Java, I mean. For Python, I've wrapped it conveniently for Python functions. Vicror On 28 Aug 2010, at 16:28, Victor Lazzarini wrote: > The problem is registering the callback. The mechanism allows only > Csound class callbacks. > > Victor > On 28 Aug 2010, at 11:15, Andres Cabrera wrote: > >> But in any case for most applications the simplest way is just to >> register a callback for the CsPerformanceThread. This callback is >> called whenever a performKsmps finishes and is waited for before >> calling another performKsmps. But I'm not sure if this is also >> available for java... >> >> Cheers, >> Andres >> >> On Sat, Aug 28, 2010 at 11:07 AM, Victor Lazzarini >> |