SuperCollider CLASSES (extension)

Chromagram

Octave chroma band based representation of energy in a signal; Chromagram for nTET tuning systems with any base reference
    

Description

A chromagram, measuring the energy at particular chroma within an nTET tuning system.

Possible extension: TODO: Could have arbitrary tuning systems if precalculated the exact fft bin + interpolation data.

Class Methods

*kr (fft, fftsize: 2048, n: 12, tuningbase: 32.703195662575, octaves: 8, integrationflag: 0, coeff: 0.9, octaveratio: 2, perframenormalize: 0)

Arguments:

fft

input fft chain, that is, from an FFT UGen

fftsize

FFT size, required for initialisation

n

Equal divisions of an octave, e.g. n=12 is 12TET, 12 steps in an octave

tuningbase

Base frequency or tuning; will correspong to index 0 in results (conventionally, this would be a 'C' in 12TET, but its an arbitrary reference)

octaves

Number of octaves considered from tuning base up

integrationflag

Whether to integrate from frame to frame, off by default

coeff

Coefficient of integration

octaveratio

Default of 2 is a 'normal' octave; other ratios are possible, e.g. Bohlen-Pierce scale uses 13 equal divisions over the ratio of 3 for a 'tritave'

perframenormalize

Defaults to off, but if set to 1 will normalize each frame with respect to itself (as long as there is non-negligible power), potentially providing a more robust measure for comparison between frames (each frame will have then a normalized distribution over chroma, independent of volume)

Inherited class methods

Instance Methods

Inherited instance methods

Examples

(
{

var in, fft, chroma;

//in = SinOsc.ar(440,0,0.1);
in= SoundIn.ar;

fft = FFT(LocalBuf(2048), in);

chroma=Chromagram.kr(fft);

chroma.poll;

Out.ar(0,Pan2.ar(in));
}.play
)



//n TET display

n= 12; //19, 24

(
x = {

var in, fft, chroma;

//in = SinOsc.ar(440,0,0.1);
in= SoundIn.ar;

fft = FFT(LocalBuf(2048), in);

chroma=Chromagram.kr(fft, 2048, n);

//chroma=Chromagram.kr(fft, 2048, n, 36.midicps, 7, 1, 0.9);

Out.kr(0,chroma);
}.play;

c= Bus.new('control', 0, n);

)



//poll coefficients snapshot
c.getn(n,{arg val; {val.plot;}.defer});



//Continuous graphical display of Chromagram values; free routine before closing window

(
var ms;

w=Window.new((n.asString)++" chroma coefficients", Rect(200,400,n*20+50,300));

ms= MultiSliderView.new(w, Rect(10,10,n*20,280));

ms.value_(Array.fill(n,0.0));
ms.valueThumbSize_(20.0);
ms.indexThumbSize_(20.0);
ms.gap_(0);

w.front;

r= {

inf.do{

c.getn(n,{arg val; {ms.value_(val)}.defer});

0.04.wait; //25 frames per second
};

}.fork;

w.onClose = {
r.stop;
c.free;
x.free;
};

)



b.free;



//Bohlen-Pierce over 3 tritaves, normalized results per frame
(
{

var in, fft, chroma;

//in = SinOsc.ar(440,0,0.1);
in= SoundIn.ar;

fft = FFT(LocalBuf(2048), in);

chroma=Chromagram.kr(fft,2048,13,octaves:3,octaveratio:3,perframenormalize:1);

chroma.poll;

Out.ar(0,Pan2.ar(in));
}.play
)