2 // waveformwidget.cpp: Track waveform window widget
4 // Part of the WOZ Maker project
6 // (C) 2018 Underground Software
9 #include "waveformwidget.h"
17 static uint32_t slip[6];
18 static bool foundBad = false;
21 WaveformWidget::WaveformWidget(QWidget * parent/*= 0*/): QWidget(parent)
24 setGeometry(QRect(0, 0, 20, 240));
25 setMinimumHeight(240);
26 setMaximumHeight(240);
28 setGeometry(QRect(0, 0, 20, 320));
29 setMinimumHeight(320);
30 setMaximumHeight(320);
35 WaveformWidget::~WaveformWidget(void)
40 void WaveformWidget::HandleUpdate(void)
42 // Set up vars that only change when the track changes...
44 Global::streamCount = 0;
45 memset(slip, 0, sizeof(slip));
48 // Find all non-BITS stream captures for this quarter-track
49 for(uint32_t i=0; i<Global::numStreams; i++)
51 if ((Global::stream[i]->location != Global::trackNum)
52 || (Global::stream[i]->captureType == 2))
55 uint32_t timeToNext = 0;
56 uint32_t trackBytes = Uint32LE(Global::stream[i]->dataLength);
58 // Set up stream vars for this track
59 Global::streamData[Global::streamCount] = Global::stream[i]->data;
60 Global::streamLen[Global::streamCount++] = trackBytes;
62 // Save the stream number for later reference
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];
69 if ((timeToNext / 2) > xmax)
70 xmax = timeToNext / 2;
75 // !!! FIX !!! Need to take this out so it uses the already synthesized stuff done in the parallel thread...
76 if (Global::streamCount > 1)
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);
86 for(uint32_t i=0; i<Global::streamCount; i++)
87 { printf("Sync point %d: %d\n", sNum[i], slip[i]); }
90 printf("Lookahead for track %.2f: %d\n", (float)Global::trackNum / 4.0f, Lookahead(slip, Global::streamCount, +1));
93 // And finally, update the display
94 setMinimumWidth(xmax);
95 setMaximumWidth(xmax);
101 void WaveformWidget::HandleInitSync(void)
104 FindInitialSyncForStreams(slip, Global::streamCount);
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]);
118 void WaveformWidget::HandleStepBack(void)
123 uint32_t minIdx = SmallestIndex(slip, Global::streamCount);
125 if (slip[minIdx] == 0)
131 StepBackUntilBad(slip, a, Global::streamCount);
135 for(uint32_t i=0; i<Global::streamCount; i++)
136 printf("<%d> ", slip[i]);
142 foundBad = StepBackThruBad(slip, a, Global::streamCount);
150 void WaveformWidget::HandleManualSync(void)
157 StepBack(slip, a, Global::streamCount);
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]);
170 void WaveformWidget::HandleZeroAll(void)
172 memset(slip, 0, sizeof(slip));
177 void WaveformWidget::HandleSynthesize(void)
179 // Global::swLen = Synthesize(slip, Global::streamCount, Global::synthWave, Global::swAmplitude);
180 Global::swLen = Synthesize2(slip, Global::streamCount, Global::synthWave, Global::swAmplitude);
186 void WaveformWidget::HandleSynthesize2(void)
188 SynthesizeTrack(Global::trackNum);
189 // emit(UpdateInfo());
194 void WaveformWidget::HandleSync(int stream, int num)
204 void WaveformWidget::HandleWaveSync(int num)
206 Global::waveSync = num;
211 void WaveformWidget::HandleRatio(int /*stream*/, int /*num*/)
216 // ratio[stream] = (double)num / 1600000.0;
222 Now we have SynthesizeTrack(trackNo), so we can display the results of that here--including the loop point if we found one...
224 Now our analysis thread calcs it for us... One less thing to worry about!
227 void WaveformWidget::paintEvent(QPaintEvent * event)
229 if (Global::a2r == NULL)
232 uint32_t xpos = event->rect().x();
233 uint32_t width = event->rect().width();
235 QPainter painter(this);
236 painter.setRenderHint(QPainter::Antialiasing);
239 font.setPixelSize(12);
241 font.setStyleHint(QFont::TypeWriter);
242 painter.setFont(font);
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);
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
255 // float y = 7 + 12 + 18;
256 float y = 7 + 12 + 18 + (40 * 3);
257 float drawXPos = (xpos < 8 ? 0 : xpos - 8);
260 //printf("update: ");
261 for(uint32_t j=0; j<Global::numStreams; j++)
263 if (Global::stream[j]->location != Global::trackNum)
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);
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);
278 if ((Global::stream[j]->captureType == 1) || (Global::stream[j]->captureType == 3))
280 for(uint32_t i=0; i<trackBytes; i++)
283 uint32_t timeToNext = Global::stream[j]->data[offset + i];
285 while (Global::stream[j]->data[offset + i] == 0xFF)
288 timeToNext += Global::stream[j]->data[offset + i];
291 uint32_t timeToNext = Global::wave[j][offset + i];
295 // x += timeToNext / 2;
296 x += ((double)timeToNext / 2.0);// * ratio[wfNum];
298 // if ((Global::stream[j]->data[offset + i] > 24) || (i == 0))
302 painter.setPen(bluePen);
304 if (x >= ((estSplice / 2) /* * ratio[wfNum]*/))
305 painter.setPen(Qt::magenta);
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);
323 if ((timeToNext >= 24) && (timeToNext <= 49))
325 byte = (byte << 1) | 1;
328 else if ((timeToNext >= 50) && (timeToNext <= 80))
330 byte = (byte << 2) | 1;
333 else if ((timeToNext >= 81) && (timeToNext <= 112))
335 byte = (byte << 3) | 1;
338 else if ((timeToNext >= 113) && (timeToNext <= 137))
340 byte = (byte << 4) | 1;
345 // Handle zeros here...
346 while (timeToNext > 32)
357 while (bitCount > 15)
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);
364 byte &= mask1[bitCount];
367 for(uint16_t z=bitCount; z>0; z--)
369 if ((byte & mask2[z - 1]) == 0)
379 sprintf(buf, "|%02X%s", byteToShow, (zeroes == 0 ? "" : (zeroes == 1 ? "." : (zeroes == 2 ? ".." : "..."))));
381 painter.setPen(whitePen);
382 painter.drawText(bytePos, y - (18 + 6), buf);
386 if (bytePos > (xpos + width))
392 else if (Global::stream[j]->captureType == 2)
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.
398 uint32_t bpStart = xpos / 16;
401 for(uint32_t i=bpStart; i<bpStart+(width/16)+4; i++)
403 if (Global::stream[j]->data[i / 8] & Global::bit[i % 8])
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);
423 if (Global::swLen == 0)
426 // Reset Y coord to the top
431 uint32_t bytePos = x;
432 uint32_t bitCount = 1;
433 float hgt = 17.0f * 1.0f;
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);
443 for(uint32_t i=0; i<Global::swLen; i++)
445 uint32_t timeToNext = Global::synthWave[i];
446 hgt = 17.0 * Global::swAmplitude[i];
447 x += (double)timeToNext / 2.0;
449 if ((timeToNext > 0) || (i == 0))
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);
462 if ((timeToNext >= 24) && (timeToNext <= 49))
464 byte = (byte << 1) | 1;
467 else if ((timeToNext >= 50) && (timeToNext <= 80))
469 byte = (byte << 2) | 1;
472 else if ((timeToNext >= 81) && (timeToNext <= 112))
474 byte = (byte << 3) | 1;
477 else if ((timeToNext >= 113) && (timeToNext <= 137))
479 byte = (byte << 4) | 1;
484 // Handle zeros here...
485 while (timeToNext > 32)
495 while (bitCount > 15)
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);
502 byte &= mask1[bitCount];
505 for(uint16_t z=bitCount; z>0; z--)
507 if ((byte & mask2[z - 1]) == 0)
517 sprintf(buf, "|%02X%s", byteToShow, (zeroes == 0 ? "" : (zeroes == 1 ? "." : (zeroes == 2 ? ".." : "..."))));
519 painter.setPen(whitePen);
520 painter.drawText(bytePos, y - (18 + 6), buf);
524 if (bytePos > (xpos + width))
530 if (Global::synWaveLen[Global::trackNum] == 0)
533 // Reset Y coord to the top
534 y = 7 + 12 + 18 + (40 * 1);
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);
546 for(uint32_t i=0; i<Global::synWaveLen[Global::trackNum]; i++)
548 uint32_t timeToNext = Global::synWave[Global::trackNum][i];
549 x += (double)timeToNext / 2.0;
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);
566 sprintf(buf, "|%d", i + 1);
567 painter.setPen(whitePen);
568 painter.drawText(x, y - (18 + 6), buf);
571 if (x > (xpos + width))
575 y = 7 + 12 + 18 + (40 * 2);
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);
587 for(uint32_t i=Global::waveSync; i<Global::synWaveLen[Global::trackNum]; i++)
589 uint32_t timeToNext = Global::synWave[Global::trackNum][i];
590 x += (double)timeToNext / 2.0;
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);
607 sprintf(buf, "|%d", i + 1);
608 painter.setPen(whitePen);
609 painter.drawText(x, y - (18 + 6), buf);
612 if (x > (xpos + width))
618 void WaveformWidget::mousePressEvent(QMouseEvent * event)
620 if (event->button() == Qt::LeftButton)
627 void WaveformWidget::mouseMoveEvent(QMouseEvent * event)
629 if (event->buttons() & Qt::LeftButton)
636 void WaveformWidget::mouseReleaseEvent(QMouseEvent * event)
638 if (event->button() == Qt::LeftButton)
645 void WaveformWidget::mouseDoubleClickEvent(QMouseEvent * event)
647 if (event->button() == Qt::LeftButton)
654 void WaveformWidget::keyPressEvent(QKeyEvent * event)
656 int key = event->key();
658 if (key == Qt::Key_Up)
661 else if (key == Qt::Key_Down)
664 else if (key == Qt::Key_Left)
667 else if (key == Qt::Key_Right)
673 // Only update if a key we recognize has been pressed!
678 void WaveformWidget::keyReleaseEvent(QKeyEvent * /*event*/)
683 void WaveformWidget::resizeEvent(QResizeEvent * /*event*/)