Javascript Wavelength to RGB

rozatlab's icon

Hello all,

I'm currently working on a patch to convert light wavelength into RGB values in javascript. I have found source code online in javascript, but am having trouble figuring out how set it up in max so that the value from the inlet (which is my wavelength value, as a flonum) after going through the functions is routed it to 3 outlets (one for each RGB value). I feel that this is a simple syntax issue, however, I am VERY new to both Max and javascript so I'm not sure. Any help is GREATLY appreciated!

I've attached a basic patcher (with a javascript page included) for the rough idea of what I'm trying to do.

Here's the code- which is supposed to assign a range of input values to the appropriate RGB parameters. I would then like to route the results to the 3 outlets, one for R, one for G, and one for B:

PROCEDURE WavelengthToRGB(CONST Wavelength: Nanometers;
VAR R,G,B: BYTE);
CONST
Gamma = 0.80;
IntensityMax = 255;
VAR
Blue : DOUBLE;
factor : DOUBLE;
Green : DOUBLE;
Red : DOUBLE;
FUNCTION Adjust(CONST Color, Factor: DOUBLE): INTEGER;
BEGIN
IF Color = 0.0
THEN RESULT := 0 // Don't want 0^x = 1 for x <> 0
ELSE RESULT := ROUND(IntensityMax * Power(Color * Factor, Gamma))
END {Adjust};
BEGIN
CASE TRUNC(Wavelength) OF
380..439:
BEGIN
Red := -(Wavelength - 440) / (440 - 380);
Green := 0.0;
Blue := 1.0
END;
440..489:
BEGIN
Red := 0.0;
Green := (Wavelength - 440) / (490 - 440);
Blue := 1.0
END;
490..509:
BEGIN
Red := 0.0;
Green := 1.0;
Blue := -(Wavelength - 510) / (510 - 490)
END;
510..579:
BEGIN
Red := (Wavelength - 510) / (580 - 510);
Green := 1.0;
Blue := 0.0
END;
580..644:
BEGIN
Red := 1.0;
Green := -(Wavelength - 645) / (645 - 580);
Blue := 0.0
END;
645..780:
BEGIN
Red := 1.0;
Green := 0.0;
Blue := 0.0
END;
ELSE
Red := 0.0;
Green := 0.0;
Blue := 0.0
END;
// Let the intensity fall off near the vision limits
CASE TRUNC(Wavelength) OF
380..419: factor := 0.3 + 0.7*(Wavelength - 380) / (420 - 380);
420..700: factor := 1.0;
701..780: factor := 0.3 + 0.7*(780 - Wavelength) / (780 - 700)
ELSE factor := 0.0
END;
R := Adjust(Red, Factor);
G := Adjust(Green, Factor);
B := Adjust(Blue, Factor)
END {WavelengthToRGB};

wavelength_to_RGB_test.maxpat
Max Patch
wavelength_to_RGB.js
js
Jan M's icon

Hi ROZATLAB,

without checking if the calculations are correct,i just went over your Javascript code and patch and put it int a proper syntax.
(see attachment and patcher)

Cheers,

Max Patch
Copy patch and select New From Clipboard in Max.

Jan

rgbtest.js
js
rozatlab's icon

Wow thank you so much Jan!!!

rozatlab's icon

Hi Jan, a quick follow up question. I've been able to implement the javascript code that you put in proper syntax (again thank you!) however, now I'm having trouble. I'm trying to turn a pitch (and it's overtones) into their corresponding color, where loudness controls saturation. Nothing groundbreaking. I was able to do so using the javascript objects for the fundamental pitch, but when I try using the same functions on the overtones (sinusoidal components) the saturation is forced to 1. Is this a javascript issue, or something else? I've attached a version of the patch for reference, as well as the js codes. Thanks again for any help!

Help1.maxpat
Max Patch
frequency_to_wavelength1.js
js
wavelength_to_RGB1.js
js
Jan M's icon

Hi ROZATLAB,

what do you mean with the saturation is forced to 1. Actually in the patch you take the saturation from the amplitude value coming out of [analyzer~] and you display the value coming out of the [swatch]. So no JS involved there. I don't see any "forced" saturation values here. If you might get an amplitude reading > 1 [swatch] will clip the value to one. Is that what you mean?

Cheers, Jan

rozatlab's icon

All is working in the example on the left of the patch, but not the right side. For some reason when I connect the last outlet of the [analyzer~] object (which is it's sinusoidal components) to the javascript objects, the swatch saturation is forced to 1., even when I don't have the amplitude connected. I'm stuck. I thought the problem could be something that's in the signal that's being sent from the last outlet of [analyzer~], or that I'm using multiple occurrences of the same javascript function, but I can't seem to pinpoint it.

I'm also quite new to Max so I apologize if there was something super basic that I missed.

Thanks for the help again Jan!