ph69
01-25-2008, 09:34 AM
Hi,
While working on modular synth, I needed a scope with synchro capabilities.
Here it is
desc:MoonSynthi ScopeII alpha (press Edit for HELP)
/*
Scope with synchro and automatic gain
DONE low pass synchro
color depending on selected channel
automatic gain
display peak max/min, mean, rms value
TODO : pitch control synchro
subsample synchro
additive display (with compensation for display size and widthS)
all gfx / serialize, no slider, for small display
*/
slider1:10<1,20>Time width (ms)
slider2:0<0, 11, 1{0,1,2,3,4,5,6,7,8,9,10,11}>Sync channel
slider3:0<0, 11, 1{0,1,2,3,4,5,6,7,8,9,10,11}>View channel
//__________________________________________________ _______________
@init
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Tables
L_BUF = srate; //1s buffer
syncBuf = 0;
viewBuf = syncBuf + L_BUF;
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Set of colours depending on which channel you select
t_r = viewBuf + L_BUF;
t_g = t_r + 12;
t_b = t_g + 12;
x = 0;
ch = 0;
loop(12,
t_r[ch] = sqrt(0.5 + 0.5 * sin(x));
t_g[ch] = sqrt(0.5 + 0.5 * sin(x + 2*$pi/3));
t_b[ch] = sqrt(0.5 + 0.5 * sin(x + 4*$pi/3));
x += $pi/6.0;
ch += 1;
);
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Buffer index
writePos = 0;
low = low2 = 0;
//__________________________________________________ _______________
@slider
widthS = srate * slider1 * 0.001;//width of a time frame in samples
syncCh = slider2|0;
viewCh = slider3|0;
//__________________________________________________ _______________
@sample
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Low pass filtering of synchro signal
low = low + 0.01 * (spl(syncCh) - low);
low2 = low2 + 0.01 * (low - low2);
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Buffering
syncBuf[writePos] = low2;
viewBuf[writePos] = spl(viewCh);
writePos += 1;
writePos >= L_BUF ?
writePos = 0;
//__________________________________________________ _______________
@gfx 100 100
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// We start 3 time frames ago (widthS).
startPos = (writePos - 3 * widthS - 1 + L_BUF) % L_BUF;
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// mean and other values over these 3 frames
v_moy = v_max = v_min = viewBuf[startPos];
v_rms = viewBuf[startPos] * viewBuf[startPos];
i = 1;
loop(3 * widthS - 1,
v = viewBuf[(startPos + i) % L_BUF];
v_moy += v;
v_rms += v * v;
v > v_max ? v_max = v;
v < v_min ? v_min = v;
i += 1;
);
v_moy /= 3 * widthS;
v_rms = sqrt(v_rms) / (3 * widthS);
peak = max(v_max, -v_min);
gain = 1 / max(peak, 0.0001); //max gain:10000
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// scanning for synchro over a time frame
av = syncBuf[startPos];
i = 0;
while(
startPos = (startPos + 1) % L_BUF;
v = syncBuf[startPos];
v > 0 && av <= 0 ?
i = widthS; // We found the 0 crossing we leave the loop
av = v;
i += 1;
i < widthS;
);
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// color
gfx_r = t_r[viewCh];
gfx_g = t_g[viewCh];
gfx_b = t_b[viewCh];
gfx_a = 1;
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Values
gfx_x = 10; gfx_y = 10;
gfx_drawnumber(v_min, 3);
gfx_x += 10;
gfx_drawnumber(v_max, 3);
gfx_x = 10; gfx_y += gfx_texth;
gfx_drawnumber(v_moy, 3);
gfx_x += 10;
gfx_drawnumber(v_rms, 3);
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// display of view channel
h_milieu = gfx_h * 0.5;
etendue = gfx_h * 0.45;
cBuf = viewBuf; //current Buffer
gfx_x = 0; gfx_y = h_milieu - etendue * cBuf[startPos];
dx = gfx_w / widthS;
i = 1; x = dx;
loop(widthS,
gfx_lineto(x,h_milieu - etendue * gain * cBuf[(startPos + i) % L_BUF], 1);
i += 1; x += dx;
);
While working on modular synth, I needed a scope with synchro capabilities.
Here it is
desc:MoonSynthi ScopeII alpha (press Edit for HELP)
/*
Scope with synchro and automatic gain
DONE low pass synchro
color depending on selected channel
automatic gain
display peak max/min, mean, rms value
TODO : pitch control synchro
subsample synchro
additive display (with compensation for display size and widthS)
all gfx / serialize, no slider, for small display
*/
slider1:10<1,20>Time width (ms)
slider2:0<0, 11, 1{0,1,2,3,4,5,6,7,8,9,10,11}>Sync channel
slider3:0<0, 11, 1{0,1,2,3,4,5,6,7,8,9,10,11}>View channel
//__________________________________________________ _______________
@init
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Tables
L_BUF = srate; //1s buffer
syncBuf = 0;
viewBuf = syncBuf + L_BUF;
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Set of colours depending on which channel you select
t_r = viewBuf + L_BUF;
t_g = t_r + 12;
t_b = t_g + 12;
x = 0;
ch = 0;
loop(12,
t_r[ch] = sqrt(0.5 + 0.5 * sin(x));
t_g[ch] = sqrt(0.5 + 0.5 * sin(x + 2*$pi/3));
t_b[ch] = sqrt(0.5 + 0.5 * sin(x + 4*$pi/3));
x += $pi/6.0;
ch += 1;
);
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Buffer index
writePos = 0;
low = low2 = 0;
//__________________________________________________ _______________
@slider
widthS = srate * slider1 * 0.001;//width of a time frame in samples
syncCh = slider2|0;
viewCh = slider3|0;
//__________________________________________________ _______________
@sample
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Low pass filtering of synchro signal
low = low + 0.01 * (spl(syncCh) - low);
low2 = low2 + 0.01 * (low - low2);
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Buffering
syncBuf[writePos] = low2;
viewBuf[writePos] = spl(viewCh);
writePos += 1;
writePos >= L_BUF ?
writePos = 0;
//__________________________________________________ _______________
@gfx 100 100
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// We start 3 time frames ago (widthS).
startPos = (writePos - 3 * widthS - 1 + L_BUF) % L_BUF;
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// mean and other values over these 3 frames
v_moy = v_max = v_min = viewBuf[startPos];
v_rms = viewBuf[startPos] * viewBuf[startPos];
i = 1;
loop(3 * widthS - 1,
v = viewBuf[(startPos + i) % L_BUF];
v_moy += v;
v_rms += v * v;
v > v_max ? v_max = v;
v < v_min ? v_min = v;
i += 1;
);
v_moy /= 3 * widthS;
v_rms = sqrt(v_rms) / (3 * widthS);
peak = max(v_max, -v_min);
gain = 1 / max(peak, 0.0001); //max gain:10000
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// scanning for synchro over a time frame
av = syncBuf[startPos];
i = 0;
while(
startPos = (startPos + 1) % L_BUF;
v = syncBuf[startPos];
v > 0 && av <= 0 ?
i = widthS; // We found the 0 crossing we leave the loop
av = v;
i += 1;
i < widthS;
);
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// color
gfx_r = t_r[viewCh];
gfx_g = t_g[viewCh];
gfx_b = t_b[viewCh];
gfx_a = 1;
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// Values
gfx_x = 10; gfx_y = 10;
gfx_drawnumber(v_min, 3);
gfx_x += 10;
gfx_drawnumber(v_max, 3);
gfx_x = 10; gfx_y += gfx_texth;
gfx_drawnumber(v_moy, 3);
gfx_x += 10;
gfx_drawnumber(v_rms, 3);
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// display of view channel
h_milieu = gfx_h * 0.5;
etendue = gfx_h * 0.45;
cBuf = viewBuf; //current Buffer
gfx_x = 0; gfx_y = h_milieu - etendue * cBuf[startPos];
dx = gfx_w / widthS;
i = 1; x = dx;
loop(widthS,
gfx_lineto(x,h_milieu - etendue * gain * cBuf[(startPos + i) % L_BUF], 1);
i += 1; x += dx;
);