[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 >> |