Scale supports arbitrary octave divisions and ratios, and (in conjunction with Tuning) can generate pitch information in various ways, including as input to Patterns.
s.boot;
a = Scale.major;
a.degrees; // [ 0, 2, 4, 5, 7, 9, 11 ]
a.semitones; // [ 0, 2, 4, 5, 7, 9, 11 ]
a.cents; // [ 0, 200, 300, 500, 700, 900, 1100 ]
a.ratios; // [ 1, 1.1224620483089, 1.2599210498937, 1.3348398541685, etc. ]
Pbind(\scale, a, \degree, Pseq((0..7) ++ (6..0) ++ [\rest], 1), \dur, 0.25).play;
// use non-standard tuning
a.tuning_(\just);
a.degrees; // no change; degrees are independent of tuning
a.semitones; // [ 0, 2.0391000173077, 3.1564128700055, 4.9804499913461, etc. ]
a.ratios.collect(_.round(0.001)); // [ 1, 1.125, 1.2, 1.333, 1.5, 1.667, 1.875 ]
Pbind(\scale, a, \degree, Pseq((0..7) ++ (6..0) ++ [\rest], 1), \dur, 0.25).play;
*major, *minor, *dorian, *chromatic, *todi, *hijaz, *partch_o1, etc.
Creates a scale from the library stored in the instance variable "all". Each scale comes with an appropriate default Tuning, but alternate tunings can be specified at creation time:
xxxxxxxxxx
Scale.phrygian(\pythagorean)
If the tuning size does not match the scale's -pitchesPerOctave, a warning will be thrown, and the scale will use its default tuning.
For a complete list of available scales, execute
xxxxxxxxxx
Scale.directory
The scale repository, to which new scales can be added.
xxxxxxxxxx
Scale.all.put(\catastrophic, Scale([0, 0.01, 0.04, 11.2]));
Scale.at(\catastrophic); // access the scale
Access from the scale repository.
xxxxxxxxxx
Scale.all.put(\catastrophic, Scale([0, 0.01, 0.04, 11.2]));
Scale.at(\ionian);
Scale.newFromKey(\ionian); // access a copy of the scale for modification
Creates a random scale from the library, constrained by size and pitchsPerOctave if desired.
xxxxxxxxxx
Scale.choose; // could be anything
Scale.choose(7); // will be a seven-note scale in its default tuning (could be any)
Scale.choose(7, 12); // will be a seven-note scale in a twelve-tone tuning (usually ET!2)
// Random seven-note scale in random twelve-tone tuning
a = Scale.choose(7, 12).tuning_(Tuning.choose(12));
a.tuning.name;
Creates a Scale from scratch. degrees should be an array of Integers or scale name. If pitchesPerOctave is nil, will guess the most appropriate number based on degrees. tuning can be an instance of Tuning or a symbol; if nil, will be equal temperament of pitchesPerOctave. Specify descDegrees if the Scale should play differently when descending than when ascending; otherwise it should be nil.
xxxxxxxxxx
Scale.new(#[0, 1, 3, 6, 8, 10, 11], name: "My ET12"); // will be in ET12
Scale.new(#[0, 3, 7, 10, 15, 19, 22], name: "My Quarter-Tone"); // will be in ET24
Scale.new(#[0, 6, 17, 21, 30, 39], 43, \partch, "My Partch");
Returns a chromatic scale for a specific tuning.
Sets or gets the tuning of the Scale.
inTuning |
can be either an instance of Tuning or a symbol matching a library tuning. |
Returns a tuned array of semitone values. -as(Array) is equivalent; -as(List) returns it as a list, etc.
Returns a tuned array of cent values.
Returns a tuned array of ratios.
Converting. For example as(Array)
, as(List)
and as(LocalBuf)
which is useful for server-side work.
xxxxxxxxxx
(
r = {
var scale = Scale.choose.postln;
SinOsc.ar(
(
DegreeToKey.kr(
scale.as(LocalBuf),
MouseX.kr(0,15), // mouse indexes into scale
scale.stepsPerOctave,
1, // mul = 1
60 // offset by 72 notes
)
+ LFNoise1.kr([3,3], 0.04) // add some low freq stereo detuning
).midicps, // convert midi notes to hertz
0,
0.25
)
}.play;
)
r.free;
Returns the length of the scale.
xxxxxxxxxx
Scale.ionian.size; // 7
Scale.minorPentatonic.size; // 5
Scale.ajam.size; // 7
Scale.partch_o1.size; // 6
Returns the size of the pitch class set from which the tuning is drawn.
xxxxxxxxxx
Scale.ionian.pitchesPerOctave; // 12
Scale.minorPentatonic.pitchesPerOctave; // 12
Scale.ajam.pitchesPerOctave; // 24--this is a quarter-tone scale
Scale.partch_o1.pitchesPerOctave; // 43
Usually 12, but may be different if the current tuning has a stretched or compressed octave. Needed for degreeToKey.
xxxxxxxxxx
Scale.new((0..14), 15, tuning: \wcAlpha).stepsPerOctave; // ~ 11.7
Scale.new(#[0, 3, 6, 9, 12], 13, tuning: \bp).stepsPerOctave; // ~ 19.02
but note:
xxxxxxxxxx
Scale.ajam.stepsPerOctave; // 12 -- quarter-tone scales have normal octaves
These access the array generated by semitones.
xxxxxxxxxx
a = Scale.major;
a.wrapAt(4); // 7
a.wrapAt(5); // 9
a.wrapAt(6); // 11
a.wrapAt(7); // 0
Returns a frequency based on current tuning and rootFreq argument.
xxxxxxxxxx
Scale.major.degreeToFreq(2, 60.midicps, 1); // 659.25511...
Scale.major(\just).degreeToFreq(2, 60.midicps, 1); // 654.06391...
Returns a ratio based on current tuning.
xxxxxxxxxx
Scale.major.degreeToRatio(2, 1).round(0.001); // 2.52
Scale.major(\just).degreeToRatio(2, 1).round(0.001); // 2.5
xxxxxxxxxx
(
s.waitForBoot({
a = Scale.ionian;
p = Pbind(
\degree, Pseq([0, 1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0, \rest], inf),
\scale, Pfunc({ a }, inf),
\dur, 0.25
);
q = p.play;
})
)
// change scale
a = Scale.phrygian;
// change tuning
a.tuning_(\just);
// can also set tuning at creation time
a = Scale.ionian(\pythagorean);
// if you use a tuning with the wrong number of pitches per octave,
// you get a warning and the scale reverts to default tuning
a.tuning_(\partch);
// random scale
(
a = Scale.choose(7, 12);
[a.name, a.tuning.name].postln;
)
(
// or make up your own arbitrary scales and tunings
a = Scale.new(
#[0, 2, 4, 5, 7, 9, 10],
12,
Tuning.new([0, 0.8, 2.1, 3, 4.05, 5.2, 6, 6.75, 8.3, 9, 10.08, 11.5]),
"Custom"
);
)
// tuning has its own class
t = Tuning.werckmeister;
a = Scale.lydian(t);
q.stop;
// getting info
a.name;
a.degrees;
a.semitones;
a.ratios;
a.tuning.name;
a.tuning.semitones;
a.tuning.ratios;
xxxxxxxxxx
// for ascending/descending scales, use Pavaroh
(
Pbind(\note, Pavaroh(
Pseq([0, 1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0, \rest], 2),
Scale.melodicMinor,
Scale.melodicMinorDesc
),
\dur, 0.25
).play;
)
xxxxxxxxxx
// note that the root pitch is not stored in the Scale (which should arguably be called a Mode for that reason)
// instead you supply it at play time:
// key of A
Pbind(
\degree, Pseq((0..7), inf), // your melody goes here
\scale, Scale.major, // your scale goes here
\root, -3 // semitones relative to 60.midicps, so this is A
).play;