[chuck-users] OSC string concatenation bug

Kyle Hipke kwhipke1 at gmail.com
Thu Jul 7 13:58:56 EDT 2011


I'm writing a program that talks with Wekinator, but I'm having a problem
with sending the feature names over OSC that I'm fairly certain is a problem
with chuck.

At the bottom of the code (see bottom of email) is the relevant method,
sendOscFeatureNames().  When I run wekinator and get to the training screen,
I run this code.  The instant it sends the feature names to Wekinator (i.e.,
the instant it is run), an exception gets raised:

"
Exception in thread "Thread-4" java.lang.ArrayIndexOutOfBoundsException:
1536
        at
com.illposed.osc.utility.OSCByteArrayToJavaConverter.lengthOfCurrentS
tring(Unknown Source)
        at
com.illposed.osc.utility.OSCByteArrayToJavaConverter.readString(Unkno
wn Source)
        at
com.illposed.osc.utility.OSCByteArrayToJavaConverter.readArgument(Unk
nown Source)
        at
com.illposed.osc.utility.OSCByteArrayToJavaConverter.convertMessage(U
nknown Source)
        at
com.illposed.osc.utility.OSCByteArrayToJavaConverter.convert(Unknown
Source)
        at com.illposed.osc.OSCPortIn.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
"

This exception is not thrown when I replace numDataPoints[i] with a constant
(like 5).

Here is the entire .ck file.  You can use it just like you would any OSC
feature extractor with Wekinator.

//Extracts the following for different numDataPoints
//0 - centroidAvg
//1 - centroidStdDev
//2 - centroidMin
//3 - centroidMax
//4 - rmsAvg
//5 - rmsStdDev
//6 - rmsMin
//7 - rmsMax
//8 - fft bin with highest fval (highest over all windows)
//...
//whenever an amplitude > threshold is detected from input, computed over
//numDataPoints 128-sample ffts that overlap by 64-samples
//
"127.0.0.1" => string hostname;
OscSend xmit;
xmit.setHost( hostname, 6448 );
OscSend xmit2;
xmit2.setHost( hostname, 6448 );

//Custom objects
adc => FFT f =^ RMS rms => blackhole;
f =^ Centroid centroid => blackhole;
f =^ Flux flux => blackhole;
f =^ RollOff rolloff => blackhole;
UAnaBlob b;

//for storing the results from each window
float rmsArr[50];
float cent[50];
float highestFFTBin[50]; //bin with highest fft fval
float highestFFTVal[50]; //the actual value of the bin

//Set up bin stuff
128 => int FFT_SIZE;
FFT_SIZE => f.size;
Windowing.hamming(64) => f.window;

1::second / 1::samp => float SR;
SR/FFT_SIZE => float bin_width;

//constants
.5 => float threshold;
0 => int peakDetected; //flag if peak has been detected
now => time lastPeakTime;
100::samp => dur peakWindow;
10::samp => dur peakPollRate;
[1,5,10,15,20,25,30,35,40,45,50] @=> int numDataPoints[]; //list of
numDataPoints values to try
1 => float rmsMultiplier; //so it isn't out of wek's range (this actually
doesn't matter, leave it at 1)

0 => int currentlyAnalyzing; //flag if currently analyzing i.e. don't detect
peak

//Run the peak detector in parallel to set the peakDetected flag
spork ~peakDetector();
spork ~sendOscFeatureNames();

//Extract features and send via osc when peak detected.
while (true) {
    if (peakDetected) {
        <<<"Peak detected! Analyzing">>>;
        analyzeAndSend();
    }
    .1::second => now;
}

//When peak detected, compute min, max, avg, and std. dev for centroid and
rms
//and send
fun void analyzeAndSend() {
    1 => currentlyAnalyzing;
    xmit.startMsg( "/oscCustomFeatures",
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
    //Get all float and rms values for the maximum numDataPoints
    getRmsCentroidAndFFT();

    for (0 => int i; i < 11; i++) {
        analyzeNumDataPoints(numDataPoints[i]) @=> float result[];
        for (0 => int j; j < 9; j++) {
            result[j] => xmit.addFloat;
        }
    }
    <<<"done">>>;
    0 => currentlyAnalyzing;
}

//populates rms, cent, and fft arrays
fun void getRmsCentroidAndFFT() {
    50 => int maxDataPoints;

    128::samp => now;
    rms.upchuck();

    for (0 => int i; i < maxDataPoints; 1 +=> i) {
        rms.fval(0) => rmsArr[i];
        centroid.upchuck();
        centroid.fval(0) => cent[i];

        0 => float highestBinMagnitude;
        0 => int highestBin;
        f.upchuck();
         //find highest bin
        for (1 => int j; j < FFT_SIZE; j++) {
            if (f.fval(j) > highestBinMagnitude) {
                f.fval(j) => highestBinMagnitude;
                j => highestBin;
            }
        }
        highestBin => highestFFTBin[i];
        highestBinMagnitude => highestFFTVal[i];

    }
}

//Analyze data using the specified number of data points, return the float
array corresponding to
//the osc message format described at top
//requires that the arrays have been populated
fun float[] analyzeNumDataPoints(int numDataPoints) {
    float centroidTotal;
    float centroidMin;
    float centroidMax;
    float centroidStdDev;
    float rmsTotal;
    float rmsMin;
    float rmsMax;
    float rmsStdDev;
    float highestBin;
    float highestBinMagnitude;
    new float[numDataPoints] @=> float centroidData[];
    new float[numDataPoints] @=> float rmsData[];

    //get 1st centroid and rms

    rmsArr[0] +=> rmsTotal;
    rmsArr[0] => rmsMin => rmsMax => rmsData[0];
    cent[0] +=> centroidTotal;
    cent[0] => centroidMin => centroidMax => centroidData[0];
    //do rest
    for (1 => int i; i < numDataPoints; i++) {
        rmsArr[i] +=> rmsTotal;
        Math.max( rmsArr[i], rmsMax ) => rmsMax;
        Math.min( rmsArr[i], rmsMin ) => rmsMin;
        rmsArr[i] => rmsData[i];
        cent[i] +=> centroidTotal;
        Math.max( cent[i], centroidMax ) => centroidMax;
        Math.min( cent[i], centroidMin ) => centroidMin;
        cent[i] => centroidData[i];

        //compute current highestBin
        if (highestFFTVal[i] > highestBinMagnitude) {
            highestFFTVal[i] => highestBinMagnitude;
            highestFFTBin[i] => highestBin;
        }
    }
    //calculate
    rmsTotal / numDataPoints => float rmsAvg;
    centroidTotal / numDataPoints => float centroidAvg;
    //get std dev
    float rmsDevSquaredTotal;
    float centroidDevSquaredTotal;
    for (0 => int i; i < numDataPoints; i++) {
        (rmsData[i] - rmsAvg)*(rmsData[i] - rmsAvg) +=> rmsDevSquaredTotal;
        (centroidData[i] - centroidAvg)*(centroidData[i] - centroidAvg) +=>
centroidDevSquaredTotal;
    }
    Math.sqrt(rmsDevSquaredTotal / numDataPoints) => rmsStdDev;
    Math.sqrt(centroidDevSquaredTotal / numDataPoints) => centroidStdDev;

    float result[9];

centroidAvg => result[0];
    centroidStdDev => result[1];
    centroidMin => result[2];
    centroidMax => result[3];
    rmsAvg * rmsMultiplier => result[4];
    rmsStdDev * rmsMultiplier => result[5];
    rmsMin * rmsMultiplier => result[6];
    rmsMax * rmsMultiplier => result[7];
    highestBin => result[8];

    return result;
}

//Pretty inefficient but does the trick
//Looks for a peak in the last peakWindow
fun void peakDetector() {
while (true){
if (adc.last() > threshold || adc.last() < -1 * threshold) {
1 => peakDetected; // analyze
now => lastPeakTime;
 } else if (now > lastPeakTime + peakWindow) {
0 => peakDetected;
}

        peakPollRate => now; //This is silly; would be better do do a
low-pass filter envelope and look for peaks there. But don't worry about it
right now.

}

}

//run in parallel to send osc feature names
fun void sendOscFeatureNames() {
    while (true) {
        xmit2.startMsg( "/oscCustomFeaturesNames
sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss");
        for (0 => int i; i < 11; i++) {
            numDataPoints[i] => int n;
            xmit2.addString(n + "centroidAvg");
            xmit2.addString(n + "centroidStdDev");
            xmit2.addString(n + "centroidMin");
            xmit2.addString(n + "centroidMax");
            xmit2.addString(n + "rmsAvg");
            xmit2.addString(n + "rmsStdDev");
            xmit2.addString(n + "rmsMin");
            xmit2.addString(n + "rmsMax");
            xmit2.addString(n + "highestFFT");
        }
        .1::second => now;
    }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cs.princeton.edu/pipermail/chuck-users/attachments/20110707/b5d2ecdf/attachment.htm>


More information about the chuck-users mailing list