void FreqWindow::PlotPaint(wxPaintEvent & evt) { wxPaintDC dc( (wxWindow *) evt.GetEventObject() ); dc.DrawBitmap( *mBitmap, 0, 0, true ); if( mProcessed == NULL ) return; int alg = mAlgChoice->GetSelection(); dc.SetFont(mFreqFont); wxRect r = mPlotRect; int width = r.width - 2; float xMin, xMax, xPos, xRatio, xLast, xStep; if (alg == 0) { xMin = mRate / mWindowSize; xMax = mRate / 2; xRatio = xMax / xMin; xPos = xMin; xLast = xPos / 2.0; if (mLogAxis) xStep = pow(2.0f, (log(xRatio) / log(2.0f)) / width); else xStep = (xMax - xMin) / width; } else { xMin = 0; xMax = mProcessedSize / mRate; xPos = xMin; xLast = xPos / 2.0; xStep = (xMax - xMin) / width; } // Find the peak nearest the cursor and plot it float bestpeak = float(0.0); if ( r.Contains(mMouseX, mMouseY) & (mMouseX!=0) & (mMouseX!=r.width-1) ) { if (mLogAxis) xPos = xMin * pow(xStep, mMouseX - (r.x + 1)); else xPos = xMin + xStep * (mMouseX - (r.x + 1)); bool up = (mProcessed[1] > mProcessed[0]); float bestdist = 1000000; float bestValue = 0.0; for (int bin = 2; bin < mProcessedSize; bin++) { bool nowUp = mProcessed[bin] > mProcessed[bin - 1]; if (!nowUp && up) { // Local maximum. Find actual value by cubic interpolation int leftbin = bin - 2; if (leftbin < 1) leftbin = 1; float valueAtMax = 0.0; float max = leftbin + CubicMaximize(mProcessed[leftbin], mProcessed[leftbin + 1], mProcessed[leftbin + 2], mProcessed[leftbin + 3], &valueAtMax); float thispeak; if (alg == 0) thispeak = max * mRate / mWindowSize; else thispeak = max / mRate; if (fabs(thispeak - xPos) < bestdist) { bestpeak = thispeak; bestdist = fabs(thispeak - xPos); bestValue = valueAtMax; if (thispeak > xPos) break; } } up = nowUp; } int px; if (mLogAxis) px = int (log(bestpeak / xMin) / log(xStep)); else px = int ((bestpeak - xMin) * width / (xMax - xMin)); dc.SetPen(wxPen(wxColour(160,160,160), 1, wxSOLID)); AColor::Line(dc, r.x + 1 + px, r.y, r.x + 1 + px, r.y + r.height); // print out info about the cursor location float value; if (mLogAxis) { xPos = xMin * pow(xStep, mMouseX - (r.x + 1)); value = GetProcessedValue(xPos, xPos * xStep); } else { xPos = xMin + xStep * (mMouseX - (r.x + 1)); value = GetProcessedValue(xPos, xPos + xStep); } wxString info; wxString xpitch; wxString peakpitch; const wxChar *xp; const wxChar *pp; if (alg == 0) { xpitch = PitchName_Absolute(FreqToMIDInoteNumber(xPos)); peakpitch = PitchName_Absolute(FreqToMIDInoteNumber(bestpeak)); xp = xpitch.c_str(); pp = peakpitch.c_str(); info.Printf(_("Cursor: %d Hz (%s) = %d dB Peak: %d Hz (%s) = %.1f dB"), int (xPos + 0.5), xp, int (value + 0.5), int (bestpeak + 0.5), pp, bestValue); } else if (xPos > 0.0 && bestpeak > 0.0) { xpitch = PitchName_Absolute(FreqToMIDInoteNumber(1.0 / xPos)); peakpitch = PitchName_Absolute(FreqToMIDInoteNumber(1.0 / bestpeak)); xp = xpitch.c_str(); pp = peakpitch.c_str(); info.Printf(_("Cursor: %.4f sec (%d Hz) (%s) = %f, Peak: %.4f sec (%d Hz) (%s) = %.3f"), xPos, int (1.0 / xPos + 0.5), xp, value, bestpeak, int (1.0 / bestpeak + 0.5), pp, bestValue); } mInfoText->SetLabel(info); } else mInfoText->SetLabel(wxT("")); // Outline the graph dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawRectangle(r); }
void FreqWindow::PlotPaint(wxPaintEvent & event) { wxPaintDC dc( (wxWindow *) event.GetEventObject() ); dc.DrawBitmap( *mBitmap, 0, 0, true ); // Fix for Bug 1226 "Plot Spectrum freezes... if insufficient samples selected" if (!mData || mDataLen < mWindowSize) return; dc.SetFont(mFreqFont); wxRect r = mPlotRect; int width = r.width - 2; float xMin, xMax, xRatio, xStep; if (mAlg == SpectrumAnalyst::Spectrum) { xMin = mRate / mWindowSize; xMax = mRate / 2; xRatio = xMax / xMin; if (mLogAxis) xStep = pow(2.0f, (log(xRatio) / log(2.0f)) / width); else xStep = (xMax - xMin) / width; } else { xMin = 0; xMax = mAnalyst->GetProcessedSize() / mRate; xStep = (xMax - xMin) / width; } float xPos = xMin; // Find the peak nearest the cursor and plot it if ( r.Contains(mMouseX, mMouseY) & (mMouseX!=0) & (mMouseX!=r.width-1) ) { if (mLogAxis) xPos = xMin * pow(xStep, mMouseX - (r.x + 1)); else xPos = xMin + xStep * (mMouseX - (r.x + 1)); float bestValue = 0; float bestpeak = mAnalyst->FindPeak(xPos, &bestValue); int px; if (mLogAxis) px = (int)(log(bestpeak / xMin) / log(xStep)); else px = (int)((bestpeak - xMin) * width / (xMax - xMin)); dc.SetPen(wxPen(wxColour(160,160,160), 1, wxSOLID)); AColor::Line(dc, r.x + 1 + px, r.y, r.x + 1 + px, r.y + r.height); // print out info about the cursor location float value; if (mLogAxis) { xPos = xMin * pow(xStep, mMouseX - (r.x + 1)); value = mAnalyst->GetProcessedValue(xPos, xPos * xStep); } else { xPos = xMin + xStep * (mMouseX - (r.x + 1)); value = mAnalyst->GetProcessedValue(xPos, xPos + xStep); } wxString cursor; wxString peak; wxString xpitch; wxString peakpitch; const wxChar *xp; const wxChar *pp; if (mAlg == SpectrumAnalyst::Spectrum) { xpitch = PitchName_Absolute(FreqToMIDInote(xPos)); peakpitch = PitchName_Absolute(FreqToMIDInote(bestpeak)); xp = xpitch; pp = peakpitch; /* i18n-hint: The %d's are replaced by numbers, the %s by musical notes, e.g. A#*/ cursor.Printf(_("%d Hz (%s) = %d dB"), (int)(xPos + 0.5), xp, (int)(value + 0.5)); peak.Printf(_("%d Hz (%s) = %.1f dB"), (int)(bestpeak + 0.5), pp, bestValue); } else if (xPos > 0.0 && bestpeak > 0.0) { xpitch = PitchName_Absolute(FreqToMIDInote(1.0 / xPos)); peakpitch = PitchName_Absolute(FreqToMIDInote(1.0 / bestpeak)); xp = xpitch; pp = peakpitch; /* i18n-hint: The %d's are replaced by numbers, the %s by musical notes, e.g. A# * the %.4f are numbers, and 'sec' should be an abbreviation for seconds */ cursor.Printf(_("%.4f sec (%d Hz) (%s) = %f"), xPos, (int)(1.0 / xPos + 0.5), xp, value); peak.Printf(_("%.4f sec (%d Hz) (%s) = %.3f"), bestpeak, (int)(1.0 / bestpeak + 0.5), pp, bestValue); } mCursorText->SetValue(cursor); mPeakText->SetValue(peak); } else { mCursorText->SetValue(wxT("")); mPeakText->SetValue(wxT("")); } // Outline the graph dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.DrawRectangle(r); }