(root)/wip/src/oscilloscope.cc - Rev 2304
Rev 2302 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* oscilloscope.cc
* DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/
#include "dingl.h"
#include "oscilloscope.h"
#include "font.h"
#include "viewwin.h"
#include "input.h"
#include "log.h"
#include "console.h"
#include <string>
#include <algorithm>
using namespace std;
extern string user_data_dir;
extern int CURRENT_INSTRUMENT;
extern const int NUM_INSTRUMENTS;
extern int lmb;
extern int mousex, mouseyy;
extern viewport view;
extern int line_height;
oscilloscope::oscilloscope (const string& _settingsf) : win (0, 0, 2048, 250) {
samples = 0;
vertices = 0;
colors = 0;
settingsf = _settingsf;
fold.set_listener (this);
load ();
px = py = -1;
lmb_clicked = move = stop_move = 0;
sample_t::lmin = sample_t::lmax = sample_t::rmin = sample_t::rmax = 0; // ok for oscilloscope.
sprintf (lbuf1, "min %1.2f / max %1.2f", sample_t::lmin, sample_t::lmax);
sprintf (rbuf1, "min %1.2f / max %1.2f", sample_t::rmin, sample_t::rmax);
lr = 0; lg = lb = 1.0f;
rr = rg = 1.0; rb = 0.0f;
opacity = 1.0f;
distort = 0;
}
oscilloscope::~oscilloscope () {
save ();
delete[] samples;
delete[] vertices;
delete[] colors;
}
void oscilloscope::alloc (int n) {
max_samples = n;
if (samples) delete[] samples;
if (vertices) delete[] vertices;
if (colors) delete[] colors;
samples = new sample_t [max_samples];
vertices = new int [8 * max_samples];
colors = new float [16 * max_samples];
set_num_samples (num_samples);
}
int oscilloscope::set_num_samples (int n) {
num_samples = min (n, max_samples);
startsamp = max_samples - num_samples;
calc_draw_params ();
return num_samples;
}
void oscilloscope::calc_draw_params () {
base = win.midy;
leftx = win.left;
rightx = leftx + num_samples;
endx = rightx + num_samples - 1;
ndraw = 4 * num_samples;
win (leftx, base - height, endx, base + height);
int dheight = 5;
pick_win (win.left, base - dheight, win.right, base + dheight);
lh = line_height;
lly = base - lh;
lry = lly;
fold.set_pos (leftx - 1.5 * fold.size, base - fold.size);
}
int oscilloscope::load () {
ifstream file ((user_data_dir + settingsf).c_str(), ios::in);
if (!file) return 0;
string ignore;
file >> ignore >> updlbl.triggert;
for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
file >> ignore >> left;
file >> ignore >> base;
file >> ignore >> height;
file >> ignore >> num_samples;
file >> ignore >> opacity;
file >> ignore >> visible;
file >> ignore >> folded;
params.push_back (oscilloscope_params_t (left, base, height, num_samples, opacity, visible, folded));
}
updlbl.start ();
return 1;
}
int oscilloscope::save () {
ofstream file ((user_data_dir + settingsf).c_str(), ios::out);
if (!file) return false;
file << "update-label-every " << updlbl.triggert << endl;
for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
oscilloscope_params_t& op = params[i];
file << "left " << op.left << endl;
file << "base " << op.base << endl;
file << "height " << op.height << endl;
file << "num_samples " << op.num_samples << endl;
file << "opacity " << op.opacity << endl;
file << "visible " << op.visible << endl;
file << "folded " << op.folded << endl;
}
return 1;
}
void oscilloscope::load_current_instrument () {
oscilloscope_params_t& op = params[CURRENT_INSTRUMENT];
left = op.left;
base = op.base;
height = op.height;
num_samples = op.num_samples;
opacity = op.opacity;
visible = op.visible;
folded = op.folded;
win (left, base - height, left + 2 * num_samples, base + height);
set_folded (folded);
set_num_samples (num_samples); // calls calc_draw_params
}
void oscilloscope::save_current_instrument () {
oscilloscope_params_t& op = params[CURRENT_INSTRUMENT];
op.left = win.left;
op.base = base;
op.height = height;
op.num_samples = num_samples;
op.opacity = opacity;
op.visible = visible;
op.folded = folded;
}
void oscilloscope::set_height (int h) {
height = h;
calc_draw_params ();
}
int oscilloscope::handle_input () {
int result = fold.handle_input ();
if (result) return result;
int x = mousex;
int y = mouseyy;
if (is_lmb (this)) {
if (lmb_clicked == 0) {
lmb_clicked = 1;
if (move) {
move = 0;
stop_move = 1;
} else if (inbox (pick_win, x, y)) { // pick_win is small window along zero line of oscilloscope
move = 1;
is_lmb.tie = this;
}
}
} else {
if (move) {
int dx = x - px, dy = y - py;
win.move (dx, dy);
calc_draw_params ();
} else if (stop_move) {
stop_move = 0;
is_lmb.clear (this);
}
lmb_clicked = 0;
}
px = x;
py = y;
result = move;
return result;
}
void oscilloscope::add_samples (float* outl, float* outr, int n) {
for (int i = 0; i < n; ++i) {
sample_t& sa = samples [i];
sa.left = outl[i]; sa.right = outr[i];
sample_t::lmin = min (sa.left, sample_t::lmin);
sample_t::lmax = max (sa.left, sample_t::lmax);
sample_t::rmin = min (sa.right, sample_t::rmin);
sample_t::rmax = max (sa.right, sample_t::rmax);
}
// used by mondrian
float lm = sample_t::lmin * sample_t::rmin, rm = sample_t::lmax * sample_t::rmax;
limit = (lm > 1 || rm > 1);
{
char lb = '.', rb = '.';
float lsum = sample_t::lmin * sample_t::lmin + sample_t::lmax * sample_t::lmax;
float rsum = sample_t::rmin * sample_t::rmin + sample_t::rmax * sample_t::rmax;
if (lsum > rsum) lb = '@'; else if (rsum > lsum) rb = '@';
if (updlbl (ui_clk())) {
sprintf (lbuf1, "min %1.2f / max %1.2f %c", sample_t::lmin, sample_t::lmax, lb);
sprintf (rbuf1, "min %1.2f / max %1.2f %c", sample_t::rmin, sample_t::rmax, rb);
updlbl.start ();
}
sample_t::lmin = sample_t::lmax = sample_t::rmin = sample_t::rmax = 0;
}
if (folded == 0) {
int x1 = leftx, x2 = rightx, y0 = base;
for (int i = 0, j = startsamp, vi = 0, ci = 0; i < num_samples; ++i, ++j, vi += 8, ci += 16) {
float l = samples[j].left;
float r = samples[j].right;
int ly = int (l * win.height);
int ry = int (r * win.height);
// distortion is red
//
float l2 = l * l;
float lrr = lr, lgg = lg, lbb = lb;
if (l2 > 1.0f) {lrr = 1; lgg = 0; lbb = 0; distort = 1;}
float rrr = rr, rgg = rg, rbb = rb;
float r2 = r * r;
if (r2 > 1.0f) {rrr = 1; rgg = 0; rbb = 0; distort = 1;}
vertices [vi] = x1;
vertices [vi+1] = y0;
vertices [vi+2] = x1;
vertices [vi+3] = y0 + ly;
vertices [vi+4] = x2;
vertices [vi+5] = y0;
vertices [vi+6] = x2;
vertices [vi+7] = y0 + ry;
colors [ci] = colors[ci+4] = lrr;
colors [ci+1] = colors[ci+5] = lgg;
colors [ci+2] = colors[ci+6] = lbb;
colors [ci+3] = colors[ci+7] = opacity;
colors [ci+8] = colors[ci+12] = rrr;
colors [ci+9] = colors[ci+13] = rgg;
colors [ci+10] = colors[ci+14] = rbb;
colors [ci+11] = colors[ci+15] = opacity;
++x1; ++x2;
}
}
}
void oscilloscope::draw () {
if (folded == 0) {
// draw samples
//
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState (GL_COLOR_ARRAY);
glColorPointer (4, GL_FLOAT, 0, colors);
glVertexPointer (2, GL_INT, 0, vertices);
glDrawArrays (GL_LINES, 0, ndraw);
glDisableClientState (GL_COLOR_ARRAY);
glDisable (GL_BLEND);
}
// draw L and R labels
//
if (limit) glColor3f (1, 0, 0); else glColor3f (lr , lg, lb);
draw_string (lbuf1, leftx, lly, 0);
glBegin (GL_LINES);
glVertex2i (leftx, win.midy);
glVertex2i (rightx, win.midy);
glEnd ();
if (limit) glColor3f (1, 0, 0); else glColor3f (rr, rg, rb);
draw_string (rbuf1, rightx, lry, 0);
glBegin (GL_LINES);
glVertex2i (rightx, win.midy);
glVertex2i (endx, win.midy);
glEnd ();
//distort = 0;
fold.draw ();
}
void oscilloscope::set_folded (int f) {
folded = f;
if (folded) {
fold.set_dir (arrow_button::right);
} else {
fold.set_dir (arrow_button::up);
}
}
void oscilloscope::clicked (button& b) {
set_folded (!folded);
}
oscilloscope_params_t::oscilloscope_params_t (int l, int b, int h, int ns, float op, int v, int f) {
left = l;
base = b;
height = h;
num_samples = ns;
opacity = op;
visible = v;
folded = f;
}