]> Shamusworld >> Repos - wozmaker/blob - src/waveformwidget.cpp
Add "settings" dialog, fixes to work with MXE cross-compilation.
[wozmaker] / src / waveformwidget.cpp
1 //
2 // waveformwidget.cpp: Track waveform window widget
3 //
4 // Part of the WOZ Maker project
5 // by James Hammons
6 // (C) 2018 Underground Software
7 //
8
9 #include "waveformwidget.h"
10 #include <math.h>
11 #include "dsp.h"
12 #include "fileio.h"
13 #include "global.h"
14
15
16 // Local variables
17 static uint32_t slip[6];
18 static bool foundBad = false;
19
20
21 WaveformWidget::WaveformWidget(QWidget * parent/*= 0*/): QWidget(parent)
22 {
23 #if 0
24         setGeometry(QRect(0, 0, 20, 240));
25         setMinimumHeight(240);
26         setMaximumHeight(240);
27 #else
28         setGeometry(QRect(0, 0, 20, 320));
29         setMinimumHeight(320);
30         setMaximumHeight(320);
31 #endif
32 }
33
34
35 WaveformWidget::~WaveformWidget(void)
36 {
37 }
38
39
40 void WaveformWidget::HandleUpdate(void)
41 {
42         // Set up vars that only change when the track changes...
43         uint32_t total = 0;
44         Global::streamCount = 0;
45         memset(slip, 0, sizeof(slip));
46         uint32_t xmax = 0;
47
48         // Find all non-BITS stream captures for this quarter-track
49         for(uint32_t i=0; i<Global::numStreams; i++)
50         {
51                 if ((Global::stream[i]->location != Global::trackNum)
52                         || (Global::stream[i]->captureType == 2))
53                         continue;
54
55                 uint32_t timeToNext = 0;
56                 uint32_t trackBytes = Uint32LE(Global::stream[i]->dataLength);
57
58                 // Set up stream vars for this track
59                 Global::streamData[Global::streamCount] = Global::stream[i]->data;
60                 Global::streamLen[Global::streamCount++] = trackBytes;
61
62                 // Save the stream number for later reference
63                 sNum[total++] = i;
64
65                 // Count time for this stream (skipping 0, because it doesn't count)
66                 for(uint32_t j=1; j<trackBytes; j++)
67                         timeToNext += Global::stream[i]->data[j];
68
69                 if ((timeToNext / 2) > xmax)
70                         xmax = timeToNext / 2;
71         }
72
73         Global::swLen = 0;
74
75 // !!! FIX !!! Need to take this out so it uses the already synthesized stuff done in the parallel thread...
76         if (Global::streamCount > 1)
77         {
78                 // Try aligning streams algorithmically...
79 //              FindSyncForStreams(slip, Global::streamCount);
80                 FindInitialSyncForStreams2(slip, Global::streamCount);
81 //              InitialSync(slip, Global::streamCount);
82 //              AttemptToFindStart(slip, Global::streamCount);
83                 Global::swLen = Synthesize2(slip, Global::streamCount, Global::synthWave, Global::swAmplitude);
84         }
85
86 for(uint32_t i=0; i<Global::streamCount; i++)
87 {       printf("Sync point %d: %d\n", sNum[i], slip[i]); }
88
89 #if 0
90 printf("Lookahead for track %.2f: %d\n", (float)Global::trackNum / 4.0f, Lookahead(slip, Global::streamCount, +1));
91 #endif
92
93         // And finally, update the display
94         setMinimumWidth(xmax);
95         setMaximumWidth(xmax);
96         update();
97 }
98
99
100 //#define PACKED
101 void WaveformWidget::HandleInitSync(void)
102 {
103 #ifdef PACKED
104         FindInitialSyncForStreams(slip, Global::streamCount);
105 #endif
106         foundBad = false;
107         update();
108
109 #if 1
110         printf("------------------------------\nInitial sync (%.2f): ", (float)Global::trackNum / 4.0f);
111         for(uint32_t i=0; i<Global::streamCount; i++)
112                 printf("<%d> ", slip[i]);
113         printf("\n\n");
114 #endif
115 }
116
117
118 void WaveformWidget::HandleStepBack(void)
119 {
120 #ifdef PACKED
121         static double a[10];
122 #endif
123         uint32_t minIdx = SmallestIndex(slip, Global::streamCount);
124
125         if (slip[minIdx] == 0)
126                 return;
127
128         if (!foundBad)
129         {
130 #ifdef PACKED
131                 StepBackUntilBad(slip, a, Global::streamCount);
132 #endif
133                 foundBad = true;
134
135                 for(uint32_t i=0; i<Global::streamCount; i++)
136                         printf("<%d> ", slip[i]);
137                 printf("\n");
138         }
139         else
140         {
141 #ifdef PACKED
142                 foundBad = StepBackThruBad(slip, a, Global::streamCount);
143 #endif
144         }
145
146         update();
147 }
148
149
150 void WaveformWidget::HandleManualSync(void)
151 {
152 #ifdef PACKED
153         double a[10];
154 #endif
155         foundBad = false;
156 #ifdef PACKED
157         StepBack(slip, a, Global::streamCount);
158 #endif
159         update();
160
161 #if 1
162         printf("------------------------------\nManual sync (%.2f): ", (float)Global::trackNum / 4.0f);
163         for(uint32_t i=0; i<Global::streamCount; i++)
164                 printf("<%d> ", slip[i]);
165         printf("\n\n");
166 #endif
167 }
168
169
170 void WaveformWidget::HandleZeroAll(void)
171 {
172         memset(slip, 0, sizeof(slip));
173         update();
174 }
175
176
177 void WaveformWidget::HandleSynthesize(void)
178 {
179 //      Global::swLen = Synthesize(slip, Global::streamCount, Global::synthWave, Global::swAmplitude);
180         Global::swLen = Synthesize2(slip, Global::streamCount, Global::synthWave, Global::swAmplitude);
181         emit(UpdateInfo());
182         update();
183 }
184
185
186 void WaveformWidget::HandleSynthesize2(void)
187 {
188         SynthesizeTrack(Global::trackNum);
189 //      emit(UpdateInfo());
190         update();
191 }
192
193
194 void WaveformWidget::HandleSync(int stream, int num)
195 {
196         if (stream > 9)
197                 return;
198
199         slip[stream] = num;
200         update();
201 }
202
203
204 void WaveformWidget::HandleWaveSync(int num)
205 {
206         Global::waveSync = num;
207         update();
208 }
209
210
211 void WaveformWidget::HandleRatio(int /*stream*/, int /*num*/)
212 {
213 //      if (stream > 9)
214 //              return;
215
216 //      ratio[stream] = (double)num / 1600000.0;
217         update();
218 }
219
220
221 /*
222 Now we have SynthesizeTrack(trackNo), so we can display the results of that here--including the loop point if we found one...
223
224 Now our analysis thread calcs it for us...  One less thing to worry about!
225 */
226
227 void WaveformWidget::paintEvent(QPaintEvent * event)
228 {
229         if (Global::a2r == NULL)
230                 return;
231
232         uint32_t xpos = event->rect().x();
233         uint32_t width = event->rect().width();
234
235         QPainter painter(this);
236         painter.setRenderHint(QPainter::Antialiasing);
237         QFont font;
238
239         font.setPixelSize(12);
240         font.setBold(true);
241         font.setStyleHint(QFont::TypeWriter);
242         painter.setFont(font);
243
244         QPen greenPen(QColor(0x66, 0x9E, 0x55, 0xFF), 2.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
245         QPen bluePen(QColor(0x20, 0x8F, 0xB5, 0xFF), 2.0, Qt::SolidLine);
246         QPen whitePen(Qt::white, 2.0, Qt::SolidLine);
247         QPen greyPen(QColor(0x4F, 0x49, 0x47, 0xFF), 2.0, Qt::SolidLine);
248         QPen orangePen(QColor(0xDE, 0x6A, 0x00, 0xFF), 2.0, Qt::SolidLine);
249
250 //BG: 3B3632, GRN: 669E55, BLU: 208FB5, V.Lines: 4F4947
251 // 12 (line + hex num), 3 space, 18 for trace, 7 after space
252 // 7px padding on top, 8px on bottom
253 // Nibble view is 52 x 12 bytes
254
255 //      float y = 7 + 12 + 18;
256         float y = 7 + 12 + 18 + (40 * 3);
257         float drawXPos = (xpos < 8 ? 0 : xpos - 8);
258         uint32_t wfNum = 0;
259
260 //printf("update: ");
261         for(uint32_t j=0; j<Global::numStreams; j++)
262         {
263                 if (Global::stream[j]->location != Global::trackNum)
264                         continue;
265
266                 float x = 0;
267                 float lastx = 0;
268 //              uint32_t trackBytes = Uint32LE(Global::stream[j]->dataLength);
269                 uint32_t trackBytes = Global::waveLen[j] - slip[wfNum];
270                 uint32_t estSplice = Uint32LE(Global::stream[j]->estLoopPoint);
271                 uint32_t byte = 1;
272                 uint32_t bytePos = 0;
273                 uint32_t bitCount = 1;
274 //              int32_t extra = (foundBad ? -1 : 0);
275                 uint32_t offset = slip[wfNum];
276 //printf("<%d> ", offset);
277
278                 if ((Global::stream[j]->captureType == 1) || (Global::stream[j]->captureType == 3))
279                 {
280                         for(uint32_t i=0; i<trackBytes; i++)
281                         {
282 #if 0
283                                 uint32_t timeToNext = Global::stream[j]->data[offset + i];
284
285                                 while (Global::stream[j]->data[offset + i] == 0xFF)
286                                 {
287                                         i++;
288                                         timeToNext += Global::stream[j]->data[offset + i];
289                                 }
290 #else
291                                 uint32_t timeToNext = Global::wave[j][offset + i];
292 #endif
293
294 //                              if (i > 0)
295         //                              x += timeToNext / 2;
296                                         x += ((double)timeToNext / 2.0);// * ratio[wfNum];
297
298 //                              if ((Global::stream[j]->data[offset + i] > 24) || (i == 0))
299                                 {
300                                         if (x >= drawXPos)
301                                         {
302                                                 painter.setPen(bluePen);
303
304                                                 if (x >= ((estSplice / 2) /* * ratio[wfNum]*/))
305                                                         painter.setPen(Qt::magenta);
306
307                                                 painter.drawLine(lastx, y, x, y);
308                                                 painter.drawLine(x, y, x + 4.0, y);
309                                                 painter.drawLine(x + 4.0, y, x + 4.0, y - 17.0);
310                                                 painter.drawLine(x + 4.0, y - 17.0, x + 8.0, y - 17.0);
311                                                 painter.drawLine(x + 8.0, y - 17.0, x + 8.0, y);
312                                                 lastx = x + 8.0;
313                                         }
314
315 //                                      if (i == 0)
316 //                                      {
317 //                                              byte = 1;
318 //                                              bitCount = 1;
319 //                                              bytePos = x;
320 //                                      }
321 //                                      else
322                                         {
323                                                 if ((timeToNext >= 24) && (timeToNext <= 49))
324                                                 {
325                                                         byte = (byte << 1) | 1;
326                                                         bitCount++;
327                                                 }
328                                                 else if ((timeToNext >= 50) && (timeToNext <= 80))
329                                                 {
330                                                         byte = (byte << 2) | 1;
331                                                         bitCount += 2;
332                                                 }
333                                                 else if ((timeToNext >= 81) && (timeToNext <= 112))
334                                                 {
335                                                         byte = (byte << 3) | 1;
336                                                         bitCount += 3;
337                                                 }
338                                                 else if ((timeToNext >= 113) && (timeToNext <= 137))
339                                                 {
340                                                         byte = (byte << 4) | 1;
341                                                         bitCount += 4;
342                                                 }
343                                                 else
344                                                 {
345                                                         // Handle zeros here...
346                                                         while (timeToNext > 32)
347                                                         {
348                                                                 byte <<= 1;
349                                                                 bitCount++;
350                                                                 timeToNext -= 32;
351                                                         }
352                                                 }
353                                         }
354
355                                         if (bitCount > 8)
356                                         {
357                                                 while (bitCount > 15)
358                                                         bitCount -= 8;
359
360                                                 uint16_t mask1[16] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF };
361                                                 uint16_t mask2[16] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 };
362                                                 uint8_t byteToShow = byte >> (bitCount - 8);
363                                                 bitCount -= 8;
364                                                 byte &= mask1[bitCount];
365                                                 uint8_t zeroes = 0;
366
367                                                 for(uint16_t z=bitCount; z>0; z--)
368                                                 {
369                                                         if ((byte & mask2[z - 1]) == 0)
370                                                         {
371                                                                 bitCount--;
372                                                                 zeroes++;
373                                                         }
374                                                         else
375                                                                 break;
376                                                 }
377
378                                                 char buf[10];
379                                                 sprintf(buf, "|%02X%s", byteToShow, (zeroes == 0 ? "" : (zeroes == 1 ? "." : (zeroes == 2 ? ".." : "..."))));
380
381                                                 painter.setPen(whitePen);
382                                                 painter.drawText(bytePos, y - (18 + 6), buf);
383
384                                                 bytePos = x;
385
386                                                 if (bytePos > (xpos + width))
387                                                         break;
388                                         }
389                                 }
390                         }
391                 }
392                 else if (Global::stream[j]->captureType == 2)
393                 {
394                         // BITS capture
395 /*
396 x positions are 16 pix apart, ideally.  So to get the # of bits, we need to divide the width / 16.  To get the # of bytes, we then divide by 8.
397 */
398                         uint32_t bpStart = xpos / 16;
399                         x = bpStart * 16.0;
400
401                         for(uint32_t i=bpStart; i<bpStart+(width/16)+4; i++)
402                         {
403                                 if (Global::stream[j]->data[i / 8] & Global::bit[i % 8])
404                                 {
405                                         painter.setPen(Qt::cyan);
406                                         painter.drawLine(lastx, y, x, y);
407                                         painter.drawLine(x, y, x + 4, y);
408                                         painter.drawLine(x + 4, y, x + 4, y - 17);
409                                         painter.drawLine(x + 4, y - 17, x + 8, y - 17);
410                                         painter.drawLine(x + 8, y - 17, x + 8, y);
411                                         lastx = x + 8.0;
412                                 }
413
414                                 x += 16.0;
415                         }
416                 }
417
418                 y += 40.0;
419                 wfNum++;
420         }
421 //printf("\n");
422
423         if (Global::swLen == 0)
424                 return;
425
426         // Reset Y coord to the top
427         y = 7 + 12 + 18;
428         float x = 0;
429         float lastx = 0;
430         uint32_t byte = 1;
431         uint32_t bytePos = x;
432         uint32_t bitCount = 1;
433         float hgt = 17.0f * 1.0f;
434
435         painter.setPen(greenPen);
436         painter.drawLine(lastx, y, x, y);
437         painter.drawLine(x, y, x + 4.0, y);
438         painter.drawLine(x + 4.0, y, x + 4.0, y - hgt);
439         painter.drawLine(x + 4.0, y - hgt, x + 8.0, y - hgt);
440         painter.drawLine(x + 8.0, y - hgt, x + 8.0, y);
441         lastx = x + 8.0;
442
443         for(uint32_t i=0; i<Global::swLen; i++)
444         {
445                 uint32_t timeToNext = Global::synthWave[i];
446                 hgt = 17.0 * Global::swAmplitude[i];
447                 x += (double)timeToNext / 2.0;
448
449                 if ((timeToNext > 0) || (i == 0))
450                 {
451                         if (x >= drawXPos)
452                         {
453                                 painter.setPen(greenPen);
454                                 painter.drawLine(lastx, y, x, y);
455                                 painter.drawLine(x, y, x + 4.0, y);
456                                 painter.drawLine(x + 4.0, y, x + 4.0, y - hgt);
457                                 painter.drawLine(x + 4.0, y - hgt, x + 8.0, y - hgt);
458                                 painter.drawLine(x + 8.0, y - hgt, x + 8.0, y);
459                                 lastx = x + 8.0;
460                         }
461
462                         if ((timeToNext >= 24) && (timeToNext <= 49))
463                         {
464                                 byte = (byte << 1) | 1;
465                                 bitCount++;
466                         }
467                         else if ((timeToNext >= 50) && (timeToNext <= 80))
468                         {
469                                 byte = (byte << 2) | 1;
470                                 bitCount += 2;
471                         }
472                         else if ((timeToNext >= 81) && (timeToNext <= 112))
473                         {
474                                 byte = (byte << 3) | 1;
475                                 bitCount += 3;
476                         }
477                         else if ((timeToNext >= 113) && (timeToNext <= 137))
478                         {
479                                 byte = (byte << 4) | 1;
480                                 bitCount += 4;
481                         }
482                         else
483                         {
484                                 // Handle zeros here...
485                                 while (timeToNext > 32)
486                                 {
487                                         byte <<= 1;
488                                         bitCount++;
489                                         timeToNext -= 32;
490                                 }
491                         }
492
493                         if (bitCount > 8)
494                         {
495                                 while (bitCount > 15)
496                                         bitCount -= 8;
497
498                                 uint16_t mask1[16] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF };
499                                 uint16_t mask2[16] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 };
500                                 uint8_t byteToShow = byte >> (bitCount - 8);
501                                 bitCount -= 8;
502                                 byte &= mask1[bitCount];
503                                 uint8_t zeroes = 0;
504
505                                 for(uint16_t z=bitCount; z>0; z--)
506                                 {
507                                         if ((byte & mask2[z - 1]) == 0)
508                                         {
509                                                 bitCount--;
510                                                 zeroes++;
511                                         }
512                                         else
513                                                 break;
514                                 }
515
516                                 char buf[10];
517                                 sprintf(buf, "|%02X%s", byteToShow, (zeroes == 0 ? "" : (zeroes == 1 ? "." : (zeroes == 2 ? ".." : "..."))));
518
519                                 painter.setPen(whitePen);
520                                 painter.drawText(bytePos, y - (18 + 6), buf);
521
522                                 bytePos = x;
523
524                                 if (bytePos > (xpos + width))
525                                         break;
526                         }
527                 }
528         }
529
530         if (Global::synWaveLen[Global::trackNum] == 0)
531                 return;
532
533         // Reset Y coord to the top
534         y = 7 + 12 + 18 + (40 * 1);
535         x = 0;
536         lastx = 0;
537
538         painter.setPen(orangePen);
539         painter.drawLine(lastx, y, x, y);
540         painter.drawLine(x, y, x + 4.0, y);
541         painter.drawLine(x + 4.0, y, x + 4.0, y - 17.0f);
542         painter.drawLine(x + 4.0, y - 17.0f, x + 8.0, y - 17.0f);
543         painter.drawLine(x + 8.0, y - 17.0f, x + 8.0, y);
544         lastx = x + 8.0;
545
546         for(uint32_t i=0; i<Global::synWaveLen[Global::trackNum]; i++)
547         {
548                 uint32_t timeToNext = Global::synWave[Global::trackNum][i];
549                 x += (double)timeToNext / 2.0;
550
551                 if (x >= drawXPos)
552                 {
553                         painter.setPen(orangePen);
554                         painter.drawLine(lastx, y, x, y);
555                         painter.drawLine(x, y, x + 4.0, y);
556                         painter.drawLine(x + 4.0, y, x + 4.0, y - 17.0f);
557                         painter.drawLine(x + 4.0, y - 17.0f, x + 8.0, y - 17.0f);
558                         painter.drawLine(x + 8.0, y - 17.0f, x + 8.0, y);
559                         lastx = x + 8.0;
560                 }
561
562                 char buf[10];
563
564                 if ((i % 10) == 0)
565                 {
566                         sprintf(buf, "|%d", i + 1);
567                         painter.setPen(whitePen);
568                         painter.drawText(x, y - (18 + 6), buf);
569                 }
570
571                 if (x > (xpos + width))
572                         break;
573         }
574
575         y = 7 + 12 + 18 + (40 * 2);
576         x = 0;
577         lastx = 0;
578
579         painter.setPen(orangePen);
580         painter.drawLine(lastx, y, x, y);
581         painter.drawLine(x, y, x + 4.0, y);
582         painter.drawLine(x + 4.0, y, x + 4.0, y - 17.0f);
583         painter.drawLine(x + 4.0, y - 17.0f, x + 8.0, y - 17.0f);
584         painter.drawLine(x + 8.0, y - 17.0f, x + 8.0, y);
585         lastx = x + 8.0;
586
587         for(uint32_t i=Global::waveSync; i<Global::synWaveLen[Global::trackNum]; i++)
588         {
589                 uint32_t timeToNext = Global::synWave[Global::trackNum][i];
590                 x += (double)timeToNext / 2.0;
591
592                 if (x >= drawXPos)
593                 {
594                         painter.setPen(orangePen);
595                         painter.drawLine(lastx, y, x, y);
596                         painter.drawLine(x, y, x + 4.0, y);
597                         painter.drawLine(x + 4.0, y, x + 4.0, y - 17.0f);
598                         painter.drawLine(x + 4.0, y - 17.0f, x + 8.0, y - 17.0f);
599                         painter.drawLine(x + 8.0, y - 17.0f, x + 8.0, y);
600                         lastx = x + 8.0;
601                 }
602
603                 char buf[10];
604
605                 if ((i % 10) == 0)
606                 {
607                         sprintf(buf, "|%d", i + 1);
608                         painter.setPen(whitePen);
609                         painter.drawText(x, y - (18 + 6), buf);
610                 }
611
612                 if (x > (xpos + width))
613                         break;
614         }
615 }
616
617
618 void WaveformWidget::mousePressEvent(QMouseEvent * event)
619 {
620         if (event->button() == Qt::LeftButton)
621         {
622                 event->accept();
623         }
624 }
625
626
627 void WaveformWidget::mouseMoveEvent(QMouseEvent * event)
628 {
629         if (event->buttons() & Qt::LeftButton)
630         {
631                 event->accept();
632         }
633 }
634
635
636 void WaveformWidget::mouseReleaseEvent(QMouseEvent * event)
637 {
638         if (event->button() == Qt::LeftButton)
639         {
640                 event->accept();
641         }
642 }
643
644
645 void WaveformWidget::mouseDoubleClickEvent(QMouseEvent * event)
646 {
647         if (event->button() == Qt::LeftButton)
648         {
649                 event->accept();
650         }
651 }
652
653
654 void WaveformWidget::keyPressEvent(QKeyEvent * event)
655 {
656         int key = event->key();
657
658         if (key == Qt::Key_Up)
659         {
660         }
661         else if (key == Qt::Key_Down)
662         {
663         }
664         else if (key == Qt::Key_Left)
665         {
666         }
667         else if (key == Qt::Key_Right)
668         {
669         }
670         else
671                 return;
672
673         // Only update if a key we recognize has been pressed!
674         update();
675 }
676
677
678 void WaveformWidget::keyReleaseEvent(QKeyEvent * /*event*/)
679 {
680 }
681
682
683 void WaveformWidget::resizeEvent(QResizeEvent * /*event*/)
684 {
685 //      ResizeGrid();
686 }
687