(root)/wip/src/oscilloscope.cc - Rev 914
Rev 652 |
Rev 1015 |
Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* oscilloscope.cc
* DIN Is Noise is copyright (c) 2006-2018 Jagannathan Sampath
* For more information, please visit http://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 FPS;
extern int MILLION;
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, 2 * MAX_SAMPLES, 250) {
vertex_array = new int [8 * MAX_SAMPLES];
color_array = new float [16 * MAX_SAMPLES];
viewr = 0;
addr = 1;
settingsf = _settingsf;
label_counter = MILLION;
fld.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 %2.2f, max %2.2f", sample_t::lmin, sample_t::lmax);
sprintf (rbuf1, "min %2.2f, max %2.2f", sample_t::rmin, sample_t::rmax);
lr = lg = lb = 0.0f;
rr = rg = rb = 0.0f;
}
int oscilloscope::load () {
ifstream file ((user_data_dir + settingsf).c_str(), ios::in);
if (!file) return 0;
string ignore;
for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
file >> ignore >> left;
file >> ignore >> base;
file >> ignore >> height;
file >> ignore >> num_samples;
file >> ignore >> visible;
file >> ignore >> folded;
params.push_back (oscilloscope_params_t (left, base, height, num_samples, visible, folded));
}
return 1;
}
int oscilloscope::save () {
ofstream file ((user_data_dir + settingsf).c_str(), ios::out);
if (!file) return false;
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 << "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;
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
if (visible) show (); else hide ();
}
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.visible = visible;
op.folded = folded;
}
oscilloscope::~oscilloscope () {
save ();
delete[] vertex_array;
delete[] color_array;
}
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;
fld.set_pos (leftx - 1.5 * fld.size, base - fld.size);
}
void oscilloscope::set_height (int h) {
height = h;
calc_draw_params ();
}
void oscilloscope::set_num_samples (int n) {
num_samples = min (n, MAX_SAMPLES);
viewr = 0;
addr = 1;
calc_draw_params ();
}
int oscilloscope::handle_input () {
int result = fld.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[addr];
float l = outl[i], r = outr[i];
sa.left = l; sa.right = r;
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);
if (sample_t::lmin < -1 || sample_t::rmin < -1 || sample_t::lmax > 1 || sample_t::rmax > 1) limit = 1; else limit = 0;
if (++addr >= num_samples) addr = 0;
if (addr == viewr) {if (++viewr >= num_samples) viewr = 0;}
}
}
void oscilloscope::draw () {
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0, view.xmax, 0, view.ymax, -1, 1);
// calc left & right labels
if (++label_counter >= FPS) { // update labels once a second
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 = '@';
sprintf (lbuf1, "min %2.2f, max %2.2f %c", sample_t::lmin, sample_t::lmax, lb);
sprintf (rbuf1, "min %2.2f, max %2.2f %c", sample_t::rmin, sample_t::rmax, rb);
sample_t::lmin = sample_t::lmax = sample_t::rmin = sample_t::rmax = 0; // ok for oscilloscope.
label_counter = 0;
}
if (folded == 0) {
// draw left & right channels
int x1 = leftx, x2 = rightx, y0 = base;
glEnableClientState (GL_COLOR_ARRAY);
glVertexPointer (2, GL_INT, 0, vertex_array);
glColorPointer (4, GL_FLOAT, 0, color_array);
for (int i = 0, j = viewr, vi = 0, ci = 0; i < num_samples; ++i, vi += 8, ci += 16) {
float l = samples[j].left;
float r = samples[j].right;
int ly = (int)(l * win.height + 0.5);
int ry = (int)(r * win.height + 0.5);
// distortion is red
//
float lrr = lr, lgg = lg, lbb = lb;
if (l > 1 || l < -1) {lrr = 1; lgg = 0; lbb = 0;}
float rrr = rr, rgg = rg, rbb = rb;
if (r > 1 || r < -1) {rrr = 1; rgg = 0; rbb = 0;}
vertex_array [vi] = x1;
vertex_array [vi+1] = y0;
vertex_array [vi+2] = x1;
vertex_array [vi+3] = y0 + ly;
vertex_array [vi+4] = x2;
vertex_array [vi+5] = y0;
vertex_array [vi+6] = x2;
vertex_array [vi+7] = y0 + ry;
color_array [ci] = color_array[ci+4] = lrr;
color_array [ci+1] = color_array[ci+5] = lgg;
color_array [ci+2] = color_array[ci+6] = lbb;
color_array [ci+3] = color_array[ci+7] = 1;
color_array [ci+8] = color_array[ci+12] = rrr;
color_array [ci+9] = color_array[ci+13] = rgg;
color_array [ci+10] = color_array[ci+14] = rbb;
color_array [ci+11] = color_array[ci+15] = 1;
if (++j >= num_samples) j = 0;
++x1; ++x2;
}
glDrawArrays (GL_LINES, 0, ndraw);
glDisableClientState (GL_COLOR_ARRAY);
}
// left
glColor3f (lr , lg, lb);
draw_string (lbuf1, leftx, lly, 0);
glVertexPointer (2, GL_INT, 0, vertex_array);
vertex_array[0]=leftx;vertex_array[1]=win.midy;
vertex_array[2]=rightx;vertex_array[3]=win.midy;
glDrawArrays (GL_LINES, 0, 2);
// right
glColor3f (rr, rg, rb);
draw_string (rbuf1, rightx, lry, 0);
vertex_array[0]=rightx;vertex_array[1]=win.midy;
vertex_array[2]=endx;vertex_array[3]=win.midy;
glVertexPointer (2, GL_INT, 0, vertex_array);
glDrawArrays (GL_LINES, 0, 2);
fld.draw ();
}
void oscilloscope::set_folded (int f) {
folded = f;
if (folded) {
fld.set_direction (arrow_button::right);
} else {
fld.set_direction (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, int v, int f) {
left = l;
base = b;
height = h;
num_samples = ns;
visible = v;
folded = f;
}