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++)
282 uint32_t timeToNext = Global::wave[j][offset + i];
285 // x += timeToNext / 2;
286 x += ((double)timeToNext / 2.0);
288 // if ((Global::stream[j]->data[offset + i] > 24) || (i == 0))
292 if (x < (estSplice / 2))
293 DrawPulse(&painter, &bluePen, lastx, x, y);
295 DrawPulse(&painter, Qt::magenta, lastx, x, y);
308 if ((timeToNext >= 24) && (timeToNext <= 49))
310 byte = (byte << 1) | 1;
313 else if ((timeToNext >= 50) && (timeToNext <= 80))
315 byte = (byte << 2) | 1;
318 else if ((timeToNext >= 81) && (timeToNext <= 112))
320 byte = (byte << 3) | 1;
323 else if ((timeToNext >= 113) && (timeToNext <= 137))
325 byte = (byte << 4) | 1;
330 // Handle zeros here...
331 while (timeToNext > 32)
342 while (bitCount > 15)
345 uint16_t mask1[16] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF };
346 uint16_t mask2[16] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 };
347 uint8_t byteToShow = byte >> (bitCount - 8);
349 byte &= mask1[bitCount];
352 for(uint16_t z=bitCount; z>0; z--)
354 if ((byte & mask2[z - 1]) == 0)
364 sprintf(buf, "|%02X%s", byteToShow, (zeroes == 0 ? "" : (zeroes == 1 ? "." : (zeroes == 2 ? ".." : "..."))));
366 painter.setPen(whitePen);
367 painter.drawText(bytePos, y - (18 + 6), buf);
371 if (bytePos > (xpos + width))
377 else if (Global::stream[j]->captureType == 2)
381 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.
383 uint32_t bpStart = xpos / 16;
386 for(uint32_t i=bpStart; i<bpStart+(width/16)+4; i++)
388 if (Global::stream[j]->data[i / 8] & Global::bit[i % 8])
390 DrawPulse(&painter, Qt::cyan, lastx, x, y);
403 if (Global::swLen == 0)
406 // Reset Y coord to the top
411 uint32_t bytePos = x;
412 uint32_t bitCount = 1;
414 DrawPulse(&painter, &greenPen, lastx, x, y);
417 for(uint32_t i=0; i<Global::swLen; i++)
419 uint32_t timeToNext = Global::synthWave[i];
420 x += (double)timeToNext / 2.0;
422 if ((timeToNext > 0) || (i == 0))
426 DrawPulse(&painter, &greenPen, lastx, x, y, Global::swAmplitude[i]);
430 if ((timeToNext >= 24) && (timeToNext <= 49))
432 byte = (byte << 1) | 1;
435 else if ((timeToNext >= 50) && (timeToNext <= 80))
437 byte = (byte << 2) | 1;
440 else if ((timeToNext >= 81) && (timeToNext <= 112))
442 byte = (byte << 3) | 1;
445 else if ((timeToNext >= 113) && (timeToNext <= 137))
447 byte = (byte << 4) | 1;
452 // Handle zeros here...
453 while (timeToNext > 32)
463 while (bitCount > 15)
466 uint16_t mask1[16] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF };
467 uint16_t mask2[16] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 };
468 uint8_t byteToShow = byte >> (bitCount - 8);
470 byte &= mask1[bitCount];
473 for(uint16_t z=bitCount; z>0; z--)
475 if ((byte & mask2[z - 1]) == 0)
485 sprintf(buf, "|%02X%s", byteToShow, (zeroes == 0 ? "" : (zeroes == 1 ? "." : (zeroes == 2 ? ".." : "..."))));
487 painter.setPen(whitePen);
488 painter.drawText(bytePos, y - (18 + 6), buf);
492 if (bytePos > (xpos + width))
498 if (Global::synWaveLen[Global::trackNum] == 0)
501 // Reset Y coord to the top
502 y = 7 + 12 + 18 + (40 * 1);
506 DrawPulse(&painter, &orangePen, lastx, x, y);
509 for(uint32_t i=0; i<Global::synWaveLen[Global::trackNum]; i++)
511 uint32_t timeToNext = Global::synWave[Global::trackNum][i];
512 x += (double)timeToNext / 2.0;
516 DrawPulse(&painter, &orangePen, lastx, x, y);
524 sprintf(buf, "|%d", i + 1);
525 painter.setPen(whitePen);
526 painter.drawText(x, y - (18 + 6), buf);
529 if (x > (xpos + width))
533 y = 7 + 12 + 18 + (40 * 2);
537 DrawPulse(&painter, &orangePen, lastx, x, y);
540 for(uint32_t i=Global::waveSync; i<Global::synWaveLen[Global::trackNum]; i++)
542 uint32_t timeToNext = Global::synWave[Global::trackNum][i];
543 x += (double)timeToNext / 2.0;
547 DrawPulse(&painter, &orangePen, lastx, x, y);
555 sprintf(buf, "|%d", i + 1);
556 painter.setPen(whitePen);
557 painter.drawText(x, y - (18 + 6), buf);
560 if (x > (xpos + width))
566 void WaveformWidget::DrawPulse(QPainter * painter, QPen * pen, float lastx, float x, float y, float height/*= 1.0*/)
568 float yHeight = y - (17.0 * height);
569 painter->setPen(*pen);
570 painter->drawLine(lastx, y, x, y);
571 painter->drawLine(x, y, x + 4.0, y);
572 painter->drawLine(x + 4.0, y, x + 4.0, yHeight);
573 painter->drawLine(x + 4.0, yHeight, x + 8.0, yHeight);
574 painter->drawLine(x + 8.0, yHeight, x + 8.0, y);
578 void WaveformWidget::DrawPulse(QPainter * painter, Qt::GlobalColor color, float lastx, float x, float y, float height/*= 1.0*/)
581 DrawPulse(painter, &pen, lastx, x, y, height);
585 void WaveformWidget::mousePressEvent(QMouseEvent * event)
587 if (event->button() == Qt::LeftButton)
594 void WaveformWidget::mouseMoveEvent(QMouseEvent * event)
596 if (event->buttons() & Qt::LeftButton)
603 void WaveformWidget::mouseReleaseEvent(QMouseEvent * event)
605 if (event->button() == Qt::LeftButton)
612 void WaveformWidget::mouseDoubleClickEvent(QMouseEvent * event)
614 if (event->button() == Qt::LeftButton)
621 void WaveformWidget::keyPressEvent(QKeyEvent * event)
623 int key = event->key();
625 if (key == Qt::Key_Up)
628 else if (key == Qt::Key_Down)
631 else if (key == Qt::Key_Left)
634 else if (key == Qt::Key_Right)
640 // Only update if a key we recognize has been pressed!
645 void WaveformWidget::keyReleaseEvent(QKeyEvent * /*event*/)
650 void WaveformWidget::resizeEvent(QResizeEvent * /*event*/)