Cents and ratios Ratios with factors Mean tone in cents Under / Over UO, non octave & scale tree Quintic Music and virtual flowers

# Dan Stearn's Under Over scales <!-- function split(string,text) { // modified from http://tech.irt.org/articles/js038/index.htm // splits string at text // set splitIndex = 0; before calling from outside this function. // splits the array splitArray[] which has to be made // before calling it // recursive method. // splits between each occurrence of the text, making zero length // strings if there is nothing else in between var strLength = string.length, txtLength = text.length; if ((strLength == 0) || (txtLength == 0)) { splitArray[0]=string; return; } var i = string.indexOf(text); if ((!i) && (text != string.substring(0,txtLength))) { splitArray[0]=string; return; } if (i == -1) { splitArray[splitIndex++] = string; return; } splitArray[splitIndex++] = string.substring(0,i); if (i+txtLength < strLength) split(string.substring(i+txtLength,strLength),text); return; } function find_gcd(m,n) // find g.c.d of m and n { min=Math.min(m,n); max=Math.max(m,n); diff=max-min; if(diff==1) return 1; if(max==min) return 1; for(ired=0;;ired++) { nmins=Math.floor(max/min); max-=min*nmins; min2=Math.min(min,max); max2=Math.max(min,max); min=min2; max=max2; if(min==0) { return max; } diff=max-min; if(diff==1) return 1; if(ired>1000) return 1;// shouldn't happen, but it's a good habit to add a little // check for runaway loops } } function round(x,precision_is) { if(precision_is<0||30<precision_is) return x; val_10_to_precision=Math.floor(0.5+Math.exp(precision_is*Math.log(10))); rounded_val=Math.floor(x*val_10_to_precision+0.5)/val_10_to_precision; return rounded_val; } function find_ratio_for_decimal(xx) { //there's a neat algorithm in Hardy and Wright that doesn't need an array //to hold the indexes, and calculates the successive approximations as //one goes along, so let's use that one. an=0,pn=0,pnm1=0,pnm2=0,qn=0,qnm1=0,qnm2=0; an=Math.floor(xx); zeta=xx-an; pnm1=1; pn=an; qnm1=0; qn=1; denum_for_decimal=pn; denom_for_decimal=qn; if(Math.abs(zeta)<1e-10) return; for(i=0;i<100;i++) { oneozeta=1/zeta; an=Math.floor(oneozeta); zeta=oneozeta-an; pnm2=pnm1;pnm1=pn; qnm2=qnm1;qnm1=qn; pn=an*pnm1+pnm2; qn=an*qnm1+qnm2; if(qn<0) break; denum_for_decimal=pn; denom_for_decimal=qn; if(Math.abs(pn/qn-xx)<1e-12) break; } } function read_as_value_or_ratio(string) { splitArray = new Array(); splitIndex = 0; split(string,'/'); if(splitIndex>1) { return eval(splitArray[0])/eval(splitArray[1]); } else { return eval(splitArray[0]); } } function find_cents_for(x) { return 1200*Math.log(x)/Math.log(2); } precision=5; function make_UO_scale(is_ou) { uo_scale = ""; cents_uo_scale = ""; cents_et_scale = ""; x_string = document.uo.x.value; decimal_places = document.uo.decimal_places.value; x = read_as_value_or_ratio(x_string); if(x<2) { x = 2; document.uo.x.value= "2"; } nvals = nnotes = eval(document.uo.nvals.value); if(nnotes>0&&x>1) { maxdiff = 0.0; etstep=Math.exp(Math.log(2)/nnotes); etval=1.0; a=1.0;b=1.0; a = nvals*x; b = a; if(is_ou) { a+=(x-2)*nnotes; b-=nnotes; } denom_for_decimal = 1; denum_for_decimal = 1; value = 1.0; for(degree = 0; degree<= nnotes; degree++) { // uo_scale += " a " + a + " b " + b + " "; value = a/b; if(is_ou) value=2/value; find_ratio_for_decimal(value); uo_scale += denum_for_decimal +"/" + denom_for_decimal + " "; c = find_cents_for(value); cents_uo_scale += round(c,decimal_places) + " "; cents_et_scale += round(find_cents_for(etval),decimal_places) + " "; if(degree>0) { cet = find_cents_for(etval); diff = c - cet; maxdiff = Math.max(maxdiff,Math.abs(diff)); } if(is_ou) { a-=x-2; b+=1; } else { a += x-2; b -= 1; } etval*=etstep; } document.uo.uo.value = uo_scale; document.uo.cents_uo.value = cents_uo_scale; document.uo.cents_et.value = cents_et_scale; document.uo.maxdiff.value = round(maxdiff,decimal_places); } } // -->

#### Number of decimal places to show

The value for x needs to be at least 2. You can enter it as a decimal or as a ratio such as 7/2.

Dan's idea is that when you set x to be 2 you get an undertone series. When you set it to be infinite you get an overtone series. Try x = 1e20 for the overtone series - this means x followed by 20 zeroes, which is large enough. In between, you get interesting rational scales that are in between an overtone and an undertone series.

When you set x to be 2 + sqrt(2) you get closest to an equal temperament scale (for octave scales). In order to make the result rational you need to use an approximation to the square root of two. Try x = 3.4. Values in the range x = 3 to x = 4 are the ones Dan refers to as equal series.

The OU scales are the inversions of the UO scales

This is Dan's algorithm in pseudo code (i.e. computer code, but with some of it in ordinary english):

```
Initialising values:

x = whatever value it has (e.g. 3.4).
n = notes in scale (e.g. 5)

Calculation:

a = n*x
b = n*x

for degree = 0, incremented by 1 until you reach n
{
scale value for this degree = a / b
a = a + x - 2
b = b - 1
}

Example:
x = 4
n = 5

a = 20
b = 20
x-2 = 2
so a -> a + 2
b -> b - 1
scale is:
20/20 22/19 24/18 26/17 28/16 30/15
=
1/1 22/19 12/9 26/17 7/4 2/1

It works because nx + n(x - 2) = n(2x - 2) = 2 (nx - n)

For x = 2, a is constant, and b decreases by 1,
so you get an undertone series

For x very large, a increases by x each time and
b is effectively constant as the 1 is small compared
with x, so you get the overtone series.

You get the closest to the equal temperament scale when it is symmetrical.

So lets do the calculation for this too.

In the case where n is even, you want the centre interval to be its own inversion.

Let n be even
n = 2m

and the centre interval is
(2mx + m(x-2)) / (2mx - m)

so you want
(2x + x-2) / (2x-1) to be its own inversion in the octave

This means you want it to equal sqrt(2)

Lets write s = sqrt(2)

So you want (3x-2) / (2x-1) = s

=>
3x - 2 = 2sx - s
=>
(3 - 2s)x = 2-s
=>
x = (2 - r2) / (3 - 2s)

multiply top and bottom by (3 + 2s) to get
x = (2 - s) (3 + 2s) / (9 - 8)
so x = 6 + s - 4 = 2 + s

This only takes account of the even cases, but for n odd,
just consider 2n, which has the values for n as
every second entry in the scale.
```