/** calculates elements in the zoom lookup table @param ch The channel we are working with @param baseElement The element's index in the zoom lookup table @param baseX The number of chunks each pixel represents (can include a fraction part) @return false if a zoomElement can't be calculated, else true */ bool DrawWidget::calcZoomElement(Channel *ch, ZoomElement &ze, int baseElement, double baseX) { int startChunk = toInt(double(baseElement) * baseX); int finishChunk = toInt(double(baseElement+1) * baseX) + 1; if(finishChunk >= (int)ch->totalChunks()) finishChunk--; //dont go off the end if(finishChunk >= (int)ch->totalChunks()) return false; //that data doesn't exist yet std::pair<large_vector<AnalysisData>::iterator, large_vector<AnalysisData>::iterator> a = minMaxElement(ch->dataIteratorAtChunk(startChunk), ch->dataIteratorAtChunk(finishChunk), lessPitch()); if(a.second == ch->dataIteratorAtChunk(finishChunk)) return false; large_vector<AnalysisData>::iterator err = std::max_element(ch->dataIteratorAtChunk(startChunk), ch->dataIteratorAtChunk(finishChunk), lessValue(0)); if(err == ch->dataIteratorAtChunk(finishChunk)) return false; float low, high; int noteIndex; if(ch->isVisibleChunk(&*err)) { low = a.first->getPitch(); high = a.second->getPitch(); noteIndex = a.first->getNoteIndex(); } else { low = 0; high = 0; noteIndex = NO_NOTE; } //float corr = err->correlation()*dB2ViewVal(err->logrms()); //float corr = err->correlation()*dB2ViewVal(err->logrms(), ch->rmsCeiling, ch->rmsFloor); float corr = err->getCorrelation() * dB2Normalised(err->getLogRms(), ch->rmsCeiling, ch->rmsFloor); QColor theColor = (gdata->pitchContourMode() == 0) ? colorBetween(gdata->backgroundColor(), ch->color, corr) : ch->color; ze.set(low, high, corr, theColor, noteIndex, (startChunk+finishChunk)/2); return true; }
void NoteData::addData(AnalysisData *analysisData, float periods) { maxLogRMS = MAX(maxLogRMS, analysisData->logrms()); maxIntensityDB = MAX(maxIntensityDB, analysisData->maxIntensityDB()); maxCorrelation = MAX(maxCorrelation, analysisData->correlation()); maxPurity = MAX(maxPurity, analysisData->volumeValue()); _volume = MAX(_volume, dB2Normalised(analysisData->logrms())); _numPeriods += periods; //sum up the periods //_periodOctaveEstimate = analysisData->periodOctaveEstimate; //overwrite the old estimate _avgPitch = bound(freq2pitch(avgFreq()), 0.0, gdata->topPitch()); }
void DrawWidget::drawChannel(QPaintDevice &pd, Channel *ch, QPainter &p, double leftTime, double currentTime, double zoomX, double viewBottom, double zoomY, int viewType) { ZoomLookup *z; if(viewType == DRAW_VIEW_SUMMARY) z = &ch->summaryZoomLookup; else z = &ch->normalZoomLookup; ChannelLocker channelLocker(ch); QColor current = ch->color; QColor invert(255 - current.red(), 255 - current.green(), 255 - current.blue()); p.setPen(current); int viewBottomOffset = toInt(viewBottom / zoomY); printf("viewBottomOffset=%d, %f, %f\n", viewBottomOffset, viewBottom, zoomY); viewBottom = double(viewBottomOffset) * zoomY; // baseX is the no. of chunks a pixel must represent. double baseX = zoomX / ch->timePerChunk(); z->setZoomLevel(baseX); double currentChunk = ch->chunkFractionAtTime(currentTime); double leftFrameTime = currentChunk - ((currentTime - leftTime) / ch->timePerChunk()); //double leftFrameTime = leftTime / ch->timePerChunk(); double frameTime = leftFrameTime; //if(frameTime < 0.0) frameTime = 0.0; int n = 0; int baseElement = int(floor(frameTime / baseX)); if(baseElement < 0) { n -= baseElement; baseElement = 0; } int lastBaseElement = int(floor(double(ch->totalChunks()) / baseX)); Q3PointArray pointArray(pd.width()*2); //QPointArray topPoints(width()*2); //QPointArray bottomPoints(width()*2); //int pointIndex = 0; //int pointIndex = 0; if (baseX > 1) { // More samples than pixels int theWidth = pd.width(); //if(baseElement + theWidth > z->size()) z->setSize(baseElement + theWidth); if(lastBaseElement > z->size()) z->setSize(lastBaseElement); for(; n < theWidth && baseElement < lastBaseElement; n++, baseElement++) { myassert(baseElement >= 0); ZoomElement &ze = z->at(baseElement); if(!ze.isValid()) { if(calcZoomElement(ch, ze, baseElement, baseX)) continue; } if(ze.high() != 0.0f && ze.high() - ze.low() < 1.0) { //if range is closer than one semi-tone then draw a line between them //if(ze.noteLow > 0) { p.setPen(ze.color()); //p.setPen(QPen(ze.color(), lineWidth)); //Note: lineTo doen't draw a pixel on the last point of the line p.drawLine(n, pd.height() - lineTopHalfWidth - toInt(ze.high() / zoomY) + viewBottomOffset, n, pd.height() + lineBottomHalfWidth - toInt(ze.low() / zoomY) + viewBottomOffset); //pointArray.setPoint(pointIndex++, n, height() - lineTopHalfWidth - toInt(ze.high / zoomY) + viewBottomOffset); //pointArray.setPoint(pointIndex++, n, height() + lineBottomHalfWidth - toInt(ze.low / zoomY) + viewBottomOffset); } } //myassert(pointIndex <= width()*2); //p.setPen(ch->color); //p.drawLineSegments(pointArray, 0, pointIndex/2); } else { // More pixels than samples float err = 0.0, pitch = 0.0, prevPitch = 0.0, vol; int intChunk = (int) floor(frameTime); // Integer version of frame time if(intChunk < 0) intChunk = 0; double stepSize = 1.0 / baseX; // So we skip some pixels int x = 0, y; //double start = 0 - stepSize; double start = (double(intChunk) - frameTime) * stepSize; double stop = pd.width() + (2 * stepSize); int squareSize = (int(sqrt(stepSize)) / 2) * 2 + 1; //make it an odd number int halfSquareSize = squareSize/2; int penX=0, penY=0; //topPoints.setPoint(pointIndex, toInt(start), 0); //bottomPoints.setPoint(pointIndex++, toInt(start), height()); for (double n = start; n < stop && intChunk < (int)ch->totalChunks(); n += stepSize, intChunk++) { myassert(intChunk >= 0); //if (intChunk < 0) continue; // So we don't go off the beginning of the array AnalysisData *data = ch->dataAtChunk(intChunk); err = data->getCorrelation(); //vol = dB2ViewVal(data->logrms(), ch->rmsCeiling, ch->rmsFloor); vol = dB2Normalised(data->getLogRms(), ch->rmsCeiling, ch->rmsFloor); //if (err >= CERTAIN_THRESHOLD) { //float val = MIN(ch->dataAtChunk(intChunk)->volumeValue, 1.0); if(gdata->pitchContourMode() == 0) //p.setPen(QPen(colorBetween(colorGroup().background(), ch->color, err*2.0-1.0), lineWidth)); //p.setPen(QPen(colorBetween(gdata->backgroundColor(), ch->color, err*sqrt(data->rms)*10.0), lineWidth)); if(viewType == DRAW_VIEW_PRINT) p.setPen(QPen(colorBetween(QColor(255, 255, 255), ch->color, err*vol), lineWidth)); else p.setPen(QPen(colorBetween(gdata->backgroundColor(), ch->color, err*vol), lineWidth)); else p.setPen(QPen(ch->color, lineWidth)); x = toInt(n); //note = (data->isValid()) ? data->note : 0.0f; //note = (ch->isVisibleNote(data->noteIndex)) ? data->note : 0.0f; pitch = (ch->isVisibleChunk(data)) ? data->getPitch() : 0.0f; myassert(pitch >= 0.0 && pitch <= gdata->topPitch()); //pitch = bound(pitch, 0, gdata->topPitch()); y = pd.height() - 1 - toInt(pitch / zoomY) + viewBottomOffset; //y = height() - 1 - int((note / zoomY) - (viewBottom / zoomY)); if(pitch > 0.0f) { if(fabs(prevPitch - pitch) < 1.0 && n != start) { //if closer than one semi-tone from previous then draw a line between them //p.lineTo(x, y); p.drawLine(penX, penY, x, y); penX = x; penY = y; } else { p.drawPoint(x, y); //p.moveTo(x, y); penX = x; penY = y; } if(stepSize > 10) { //draw squares on the data points //p.setPen(invert); p.setBrush(Qt::NoBrush); p.drawRect(x - halfSquareSize, y - halfSquareSize, squareSize, squareSize); //p.setPen(QPen(current, 2)); } //} else { // p.moveTo(x, height()-1-int(((note-viewBottom) / zoomY))); //} } prevPitch = pitch; } } }
//------------------------------------------------------------------------------ float AnalysisData::getVolumeValue(const GData & p_data)const { return (dB2Normalised(values[AMPLITUDE_RMS],p_data) + values[AMPLITUDE_CORRELATION] - 1.0f) * 0.2; }