////////////////////////////////////////////////////////////////////// // Called to update spectrum data for displaying on the screen ////////////////////////////////////////////////////////////////////// void CPlotter::draw() { int i,n; int w; int h; int xmin, xmax; if (m_DrawOverlay) { drawOverlay(); m_DrawOverlay = false; } QPoint LineBuf[MAX_SCREENSIZE]; if (!m_Running) return; // get/draw the waterfall w = m_WaterfallPixmap.width(); h = m_WaterfallPixmap.height(); // no need to draw if pixmap is invisible if ((w != 0) || (h != 0)) { // move current data down one line(must do before attaching a QPainter object) m_WaterfallPixmap.scroll(0,1,0,0, w, h); QPainter painter1(&m_WaterfallPixmap); // get scaled FFT data getScreenIntegerFFTData(255, qMin(w, MAX_SCREENSIZE), m_MaxdB, m_MindB, m_FftCenter - (qint64)m_Span/2, m_FftCenter + (qint64)m_Span/2, m_wfData, m_fftbuf, &xmin, &xmax); // draw new line of fft data at top of waterfall bitmap painter1.setPen(QColor(0, 0, 0)); for (i = 0; i < xmin; i++) painter1.drawPoint(i,0); for (i = xmax; i < w; i++) painter1.drawPoint(i,0); for (i = xmin; i < xmax; i++) { painter1.setPen(m_ColorTbl[ 255-m_fftbuf[i] ]); painter1.drawPoint(i,0); } } // get/draw the 2D spectrum w = m_2DPixmap.width(); h = m_2DPixmap.height(); if ((w != 0) || (h != 0)) { // first copy into 2Dbitmap the overlay bitmap. m_2DPixmap = m_OverlayPixmap.copy(0,0,w,h); QPainter painter2(&m_2DPixmap); // workaround for "fixed" line drawing since Qt 5 // see http://stackoverflow.com/questions/16990326 #if QT_VERSION >= 0x050000 painter2.translate(0.5, 0.5); #endif // get new scaled fft data getScreenIntegerFFTData(h, qMin(w, MAX_SCREENSIZE), m_MaxdB, m_MindB, m_FftCenter - (qint64)m_Span/2, m_FftCenter + (qint64)m_Span/2, m_fftData, m_fftbuf, &xmin, &xmax); // draw the pandapter painter2.setPen(m_FftColor); n = xmax - xmin; for (i = 0; i < n; i++) { LineBuf[i].setX(i + xmin); LineBuf[i].setY(m_fftbuf[i + xmin]); } if (m_FftFill) { QLinearGradient linGrad(QPointF(xmin, h), QPointF(xmin, 0)); linGrad.setColorAt(0.0, m_FftCol0); linGrad.setColorAt(1.0, m_FftCol1); painter2.setBrush(QBrush(QGradient(linGrad))); if (n < MAX_SCREENSIZE-2) { LineBuf[n].setX(xmax-1); LineBuf[n].setY(h); LineBuf[n+1].setX(xmin); LineBuf[n+1].setY(h); painter2.drawPolygon(LineBuf, n+2); } else { LineBuf[MAX_SCREENSIZE-2].setX(xmax-1); LineBuf[MAX_SCREENSIZE-2].setY(h); LineBuf[MAX_SCREENSIZE-1].setX(xmin); LineBuf[MAX_SCREENSIZE-1].setY(h); painter2.drawPolygon(LineBuf, n); } } else { painter2.drawPolyline(LineBuf, n); } } // trigger a new paintEvent update(); }
////////////////////////////////////////////////////////////////////// // Called to update spectrum data for displaying on the screen ////////////////////////////////////////////////////////////////////// void CPlotter::draw() { int i,n; int w; int h; int xmin, xmax; if (m_DrawOverlay) { drawOverlay(); m_DrawOverlay = false; } QPoint LineBuf[MAX_SCREENSIZE]; if (!m_Running) return; // get/draw the waterfall w = m_WaterfallPixmap.width(); h = m_WaterfallPixmap.height(); // no need to draw if pixmap is invisible if ((w != 0) || (h != 0)) { // move current data down one line(must do before attaching a QPainter object) m_WaterfallPixmap.scroll(0,1,0,0, w, h); QPainter painter1(&m_WaterfallPixmap); // get scaled FFT data getScreenIntegerFFTData(255, qMin(w, MAX_SCREENSIZE), m_MaxdB, m_MindB, m_FftCenter - (qint64)m_Span/2, m_FftCenter + (qint64)m_Span/2, m_wfData, m_fftbuf, &xmin, &xmax); // draw new line of fft data at top of waterfall bitmap painter1.setPen(QColor(0, 0, 0)); for (i = 0; i < xmin; i++) painter1.drawPoint(i,0); for (i = xmax; i < w; i++) painter1.drawPoint(i,0); for (i = xmin; i < xmax; i++) { painter1.setPen(m_ColorTbl[ 255-m_fftbuf[i] ]); painter1.drawPoint(i,0); } } // get/draw the 2D spectrum w = m_2DPixmap.width(); h = m_2DPixmap.height(); if ((w != 0) || (h != 0)) { // first copy into 2Dbitmap the overlay bitmap. m_2DPixmap = m_OverlayPixmap.copy(0,0,w,h); QPainter painter2(&m_2DPixmap); // workaround for "fixed" line drawing since Qt 5 // see http://stackoverflow.com/questions/16990326 #if QT_VERSION >= 0x050000 painter2.translate(0.5, 0.5); #endif // get new scaled fft data getScreenIntegerFFTData(h, qMin(w, MAX_SCREENSIZE), m_MaxdB, m_MindB, m_FftCenter - (qint64)m_Span/2, m_FftCenter + (qint64)m_Span/2, m_fftData, m_fftbuf, &xmin, &xmax); // draw the pandapter painter2.setPen(m_FftColor); n = xmax - xmin; for (i = 0; i < n; i++) { LineBuf[i].setX(i + xmin); LineBuf[i].setY(m_fftbuf[i + xmin]); } if (m_FftFill) { QLinearGradient linGrad(QPointF(xmin, h), QPointF(xmin, 0)); linGrad.setColorAt(0.0, m_FftCol0); linGrad.setColorAt(1.0, m_FftCol1); painter2.setBrush(QBrush(QGradient(linGrad))); if (n < MAX_SCREENSIZE-2) { LineBuf[n].setX(xmax-1); LineBuf[n].setY(h); LineBuf[n+1].setX(xmin); LineBuf[n+1].setY(h); painter2.drawPolygon(LineBuf, n+2); } else { LineBuf[MAX_SCREENSIZE-2].setX(xmax-1); LineBuf[MAX_SCREENSIZE-2].setY(h); LineBuf[MAX_SCREENSIZE-1].setX(xmin); LineBuf[MAX_SCREENSIZE-1].setY(h); painter2.drawPolygon(LineBuf, n); } } else { painter2.drawPolyline(LineBuf, n); } //Peak detection if (m_PeakDetection > 0) { m_Peaks.clear(); float mean = 0; float sum_of_sq = 0; for (i = 0; i < n; i++) { mean += m_fftbuf[i + xmin]; sum_of_sq += m_fftbuf[i + xmin] * m_fftbuf[i + xmin]; } mean /= n; float stdev= sqrt( sum_of_sq/n-mean*mean ); int lastPeak=-1; for (i = 0; i < n; i++) { //m_PeakDetection times the std over the mean or better than current peak float d = (lastPeak==-1) ? (mean - m_PeakDetection * stdev) : m_fftbuf[lastPeak+xmin]; if (m_fftbuf[i + xmin] < d) lastPeak=i; if (lastPeak != -1 && (i - lastPeak > PEAK_H_TOLERANCE || i == n-1)) { m_Peaks.insert(lastPeak+xmin, m_fftbuf[lastPeak + xmin]); painter2.drawEllipse(lastPeak+xmin-5, m_fftbuf[lastPeak + xmin]-5, 10, 10); lastPeak=-1; } } } //Peak hold if (m_PeakHoldActive) { for (i = 0; i < n; i++) { if(!m_PeakHoldValid || m_fftbuf[i] < m_fftPeakHoldBuf[i]) m_fftPeakHoldBuf[i] = m_fftbuf[i]; LineBuf[i].setX(i + xmin); LineBuf[i].setY(m_fftPeakHoldBuf[i + xmin]); } painter2.setPen(m_PeakHoldColor); painter2.drawPolyline(LineBuf, n); m_PeakHoldValid=true; } painter2.end(); } // trigger a new paintEvent update(); }