Subversion Repositories DIN Is Noise

Rev

Rev 2302 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
964 jag 1
/*
2
* oscilloscope.cc
2302 jag 3
* DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath
1713 jag 4
* DIN Is Noise is released under GNU Public License 2.0
1479 jag 5
* For more information, please visit https://dinisnoise.org/
964 jag 6
*/
7
 
8
#include "dingl.h"
9
#include "oscilloscope.h"
10
#include "font.h"
11
#include "viewwin.h"
12
#include "input.h"
13
#include "log.h"
14
#include "console.h"
15
#include <string>
16
#include <algorithm>
17
using namespace std;
18
 
19
extern string user_data_dir;
20
extern int CURRENT_INSTRUMENT;
21
extern const int NUM_INSTRUMENTS;
22
extern int lmb;
23
extern int mousex, mouseyy;
24
extern viewport view;
25
extern int line_height;
26
 
1924 jag 27
oscilloscope::oscilloscope (const string& _settingsf) : win (0, 0, 2048, 250) {
1925 jag 28
  samples = 0;
1927 jag 29
  vertices = 0;
30
  colors = 0;
964 jag 31
  settingsf = _settingsf;
1927 jag 32
  fold.set_listener (this);
964 jag 33
  load ();
34
  px = py = -1;
35
  lmb_clicked = move = stop_move = 0;
36
  sample_t::lmin = sample_t::lmax = sample_t::rmin = sample_t::rmax = 0; // ok for oscilloscope.
2278 jag 37
  sprintf (lbuf1, "min %1.2f / max %1.2f", sample_t::lmin, sample_t::lmax);
38
  sprintf (rbuf1, "min %1.2f / max %1.2f", sample_t::rmin, sample_t::rmax);
1925 jag 39
  lr = 0; lg = lb = 1.0f;
40
  rr = rg = 1.0; rb = 0.0f;
1920 jag 41
  opacity = 1.0f;
2304 jag 42
  distort = 0;
964 jag 43
}
44
 
1924 jag 45
oscilloscope::~oscilloscope () {
46
  save ();
47
  delete[] samples;
1927 jag 48
  delete[] vertices;
49
  delete[] colors;
1924 jag 50
}
51
 
52
void oscilloscope::alloc (int n) {
1925 jag 53
  max_samples = n;
1924 jag 54
  if (samples) delete[] samples;
1927 jag 55
  if (vertices) delete[] vertices;
56
  if (colors) delete[] colors;
1925 jag 57
  samples = new sample_t [max_samples];
1927 jag 58
  vertices = new int [8 * max_samples];
59
  colors = new float [16 * max_samples];
1925 jag 60
  set_num_samples (num_samples);
1924 jag 61
}
62
 
2113 jag 63
int oscilloscope::set_num_samples (int n) {
1925 jag 64
  num_samples = min (n, max_samples);
65
  startsamp =  max_samples - num_samples;
66
  calc_draw_params ();
2113 jag 67
  return num_samples;
1925 jag 68
}
69
 
70
void oscilloscope::calc_draw_params () {
71
  base = win.midy;
72
  leftx = win.left;
73
  rightx = leftx + num_samples;
74
  endx = rightx + num_samples - 1;
75
  ndraw = 4 * num_samples;
76
  win (leftx, base - height, endx, base + height);
77
  int dheight = 5;
78
  pick_win (win.left, base - dheight, win.right, base + dheight);
79
  lh = line_height;
80
  lly = base - lh;
81
  lry = lly;
1927 jag 82
  fold.set_pos (leftx - 1.5 * fold.size, base - fold.size);
1925 jag 83
}
84
 
964 jag 85
int oscilloscope::load () {
86
  ifstream file ((user_data_dir + settingsf).c_str(), ios::in);
87
  if (!file) return 0;
88
  string ignore;
2278 jag 89
  file >> ignore >> updlbl.triggert;
964 jag 90
  for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
91
    file >> ignore >> left;
92
    file >> ignore >> base;
93
    file >> ignore >> height;
94
    file >> ignore >> num_samples;
1920 jag 95
    file >> ignore >> opacity;
964 jag 96
    file >> ignore >> visible;
97
    file >> ignore >> folded;
1920 jag 98
    params.push_back (oscilloscope_params_t (left, base, height, num_samples, opacity, visible, folded));
964 jag 99
  }
2278 jag 100
  updlbl.start ();
964 jag 101
  return 1;
102
}
103
 
104
int oscilloscope::save () {
105
  ofstream file ((user_data_dir + settingsf).c_str(), ios::out);
106
  if (!file) return false;
2278 jag 107
  file << "update-label-every " << updlbl.triggert << endl;
964 jag 108
  for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
109
    oscilloscope_params_t& op = params[i];
110
    file << "left " << op.left << endl;
111
    file << "base " << op.base << endl;
112
    file << "height " << op.height << endl;
113
    file << "num_samples " << op.num_samples << endl;
1920 jag 114
    file << "opacity " << op.opacity << endl;
964 jag 115
    file << "visible " << op.visible << endl;
116
    file << "folded " << op.folded << endl;
117
  }
118
  return 1;
119
}
120
 
121
void oscilloscope::load_current_instrument () {
122
  oscilloscope_params_t& op = params[CURRENT_INSTRUMENT];
123
  left = op.left;
124
  base = op.base;
125
  height = op.height;
126
  num_samples = op.num_samples;
1920 jag 127
  opacity = op.opacity;
1518 jag 128
  visible = op.visible;
964 jag 129
  folded = op.folded;
130
  win (left, base - height, left + 2 * num_samples, base + height);
131
  set_folded (folded);
132
  set_num_samples (num_samples); // calls calc_draw_params
133
}
134
 
135
void oscilloscope::save_current_instrument () {
136
  oscilloscope_params_t& op = params[CURRENT_INSTRUMENT];
137
  op.left = win.left;
138
  op.base = base;
139
  op.height = height;
140
  op.num_samples = num_samples;
1920 jag 141
  op.opacity = opacity;
964 jag 142
  op.visible = visible;
143
  op.folded = folded;
144
}
145
 
146
void oscilloscope::set_height (int h) {
147
  height = h;
148
  calc_draw_params ();
149
}
150
 
151
int oscilloscope::handle_input () {
152
 
1927 jag 153
  int result = fold.handle_input ();
964 jag 154
  if (result) return result;
155
 
156
  int x = mousex;
157
  int y = mouseyy;
158
 
159
  if (is_lmb (this)) {
160
    if (lmb_clicked == 0) {
161
      lmb_clicked = 1;
162
      if (move) {
163
        move = 0;
164
        stop_move = 1;
165
      } else if (inbox (pick_win, x, y)) { // pick_win is small window along zero line of oscilloscope
166
        move = 1;
167
        is_lmb.tie = this;
168
      }
169
    }
170
  } else {
171
    if (move) {
172
      int dx = x - px, dy = y - py;
173
      win.move (dx, dy);
174
      calc_draw_params ();
175
    } else if (stop_move) {
176
      stop_move = 0;
177
      is_lmb.clear (this);
178
    }
179
    lmb_clicked = 0;
180
  }
181
 
182
  px = x;
183
  py = y;
184
  result = move;
185
  return result;
186
}
187
 
188
void oscilloscope::add_samples (float* outl, float* outr, int n) {
1924 jag 189
 
964 jag 190
  for (int i = 0; i < n; ++i) {
1925 jag 191
    sample_t& sa = samples [i];
192
    sa.left = outl[i]; sa.right = outr[i];
964 jag 193
    sample_t::lmin = min (sa.left, sample_t::lmin);
194
    sample_t::lmax = max (sa.left, sample_t::lmax);
195
    sample_t::rmin = min (sa.right, sample_t::rmin);
196
    sample_t::rmax = max (sa.right, sample_t::rmax);
197
  }
1924 jag 198
 
2066 jag 199
  // used by mondrian
1927 jag 200
  float lm = sample_t::lmin * sample_t::rmin, rm = sample_t::lmax * sample_t::rmax;
201
  limit = (lm > 1 || rm > 1);
1924 jag 202
 
1925 jag 203
  {
204
    char lb = '.', rb = '.';
205
    float lsum = sample_t::lmin * sample_t::lmin + sample_t::lmax * sample_t::lmax;
206
    float rsum = sample_t::rmin * sample_t::rmin + sample_t::rmax * sample_t::rmax;
207
    if (lsum > rsum) lb = '@'; else if (rsum > lsum) rb = '@';
2278 jag 208
    if (updlbl (ui_clk())) {
209
      sprintf (lbuf1, "min %1.2f / max %1.2f %c", sample_t::lmin, sample_t::lmax, lb);
210
      sprintf (rbuf1, "min %1.2f / max %1.2f %c", sample_t::rmin, sample_t::rmax, rb);
211
      updlbl.start ();
212
    }
1925 jag 213
    sample_t::lmin = sample_t::lmax = sample_t::rmin = sample_t::rmax = 0;
214
  }
1924 jag 215
 
964 jag 216
  if (folded == 0) {
217
 
218
    int x1 = leftx, x2 = rightx, y0 = base;
1924 jag 219
    for (int i = 0, j = startsamp, vi = 0, ci = 0; i < num_samples; ++i, ++j, vi += 8, ci += 16) {
964 jag 220
 
221
      float l = samples[j].left;
1925 jag 222
      float r = samples[j].right;
964 jag 223
 
1925 jag 224
      int ly = int (l * win.height);
225
      int ry = int (r * win.height);
964 jag 226
 
1925 jag 227
      // distortion is red
228
      //
2304 jag 229
 
1920 jag 230
      float l2 = l * l;
964 jag 231
      float lrr = lr, lgg = lg, lbb = lb;
1920 jag 232
 
2304 jag 233
      if (l2 > 1.0f) {lrr = 1; lgg = 0; lbb = 0; distort = 1;}
234
 
964 jag 235
      float rrr = rr, rgg = rg, rbb = rb;
1920 jag 236
      float r2 = r * r;
2304 jag 237
      if (r2 > 1.0f) {rrr = 1; rgg = 0; rbb = 0; distort = 1;}
964 jag 238
 
1927 jag 239
      vertices [vi] = x1;
240
      vertices [vi+1] = y0;
241
      vertices [vi+2] = x1;
242
      vertices [vi+3] = y0 + ly;
243
      vertices [vi+4] = x2;
244
      vertices [vi+5] = y0;
245
      vertices [vi+6] = x2;
246
      vertices [vi+7] = y0 + ry;
964 jag 247
 
1927 jag 248
      colors [ci] = colors[ci+4] = lrr;
249
      colors [ci+1] = colors[ci+5] = lgg;
250
      colors [ci+2] = colors[ci+6] = lbb;
251
      colors [ci+3] = colors[ci+7] = opacity;
252
      colors [ci+8] = colors[ci+12] = rrr;
253
      colors [ci+9] = colors[ci+13] = rgg;
254
      colors [ci+10] = colors[ci+14] = rbb;
255
      colors [ci+11] = colors[ci+15] = opacity;
964 jag 256
 
257
      ++x1; ++x2;
1925 jag 258
 
964 jag 259
    }
1925 jag 260
 
261
  }
262
 
263
}
264
 
265
void oscilloscope::draw () {
266
 
267
  if (folded == 0) {
1927 jag 268
    // draw samples
269
    //
1925 jag 270
    glEnable (GL_BLEND);
271
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1146 jag 272
    glEnableClientState (GL_COLOR_ARRAY);
1927 jag 273
    glColorPointer (4, GL_FLOAT, 0, colors);
274
    glVertexPointer (2, GL_INT, 0, vertices);
964 jag 275
    glDrawArrays (GL_LINES, 0, ndraw);
276
    glDisableClientState (GL_COLOR_ARRAY);
1920 jag 277
    glDisable (GL_BLEND);
1927 jag 278
 
964 jag 279
  }
280
 
1927 jag 281
  // draw L and R labels 
282
  //
2304 jag 283
  if (limit) glColor3f (1, 0, 0); else glColor3f (lr , lg, lb);
964 jag 284
  draw_string (lbuf1, leftx, lly, 0);
1920 jag 285
  glBegin (GL_LINES);
286
    glVertex2i (leftx, win.midy);
287
    glVertex2i (rightx, win.midy);
288
  glEnd ();
964 jag 289
 
2304 jag 290
  if (limit) glColor3f (1, 0, 0); else glColor3f (rr, rg, rb);
2278 jag 291
  draw_string (rbuf1, rightx, lry, 0);
1920 jag 292
  glBegin (GL_LINES);
293
    glVertex2i (rightx, win.midy);
294
    glVertex2i (endx, win.midy);
295
  glEnd ();
964 jag 296
 
2304 jag 297
  //distort = 0;
298
 
1927 jag 299
  fold.draw ();
964 jag 300
 
301
}
302
 
303
void oscilloscope::set_folded (int f) {
304
  folded = f;
305
  if (folded) {
1927 jag 306
    fold.set_dir (arrow_button::right);
964 jag 307
  } else {
1927 jag 308
    fold.set_dir (arrow_button::up);
964 jag 309
  }
310
}
311
 
312
void oscilloscope::clicked (button& b) {
313
  set_folded (!folded);
314
}
315
 
1920 jag 316
oscilloscope_params_t::oscilloscope_params_t (int l, int b, int h, int ns, float op, int v, int f) {
964 jag 317
  left = l;
318
  base = b;
319
  height = h;
320
  num_samples = ns;
1920 jag 321
  opacity = op;
964 jag 322
  visible = v;
323
  folded = f;
324
}