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