Here's a super-quick conversion of the VU-meter script changed to use the new audio interface in JScript Panel 3.6.6.
// ==PREPROCESSOR==
// @name "JSP3 VU Meter"
// ==/PREPROCESSOR==
var timer_SetInterval = 30; //ms
var VUMeterFb2k = false; // true: foobar2000 VU Meter style; false: free style
var font,font_t = "";
var g_text = "";
var ww = 0, wh = 0;
var colours = {
text : 0,
background : 0,
highlight : 0,
}
var color_1;
var color_2;
var color = [];
var step = 20; // more is less space between bars (cpu powers consumed) and vice versa.
var minDB = -60; //dB as Foobar2000' s built - in VU Meter
var db = [];
var ColourTypeCUI = {
text: 0,
selection_text: 1,
inactive_selection_text: 2,
background: 3,
selection_background: 4,
inactive_selection_background: 5,
active_item_frame: 6
};
var ColourTypeDUI = {
text: 0,
background: 1,
highlight: 2,
selection: 3
};
var FontTypeCUI = {
items : 0,
labels : 1,
};
var FontTypeDUI = {
defaults : 0,
tabs : 1,
lists : 2,
playlists : 3,
statusbar : 4,
console : 5,
};
function update_colours() {
if (window.IsDefaultUI) {
colours.text = window.GetColourDUI(ColourTypeDUI.text);
colours.highlight = window.GetColourDUI(ColourTypeDUI.highlight);
colours.background = window.GetColourDUI(ColourTypeDUI.background);
} else {
colours.text = window.GetColourCUI(ColourTypeCUI.text);
colours.background = window.GetColourCUI(ColourTypeCUI.background);
colours.highlight = blendColours(colours.text, colours.background, 0.4);
}
//custom colours override
// colours.text = RGB(255,255,255);
// colours.highlight = RGB(0,0,250);
// colours.background = RGB(0,0,0);
color_1 = colours.text; // or any color RGB(250,250,250);
color_2 = colours.highlight; // or any color RGB(0,0,0);
color = [];
for (var i = 0; i <= step; i++) {
color.push(blendColours(color_1, color_2, (i / step)));
db.push((minDB / step) * (step - i))
}
}
function update_font() {
if (window.IsDefaultUI) {
font = window.GetFontDUI(FontTypeDUI.defaults);
} else {
font = window.GetFontCUI(FontTypeCUI.items);
}
// adjust size
font_t = font;
var obj = JSON.parse(font_t);
obj.Size -= 4;
font_t = JSON.stringify(obj);
}
update_colours();
update_font();
function on_colours_changed() {
update_colours();
window.Repaint();
}
function on_mouse_lbtn_up(x, y) {
window.ShowConfigure();
}
function on_size() {
ww = window.Width;
wh = window.Height;
}
//------------- just an implementation /////////////
function RGB(r,g,b) { return (0xff000000|(r<<16)|(g<<8)|(b)); }
function RGBA(r, g, b, a) { return ((a << 24) | (r << 16) | (g << 8) | (b)); }
function toRGB(col) {
var a = col - 0xFF000000;
return [a >> 16, a >> 8 & 0xFF, a & 0xFF];
}
function blendColours(c1, c2, factor) { //@Marc2003
var c1 = toRGB(c1);
var c2 = toRGB(c2);
var r = Math.round(c1[0] + factor * (c2[0] - c1[0]));
var g = Math.round(c1[1] + factor * (c2[1] - c1[1]));
var b = Math.round(c1[2] + factor * (c2[2] - c1[2]));
return (0xff000000 | (r << 16) | (g << 8) | (b));
}
function on_paint(gr) {
gr.FillRectangle(0, 0, ww, wh, colours.background);
//
LM = RMS_level1; // ~ VUMeter.LeftLevel;
RM = RMS_level2; // ~ VUMeter.RightLevel;
L = Peak_level1; // ~ VUMeter.LeftPeak;
R = Peak_level2; // ~ VUMeter.RightPeak;
var h = 20; // VUh_bar;
var VUh_bar = 20; //
var VU_x = 20; //VUx;
var VUy = 5;
var VUh_off = h + 5;
var VUw = ww - 20;
var yL = (VUy + h);
var yLM = (VUy + h) + VUh_bar;
var yRM = (VUy + h) + VUh_bar + VUh_off;
var yR = (VUy + h) + VUh_bar + VUh_off + VUh_bar;
var dbLM = PctToDB(LM),
dbRM = PctToDB(RM),
dbL = PctToDB(L),
dbR = PctToDB(R);
if (VUMeterFb2k) {// foobar2000 VUMeter style
if (!(dbLM == 0 || dbLM == -Infinity)) {
// 65 : -60db- 0dB (+ 5dB offset at the end beyond 0dB ) scale
var wLM = Math.round(ww * ((100 + Number(dbLM)) / 65 - 40 / 65));
var wRM = Math.round(ww * ((100 + Number(dbRM)) / 65 - 40 / 65));
var wL = Math.round(ww * ((100 + Number(dbL)) / 65 - 40 / 65));
var wR = Math.round(ww * ((100 + Number(dbR)) / 65 - 40 / 65));
FillGradientRectangle(gr, VU_x, yLM, wLM, h - 1, 1, colours.text, colours.highlight);
FillGradientRectangle(gr, VU_x, yRM, wRM, h - 1, 1, colours.text, colours.highlight);
FillGradientRectangle(gr, VU_x, yL, wL, h - 1, 1, colours.text, colours.highlight);
FillGradientRectangle(gr, VU_x, yR, wR, h - 1, 1, colours.text, colours.highlight);
}
} else { // free style
h = 15;
var offset = Math.floor((VUw - VU_x) / (step + 1)); //step+1 : number of bars and we need 1 more bar at the end
var w = Math.floor((VUw - VU_x) / (step + 4)); // step+4 : width bar. we need some spaces between bars.
for (var i = 0; i <= step; i++) {
if (i > 0) {
dbLM = PctToDB(LM),
dbRM = PctToDB(RM),
dbL = PctToDB(L),
dbR = PctToDB(R);
}
gr.FillRectangle(VU_x + i * offset, yLM, w, h, dbLM >= db[i] ? color[i] : RGBA(0, 0, 0, 0));
gr.FillRectangle(VU_x + i * offset, yRM, w, h, dbRM >= db[i] ? color[i] : RGBA(0, 0, 0, 0));
if ((dbL > db[i] && dbL < db[i + 1])) {
var wL = i * offset + offset / Math.abs(db[i + 1] - db[i]) * Math.abs(dbL - db[i]);
gr.FillRectangle(VU_x, yL, wL, h, color[i]);
}
if ((dbR > db[i] && dbR < db[i + 1])) {
var wR = i * offset + offset / Math.abs(db[i + 1] - db[i]) * Math.abs(dbR - db[i]);
gr.FillRectangle(VU_x, yR, wR, h, color[i]);
}
}
}
// X-,Y-axis
for (var i = (65 - 5) / 5, j = 0; i >= 0; i--, j++)
gr.WriteText("-" + 5 * i + "dB", font_t, colours.text, VU_x / 2 + j * (ww - VU_x) / 13, yR + h + 10, ww, wh);
gr.WriteText("FL", font_t, colours.text, 0, yLM, ww, wh);
gr.WriteText("FL", font_t, colours.text, 0, yL, ww, wh);
gr.WriteText("FR", font_t, colours.text, 0, yRM, ww, wh);
gr.WriteText("FR", font_t, colours.text, 0, yR, ww, wh);
FillGradientRectangle(gr, VU_x, yR + h + 5, ww, 1, 1, colours.text, colours.highlight);
}
function clear_meter() {
RMS_level1 = 0;
RMS_level2 = 0;
Peak_level1 = 0;
Peak_level2 = 0;
prev_time = 0;
window.Repaint();
}
function on_playback_new_track(handler) {
VUMeter();
}
function on_playback_stop(reason) {
if (reason != 2) { // not starting another track
offVUMeterTimer();
clear_meter();
}
}
function on_playback_pause(state) {
state ? offVUMeterTimer() : onVUMeterTimer();
}
var RMS_level1 = RMS_level2 = Peak_level1 = Peak_level2 = 0; // RMS and Peak level of each 2 channels.
var timer_SetInterval_id = null;
var prev_time = 0;
function on_script_unload() {
}
function PctToDB(num) {
// input : num [0-1]
// output: dB [-100,0]
return ((2000 * Math.log(num) / Math.LN10) / 100).toFixed(2);
}
function onVUMeterTimer() {
if (!fb.IsPlaying || fb.IsPaused) return;
if (timer_SetInterval_id === null) {
timer_SetInterval_id = window.SetInterval(function() {
if (fb.PlaybackTime) {
var cur_time = fb.PlaybackTime;
var chunk = fb.GetAudioChunk(cur_time - prev_time);
if (chunk) {
prev_time = cur_time;
var data = chunk.Data.toArray();
if (data) {
var ch_count = chunk.ChannelCount;
var frame_len = chunk.SampleCount;
var ch2_idx = 1;
if (ch_count < 2) ch2_idx = 0;
var sum1 = 0;
var sum2 = 0;
var peak1 = 0;
var peak2 = 0;
for (var i = 0; i < data.length; i += ch_count) {
var l = data[i];
var r = data[i + ch2_idx];
if (l > peak1) peak1 = l;
if (r > peak2) peak2 = r;
sum1 += l * l;
sum2 += r * r;
}
RMS_level1 = Math.sqrt(sum1/frame_len);
RMS_level2 = Math.sqrt(sum2/frame_len);
Peak_level1 = peak1;
Peak_level2 = peak2;
}
}
}
//(window.RepaintRect(x, y, w, h);
window.Repaint();
}, timer_SetInterval);
}
}
function offVUMeterTimer() {
if (timer_SetInterval_id) window.ClearInterval(timer_SetInterval_id);
timer_SetInterval_id = null;
}
onVUMeterTimer();
function VUMeter() {
offVUMeterTimer(); //turn off timer
var handle = fb.IsPlaying ? fb.GetNowPlaying() : false;
if (!handle) return;
// set VUMeter timer tiktok
onVUMeterTimer();
}
function FillGradientRectangle(gr, x, y, w, h, direction, colour1, colour2) { //@Marc2003
var stops = [[0, colour1], [1, colour2]];
var brush = {
Start: [0, 0],
Stops: stops
};
if (direction == 0)
brush.End = [0, h];
else
brush.End = [w, 0];
gr.FillRectangle(x, y, w, h, JSON.stringify(brush));
}
//EOF
Edit: tiny bit cleaned up version.
Hi Case--your first version of the VU Meter implementation made possible by marc2k3's new JSP code was here, using the same meter GUI as the original Ilovefb2k release. Because the image scheme is classic, I am hoping that you wouldn't mind releasing a new version of the script?