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[9];
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 if (Global::streamCount > 1)
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);
85 for(uint32_t i=0; i<Global::streamCount; i++)
86 { printf("Sync point %d: %d\n", sNum[i], slip[i]); }
89 printf("Lookahead for track %.2f: %d\n", (float)Global::trackNum / 4.0f, Lookahead(slip, Global::streamCount, +1));
92 // And finally, update the display
93 setMinimumWidth(xmax);
94 setMaximumWidth(xmax);
100 void WaveformWidget::HandleInitSync(void)
103 FindInitialSyncForStreams(slip, Global::streamCount);
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]);
117 void WaveformWidget::HandleStepBack(void)
122 uint32_t minIdx = SmallestIndex(slip, Global::streamCount);
124 if (slip[minIdx] == 0)
130 StepBackUntilBad(slip, a, Global::streamCount);
134 for(uint32_t i=0; i<Global::streamCount; i++)
135 printf("<%d> ", slip[i]);
141 foundBad = StepBackThruBad(slip, a, Global::streamCount);
149 void WaveformWidget::HandleManualSync(void)
156 StepBack(slip, a, Global::streamCount);
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]);
169 void WaveformWidget::HandleZeroAll(void)
171 memset(slip, 0, sizeof(slip));
176 void WaveformWidget::HandleSynthesize(void)
178 // Global::swLen = Synthesize(slip, Global::streamCount, Global::synthWave, Global::swAmplitude);
179 Global::swLen = Synthesize2(slip, Global::streamCount, Global::synthWave, Global::swAmplitude);
185 void WaveformWidget::HandleSynthesize2(void)
187 SynthesizeTrack(Global::trackNum);
188 // emit(UpdateInfo());
193 void WaveformWidget::HandleSync(int stream, int num)
203 void WaveformWidget::HandleWaveSync(int num)
205 Global::waveSync = num;
210 void WaveformWidget::HandleRatio(int /*stream*/, int /*num*/)
215 // ratio[stream] = (double)num / 1600000.0;
221 Now we have SynthesizeTrack(trackNo), so we can display the results of that here--including the loop point if we found one...
223 Now our analysis thread calcs it for us... One less thing to worry about!
226 void WaveformWidget::paintEvent(QPaintEvent * event)
228 if (Global::a2r == NULL)
231 uint32_t xpos = event->rect().x();
232 uint32_t width = event->rect().width();
234 QPainter painter(this);
235 painter.setRenderHint(QPainter::Antialiasing);
238 font.setPixelSize(12);
240 font.setStyleHint(QFont::TypeWriter);
241 painter.setFont(font);
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);
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
254 // float y = 7 + 12 + 18;
255 float y = 7 + 12 + 18 + (40 * 3);
256 float drawXPos = (xpos < 8 ? 0 : xpos - 8);
259 //printf("update: ");
260 for(uint32_t j=0; j<Global::numStreams; j++)
262 if (Global::stream[j]->location != Global::trackNum)
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);
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);
277 if ((Global::stream[j]->captureType == 1) || (Global::stream[j]->captureType == 3))
279 for(uint32_t i=0; i<trackBytes; i++)
282 uint32_t timeToNext = Global::stream[j]->data[offset + i];
284 while (Global::stream[j]->data[offset + i] == 0xFF)
287 timeToNext += Global::stream[j]->data[offset + i];
290 uint32_t timeToNext = Global::wave[j][offset + i];
294 // x += timeToNext / 2;
295 x += ((double)timeToNext / 2.0);// * ratio[wfNum];
297 // if ((Global::stream[j]->data[offset + i] > 24) || (i == 0))
301 painter.setPen(bluePen);
303 if (x >= ((estSplice / 2) /* * ratio[wfNum]*/))
304 painter.setPen(Qt::magenta);
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);
322 if ((timeToNext >= 24) && (timeToNext <= 49))
324 byte = (byte << 1) | 1;
327 else if ((timeToNext >= 50) && (timeToNext <= 80))
329 byte = (byte << 2) | 1;
332 else if ((timeToNext >= 81) && (timeToNext <= 112))
334 byte = (byte << 3) | 1;
337 else if ((timeToNext >= 113) && (timeToNext <= 137))
339 byte = (byte << 4) | 1;
344 // Handle zeros here...
345 while (timeToNext > 32)
356 while (bitCount > 15)
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);
363 byte &= mask1[bitCount];
366 for(uint16_t z=bitCount; z>0; z--)
368 if ((byte & mask2[z - 1]) == 0)
378 sprintf(buf, "|%02X%s", byteToShow, (zeroes == 0 ? "" : (zeroes == 1 ? "." : (zeroes == 2 ? ".." : "..."))));
380 painter.setPen(whitePen);
381 painter.drawText(bytePos, y - (18 + 6), buf);
385 if (bytePos > (xpos + width))
391 else if (Global::stream[j]->captureType == 2)
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.
397 uint32_t bpStart = xpos / 16;
400 for(uint32_t i=bpStart; i<bpStart+(width/16)+4; i++)
402 if (Global::stream[j]->data[i / 8] & Global::bit[i % 8])
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);
422 if (Global::swLen == 0)
425 // Reset Y coord to the top
430 uint32_t bytePos = x;
431 uint32_t bitCount = 1;
432 float hgt = 17.0f * 1.0f;
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);
442 for(uint32_t i=0; i<Global::swLen; i++)
444 uint32_t timeToNext = Global::synthWave[i];
445 hgt = 17.0 * Global::swAmplitude[i];
446 x += (double)timeToNext / 2.0;
448 if ((timeToNext > 0) || (i == 0))
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);
461 if ((timeToNext >= 24) && (timeToNext <= 49))
463 byte = (byte << 1) | 1;
466 else if ((timeToNext >= 50) && (timeToNext <= 80))
468 byte = (byte << 2) | 1;
471 else if ((timeToNext >= 81) && (timeToNext <= 112))
473 byte = (byte << 3) | 1;
476 else if ((timeToNext >= 113) && (timeToNext <= 137))
478 byte = (byte << 4) | 1;
483 // Handle zeros here...
484 while (timeToNext > 32)
494 while (bitCount > 15)
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);
501 byte &= mask1[bitCount];
504 for(uint16_t z=bitCount; z>0; z--)
506 if ((byte & mask2[z - 1]) == 0)
516 sprintf(buf, "|%02X%s", byteToShow, (zeroes == 0 ? "" : (zeroes == 1 ? "." : (zeroes == 2 ? ".." : "..."))));
518 painter.setPen(whitePen);
519 painter.drawText(bytePos, y - (18 + 6), buf);
523 if (bytePos > (xpos + width))
529 if (Global::synWaveLen[Global::trackNum] == 0)
532 // Reset Y coord to the top
533 y = 7 + 12 + 18 + (40 * 1);
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);
545 for(uint32_t i=0; i<Global::synWaveLen[Global::trackNum]; i++)
547 uint32_t timeToNext = Global::synWave[Global::trackNum][i];
548 x += (double)timeToNext / 2.0;
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);
565 sprintf(buf, "|%d", i + 1);
566 painter.setPen(whitePen);
567 painter.drawText(x, y - (18 + 6), buf);
570 if (x > (xpos + width))
574 y = 7 + 12 + 18 + (40 * 2);
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);
586 for(uint32_t i=Global::waveSync; i<Global::synWaveLen[Global::trackNum]; i++)
588 uint32_t timeToNext = Global::synWave[Global::trackNum][i];
589 x += (double)timeToNext / 2.0;
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);
606 sprintf(buf, "|%d", i + 1);
607 painter.setPen(whitePen);
608 painter.drawText(x, y - (18 + 6), buf);
611 if (x > (xpos + width))
617 void WaveformWidget::mousePressEvent(QMouseEvent * event)
619 if (event->button() == Qt::LeftButton)
626 void WaveformWidget::mouseMoveEvent(QMouseEvent * event)
628 if (event->buttons() & Qt::LeftButton)
635 void WaveformWidget::mouseReleaseEvent(QMouseEvent * event)
637 if (event->button() == Qt::LeftButton)
644 void WaveformWidget::mouseDoubleClickEvent(QMouseEvent * event)
646 if (event->button() == Qt::LeftButton)
653 void WaveformWidget::keyPressEvent(QKeyEvent * event)
655 int key = event->key();
657 if (key == Qt::Key_Up)
660 else if (key == Qt::Key_Down)
663 else if (key == Qt::Key_Left)
666 else if (key == Qt::Key_Right)
672 // Only update if a key we recognize has been pressed!
677 void WaveformWidget::keyReleaseEvent(QKeyEvent * /*event*/)
682 void WaveformWidget::resizeEvent(QResizeEvent * /*event*/)