PitchCircle visual representation of cycle of fifths sets


PitchCircle is intended to provide a visual representation of 12-tone equal temperament C7 segments and subsets, entered as arrays of integers. It is not intended to provide pitch-class operations (other than a simple complementation method). Note that microtonal representations are possible, but do not work with many instance methods. See the example at the end of the file.


 

Creation / Class Methods


*new (steps, tonic, mod, offset, drawints, size, win, num)


steps - number of steps in circle. Default value is 12.

tonic - as an integer, default value is 0 ("C major" collection) if number of steps is 7.

mod - circle generator, either scalic/chromatic (1),  circle of 5ths (7), or thirds (3). Default value is 1

offset - rotates the circle in steps. Default value is 0, where the "tonic" is at the 

top of the circle. Positive values rotate anti-clockwise. Negative offset values are valid. 

drawints - boolean as to whether to display note names or pc integers. 

Default value is false. Note that PitchCircle may not provide correct 

diatonic note spellings for complex keys (or natural minor modes). See spell method for adjusting spellings.

size - window size in pixels if a window is not passed in. Default value is 300.

win - a window can be passed in, default is a new window. PitchCircle expects win to have a  FlowLayout decorator for positioning.

num - an Integer. Default is 1; the number of PitchCircles in the default window.


// example

p = PitchCircle.new(num: 2);

u = PitchCircle.new(win: p.win);

p.drawSet;

u.dotsColFn = { Color.red }; 

u.drawSet(p.complement)

p.close;


Instance variables

set_(aSet) 

set

set or access the primary pc array for display. Its type is an Array, but Sets can be used. Can be bypassed using the drawSet method. Default is the diatonic set [0, 2, 4, 5, 7, 9, 11], transposed to tonic.


// example

p = PitchCircle.new(7, 2);

p.set // default here is [ 2, 4, 6, 7, 9, 11, 1 ]

p.drawSet;

p.set_([2, 4, 6]); 

p.drawSet;

p.close;

dotsColFn_(aFunction)

dotsColFn

set or access the function that determines the color for the display dots. 

The function is passed in the set as an argument when evaluated upon drawing the set.

The default function is { Color.blue }. 

Takes effect when circle is next drawn.

// example

p = PitchCircle.new;

p.dotsColFn = {|set| if(set.size<4, {Color.red}, {Color.green})};

p.set_([2, 4, 6]); 

p.drawSet;

p.drawSet([2, 4, 6, 7, 8]);

p.close;



drawInts_(boolean)

drawInts

see the corresponding argument in *new.  Takes effect when circle is next drawn.


hlDots_(dots)

hlDots

set or return the current dots Array. A dot will have an extra circle around if if is included in set.  Default is nil.

lines_(boolean)

lines

toggle between drawing lines between pc elements. Default is true.

steps

steps_(integer)

see the corresponding argument in *new.  


tonic

tonic_(integer)

see the corresponding argument in *new. Note that if steps is 12, changing the tonic has the effect only of altering the offset, and possibly respelling the note names.

mod_(arg1)

mod

see the corresponding argument in *new. 

offset_(arg1)

offset

see the corresponding argument in *new.  If steps is 12, the clock will rotate so that arg1 is at the top.


labelAlign_(aSymbol)

labelAlign


Sets or returns the label text alignment. Default value is \center.


labelSize_(integer)

labelSize


Sets or returns the label font size. Takes effect when circle is next drawn.



labelAlign_(aSymbol)

labelAlign


Returns or sets the label text alignment. Default value is \center.


// Instance variables example

p = PitchCircle.new(7, 3, 3);

p.drawInts_(true);

p.drawSet;

p.drawInts_(false);

p.offset_(5);

p.set_([10, 2, 5, 8]); 

p.drawSet;

p.drawLabel("Bb Major 7th chord");

p.close;

Instance methods

drawSet (aSet, aLabel, aDotsCol)

aSet - an Array or Set. Default value is the set instance variable.

aLabel - a String. Default value is aSet.

aDotsCol -  Default value is the dotsColFn instance variable

// example

p = PitchCircle.new;

p.set_(Set[ 0, 2, 4, 6, 8, 10 ]);

p.drawSet(aLabel: format("A wholetone scale %", p.set.asArray)) ;

p.close;



note_(note) 

Shortcut for p.set_([note]); p.drawSet.


// example

p = PitchCircle.new(7, 0);

p.note_(0);

p.close;


drawLabel (aString, align)

aString - a String. Default value is aSet.

align -  Default value is the dotsColFn instance variable



spell (pc, noteStr)

pc - an integer, e.g. the pc-name for the note that requires respelling.

noteStr - a String that will replace the curren note name.

NB. Respelling will not survive a change mod,  steps or tonic.

// example

p = PitchCircle.new;

p.set_([2, 4, 5, 7, 9, 10, 1]);

p.drawSet;

p.offset_(2);

p.spell(10, "Bb")

p.drawSet(aLabel: format("D harmonic minor %", p.set.asArray));

p.close;



spellAll (arr)

arr - an Array of pc and note name pairs. See spell method.

NB. Respelling will not survive a change mod,  steps or tonic.

// example

p = PitchCircle.new;

p.set_([8, 10, 11, 1, 3, 5, 7]);

p.drawSet;

p.offset_(8);

p.spellAll([10, "A#", 5, "E#", 7, "F##"]); 

p.close;


setAll (mod, tonic, offset, steps)


Resets arguments. Existing set is preserved and drawn where it is a subset of the new collection, error otherwise.

p = PitchCircle.new;

p.set_([6, 8, 10, 1, 3]);

p.drawSet;

p.setAll(1, 1, 0, 7); // mod, tonic, offset, steps

p.set // => [ 1, 3, 6, 8, 10 ] // same set

p.setAll(1, 0, 0, 7); // error as existing set is not common to new collection

p.set_([2, 4, 5]); // no error

p.drawSet; 

p.close;


drawSets (aSets, aLabel, colsArr)

draws an array or arrays (sets) in different colors.

aSets - an array of Arrays or Sets.

aLabel - default is aSets.

colsArr - an optional Array of colours. 


// example

p = PitchCircle.new;

a = [0, 1, 5];

p.drawSets([a, a+3, a+6]);

p.close;



addSet (aSet, aLabel, aDotsCol)

an alternative to drawSets. Superimposes a second set over the set instance variable.

aSet - an Array or Set.

aDotsCol - default value is Color.green.

// example

p = PitchCircle.new;

p.set_([0, 2, 7]);

p.drawSet(p.set)

p.addSet([4, 5, 6]);

p.close;



addSpacing (num, aDotsCol)

This is designed to be used to demonstrate "maximal evenness" (see the writings of John Clough). 

Like addSet, the result is superimposed over the set instance variable.

num - number of divisions of the circle. Default value is 7.

aDotsCol -  default value is Color.green.

// example

p = PitchCircle.new;

p.set_([10, 0, 2, 5, 7])

p.addSpacing(5);

p.close;


complement (aSet)

returns the complement of an Array or Set.

aSet - set to complement. Default value is the set instance variable.

// example

p = PitchCircle.new;

p.set_([10, 0, 2, 5, 7])

// See post window

p.complement; // => [ 1, 3, 4, 6, 8, 9, 11 ]

p.complement([0, 2, 4, 6, 8, 10]);

p.close;



drawCompl (aDotsCol, aLabel)

A shorthand method for drawing  set and its complement.

// example

p = PitchCircle.new;

p.set_([10, 0, 2, 5, 7]);

p.drawCompl;

p.close;



front

brings the PitchCircle window to the front.

p.front;


close

close the PitchCircle window.

p.close;




// Examples

(

var newSet;

p = PitchCircle.new;

Routine {

p.labelAlign_(\left);

24.do({ |i|

if(i.even, {

{

newSet = p.complement.scramble.keep(rrand(4, 6)).sort;

p.hlDots_(newSet.sect([11, 0, 1]).choose);

p.drawSet(newSet);

}.defer;

}, {

{ p.complement(p.set);

  p.drawCompl(

  aLabel: format("%  compl.: %", 

  p.set, p.complement(p.set))

  );

}.defer;

});

0.5.wait;

});

1.wait;

p.close;

}.play;

)

// 19-ET microtonal example

(

p = PitchCircle.new(19);

i = (0..18);

n = ["C", "C#", "Db", "D", "D#", "Eb", "E", "E#", "F", "Gb", "F#", "Gb", "G", "G#", "Ab", "A", "A#", "B", "B#"];

p.notes = n;

p.integers = i;

p.hlDots_(2);

p.drawInts_(true);

p.drawSet([0, 2, 4, 6, 8, 10]);

)

(

// the offset variable cannot be used directly

var rotn=5.neg;

p.notes = n.rotate(rotn);

p.integers = i.rotate(rotn);

p.drawInts_(false);

p.hlDots_((2 + rotn)%19);

p.drawSet;

)