To split a frequency range into 9 segments, you'll need to take the 9th root of the factor from low to high frequencies:
let a=20,b=20000,n=9;
const fact=Math.pow(b/a,1/n);
console.log(a);
for (i=0; i<n; i++) console.log(a*=fact)
Note regarding the revised question:
The code below converts sound frequencies to light frequencies with a conversion rate of 440HZ = 640nm. Within one octave: as the sound pitch increases, the wavelength decreases:
sound frequency / Hz |
wavelength / nm |
440 |
640 |
660 |
426.6666666666667 |
879.9999 |
320.0000363636406 |
880 |
640 |
1320 |
426.6666666666667 |
1760 |
640 |
let a=20,b=20000,n=12;
const A=440, lnA=Math.log2(A)%1;
const L=640; // base wavelength
if(1)for (let n=35,f=20,f1=20000,fact=Math.pow(f1/f,1/n);n-->-1; f*=fact) {
let l=(lnA-Math.log2(f))%1;
let wl=Math.pow(2,l)*L // light wavelength in nm
console.log(f,wl)
}
This snippet covers the frequency range 20...20000Hz in 35 steps (adjustable). It maps light wavelengths for the fractional part (l=(lnA-Math.log2(f))%1
) of frequencies, repetitive each octave.
Request for clarification:
Based on the latest input from OP, it seems that the wavelength calculations should follow this pattern:
https://i.sstatic.net/Y63nZ.png
In this scenario, the entire frequency spectrum (from lower value f0 to higher value f1) is divided into 6 sections (not octaves!), and within each section, sound frequencies are converted to wavelengths falling between wl0 (longest) and wl1 (shortest).
OP, does this align with your intentions?
If so, then this solution should suit your needs:
function calcWaveLength([f0,f1],[wl0,wl1],n){
const lf0=Math.log(f0), lfstep=Math.log(f1/f0)/n,
lwl0=Math.log(wl0), llrange=Math.log(wl1/wl0);
return function(freq){
lf=Math.log(freq)
return Math.exp( lwl0 + (lf-lf0)/lfstep % 1 * llrange )
}
}
// set up the calc function (once) for each frequency range:
const calc=calcWaveLength([20,20000],[640,460],3);
console.log("frequency, wavelength");
[20,35.56558820077846,63.245553203367585,112.46826503806982,199.999,
200,355.65588200778456,632.4555320336758,1124.682650380698,1999.99,
2000,3556.558820077845,6324.555320336758,11246.82650380698,19999.9,
20000].forEach(f=>
console.log(f.toFixed(3),calc(f).toFixed(3))
)
The code computes according to the diagram's specifications, resembling a sawtooth wave function with sharp edges at segment ends:
https://i.sstatic.net/gyHAf.png