SuperCollider CLASSES (extension)

KMeansRT
ExtensionExtension

k-means classification in real time
Inherits from: UGen : AbstractFunction : Object

Description

Performs online k-means classification, classifying each datapoint that comes in and updating the k-means centroids.

The method is described in Algorithm B.1 of Brian McFee's 2012 thesis (http://cseweb.ucsd.edu/~bmcfee/papers/bmcfee_dissertation.pdf ). McFee calls it "online Hartigan k-means".

Class Methods

*kr (bufnum, inputdata, k: 5, gate: 1, reset: 0, learn: 1)

Arguments:

bufnum

a Buffer with "k" frames and "d + 1" channels (where d is the number of dimensions of input data. Each frame of the Buffer will hold data for a centroid (the centroid location, plus the final channel holds the effective number of points associated with the centroid).

inputdata

An array representing the input point. Num channels must match the dimensionality of the points in the dataset.

k

k is the number of centroids.

gate

The unit is active while gate > 0. While <=0, no search is performed and output is held steady

reset

If reset is greater than 0, the "flexibility" of the centroids is reset back to initial values (as if no data had been received).

learn

Controls whether the unit is learning from its input. If you set this to zero it will not learn, but will still output decisions. This is useful for applying a previously-learned clusterer without modifying it. This argument cannot be modulated: each time you use KMeansRT it is either learning from scratch, or using a fixed pre-learnt buffer.

Returns:

the cluster index with which the input datapoint has been associated.

*getCentroid (bufnum, classif, ndims)

A convenience method (just a wrapper round BufRd really) that lets you access the centroid location, given a cluster index.

Arguments:

bufnum

the same buffer as is passed to .kr

classif

the classification index, i.e. the output from .kr

ndims

the number of dimensions ("d" in the above description)

Returns:

the "d"-dimensional current location of the centroid corresponding to index "classif".

Inherited class methods

Instance Methods

Inherited instance methods

Examples

This example clusters every frame of a sound sample, using the spectral centroid of each frame, and sonifies the result:

s.boot;
k = 5;
~ndims = 1;
b = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");
~kbuf = Buffer.alloc(s, k, ~ndims+1)

(
x = {
    var sig, chain, chaintrig, features, kbuf, classif, centroid, resynth;

    // sig = AudioIn.ar;
    sig = PlayBuf.ar(1, b, loop: 1);
    chain = FFT(LocalBuf(512), sig);
    chaintrig = chain > -0.001;

    features = [SpecCentroid.kr(chain)]; // just one 1D feature here
    classif = KMeansRT.kr(~kbuf, features, k, chaintrig);
    classif.poll(chaintrig);

    // Now we read the centroid position back out of the buffer and sonify
    centroid = KMeansRT.getCentroid(~kbuf, classif, ~ndims).at(0);

    resynth = SinOsc.ar(centroid, 0, 0.1);
    [sig, resynth]
}.play
)

x.free

This example clusters onsets:

s.boot;
k = 5;
~ndims = 1;
// Specify a stereo music recording you have locally.
b = Buffer.cueSoundFile(s, "~/back_to_black.wav".standardizePath, 0, 2);
~kbuf = Buffer.alloc(s, k, ~ndims+1)

(
x = {
    var sig, chain, trig, features, kbuf, classif, centroid, resynth;

    sig = DiskIn.ar(2, b.bufnum);

    chain = FFT(LocalBuf(1024), sig.mean);
    trig = Onsets.kr(chain);

    features = [SpecCentroid.kr(chain)]; // just one 1D feature here
    classif = KMeansRT.kr(~kbuf, features, k, trig);
    classif.poll(trig);

    resynth = Pulse.ar(classif.linexp(0, k, 100, 1000)) * 0.9 * EnvGen.ar(Env.perc, trig);
    sig + resynth
}.play
)

x.free;
b.close; b.free;