bool TrajectoryAnalysisModuleData::Impl::isInitialized( const AnalysisData &data) const { for (int i = 0; i < data.dataSetCount(); ++i) { if (data.columnCount(i) > 0) { // If not all of the column counts are set, startData() in the // constructor asserts, so that does not need to be checked here. return true; } } return false; }
int AnalysisTemplate::initAnalysis(const TopologyInformation & /*top*/) { _data.setColumns(_sel.size()); registerAnalysisDataset(&_data, "avedist"); _avem = new AnalysisDataAverageModule(); _data.addModule(_avem); if (!_fnDist.empty()) { AnalysisDataPlotModule *plotm = new AnalysisDataPlotModule(_options); plotm->setFileName(_fnDist); plotm->setTitle("Average distance"); plotm->setXLabel("Time (ps)"); plotm->setYLabel("Distance (nm)"); _data.addModule(plotm); } return 0; }
void AnalysisTemplate::initAnalysis(const TrajectoryAnalysisSettings &settings, const TopologyInformation & /*top*/) { nb_.setCutoff(cutoff_); data_.setColumnCount(0, sel_.size()); avem_.reset(new AnalysisDataAverageModule()); data_.addModule(avem_); if (!fnDist_.empty()) { AnalysisDataPlotModulePointer plotm( new AnalysisDataPlotModule(settings.plotSettings())); plotm->setFileName(fnDist_); plotm->setTitle("Average distance"); plotm->setXAxisIsTime(); plotm->setYLabel("Distance (nm)"); data_.addModule(plotm); } }
void DrawWidget::setChannelVerticalView(Channel *ch, double leftTime, double currentTime, double zoomX, double viewBottom, double zoomY) { ZoomLookup *z = &ch->normalZoomLookup; ChannelLocker channelLocker(ch); int viewBottomOffset = toInt(viewBottom / zoomY); viewBottom = double(viewBottomOffset) * zoomY; std::vector<float> ys; ys.reserve(width()); std::vector<float> weightings; weightings.reserve(width()); float maxY = 0.0f, minY = gdata->topPitch(); float totalY = 0.0f; float numY = 0.0f; // 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 frameTime = leftFrameTime; int n = 0; int currentBaseElement = int(floor(currentChunk / baseX)); int firstBaseElement = int(floor(frameTime / baseX)); int baseElement = firstBaseElement; if(baseElement < 0) { n -= baseElement; baseElement = 0; } int lastBaseElement = int(floor(double(ch->totalChunks()) / baseX)); double leftBaseWidth = MAX(1.0, double(currentBaseElement - firstBaseElement)); double rightBaseWidth = MAX(1.0, double(lastBaseElement - currentBaseElement)); /* We calculate the auto follow and scale by averaging all the note elements in view. We weight the frequency averaging by a triangle weighting function centered on the current time. Also it is weighted by the corr value of each frame. /|\ / | \ / | \ / | \ ^ ^ leftBaseWidth rightBaseWidth */ //QPointArray bottomPoints(width()*2); //int pointIndex = 0; if (baseX > 1) { // More samples than pixels int theWidth = width(); if(lastBaseElement > z->size()) z->setSize(lastBaseElement); for(; n < theWidth && baseElement < lastBaseElement; n++, baseElement++) { myassert(baseElement >= 0); ZoomElement &ze = z->at(baseElement); //if(!z->hasValue(baseElement)) { if(!ze.isValid()) { if(!calcZoomElement(ch, ze, baseElement, baseX)) continue; } if(ze.low() > 0.0f && ze.high() > 0.0f) { float weight = ze.corr(); if(baseElement < currentBaseElement) weight *= double(currentBaseElement - baseElement) / leftBaseWidth; else if(baseElement > currentBaseElement) weight *= double(baseElement - currentBaseElement) / rightBaseWidth; if(ze.low() < minY) minY = ze.low(); if(ze.high() > maxY) maxY = ze.high(); totalY += (ze.low() + ze.high()) / 2.0f * weight; numY += weight; ys.push_back((ze.low() + ze.high()) / 2.0f); weightings.push_back(weight); } /* int y = height() - 1 - toInt(ze.high / zoomY) + viewBottomOffset; bottomPoints.setPoint(pointIndex++, n, y); bottomPoints.setPoint(pointIndex++, n, height()); */ } /* p.setPen(Qt::NoPen); p.setBrush(gdata->shading1Color()); p.drawRect(firstN, 0, lastN, height()); p.setPen(gdata->shading2Color()); p.drawLineSegments(bottomPoints, 0, pointIndex/2); */ } else { // More pixels than samples float pitch = 0.0; 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 float corr; double start = (double(intChunk) - frameTime) * stepSize; double stop = width() + (2 * stepSize); //bottomPoints.setPoint(pointIndex++, toInt(start), height()); for (double n = start; n < stop && intChunk < (int)ch->totalChunks(); n += stepSize, intChunk++) { myassert(intChunk >= 0); AnalysisData *data = ch->dataAtChunk(intChunk); /* if(gdata->pitchContourMode() == 0) p.setPen(QPen(colorBetween(gdata->backgroundColor(), ch->color, err*sqrt(data->rms)*10.0), lineWidth)); else p.setPen(QPen(ch->color, lineWidth)); */ pitch = (ch->isVisibleChunk(data)) ? data->getPitch() : 0.0f; myassert(pitch >= 0.0 && pitch <= gdata->topPitch()); //corr = data->correlation*sqrt(data->rms)*10.0; corr = data->getCorrelation() * dB2ViewVal(data->getLogRms()); if(pitch > 0.0f) { float weight = corr; if(minY < pitch) minY = pitch; if(maxY > pitch) maxY = pitch; totalY += pitch * weight; numY += weight; ys.push_back(pitch); weightings.push_back(weight); } //bottomPoints.setPoint(pointIndex++, x, y); } //bottomPoints.setPoint(pointIndex, bottomPoints.point(pointIndex-1).x(), height()); //pointIndex++; /* myassert(pointIndex <= width()*2); p.setPen(Qt::NoPen); p.setBrush(gdata->shading1Color()); p.drawRect(firstN, 0, lastN, height()); p.setBrush(gdata->shading2Color()); p.drawPolygon(bottomPoints, false, 0, pointIndex); */ } if(!ys.empty() > 0) { float meanY = totalY / numY; double spred = 0.0; myassert(ys.size() == weightings.size()); //use a linear spred function. not a squared one like standard deviation for(uint j=0; j<ys.size(); j++) { spred += sq(ys[j] - meanY) * weightings[j]; } spred = sqrt(spred / numY) * 4.0; //printf("spred = %f\n", spred); if(spred < 12.0) spred = 12.0; //show a minimum of 12 semi-tones gdata->view->setViewBottomRaw(meanY - gdata->view->viewHeight() / 2.0); //gdata->view->setLogZoomYRaw(log(height()/spred)); } }
void DrawWidget::drawChannelFilled(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); 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)); int firstN = n; int lastN = firstN; //QPointArray pointArray(width()*2); //QPointArray topPoints(width()*2); /* Q3PointArray bottomPoints(width()*2); Q3PointArray evenMidPoints(width()*2); Q3PointArray oddMidPoints(width()*2); Q3PointArray evenMidPoints2(width()*2); Q3PointArray oddMidPoints2(width()*2);*/ QPolygon bottomPoints(width()*2); QPolygon evenMidPoints(width()*2); QPolygon oddMidPoints(width()*2); QPolygon evenMidPoints2(width()*2); QPolygon oddMidPoints2(width()*2); std::vector<QRect> noteRect(width()*2); std::vector<QRect> noteRect2(width()*2); std::vector<bool> isNoteRectEven(width()*2); //int pointIndex = 0; int pointIndex = 0; int evenMidPointIndex = 0; int oddMidPointIndex = 0; int evenMidPointIndex2 = 0; int oddMidPointIndex2 = 0; int rectIndex = 0; int rectIndex2 = 0; if (baseX > 1) { // More samples than pixels int theWidth = 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(!z->hasValue(baseElement)) { if(!ze.isValid()) { if(!calcZoomElement(ch, ze, baseElement, baseX)) continue; } /*p.setPen(gdata->shading1Color()); p.moveTo(n, 0); p.lineTo(n, height() - 1 - toInt(ze.high / zoomY) + viewBottomOffset); p.setPen(gdata->shading2Color()); p.lineTo(n, height());*/ int y = height() - 1 - toInt(ze.high() / zoomY) + viewBottomOffset; int y2, y3; //if(ze.noteIndex >= 0) { if(ze.noteIndex() != -1 && ch->dataAtChunk(ze.midChunk())->getNoteIndex() != -1) { myassert(ze.noteIndex() >= 0); myassert(ze.noteIndex() < int(ch->noteData.size())); myassert(ch->isValidChunk(ze.midChunk())); AnalysisData *data = ch->dataAtChunk(ze.midChunk()); //double avgNote = ch->noteData[ze.noteIndex()].avgNote(); //printf("avgFreq = %f, ", ch->noteData[ze.noteIndex].avgFreq()); //printf("numPeriods = %f, ", ch->noteData[ze.noteIndex].numPeriods()); //printf("noteLength = %f\n", ch->noteData[ze.noteIndex].noteLength()); //y2 = height() - 1 - toInt((avgNote+0.5) / zoomY) + viewBottomOffset; //y3 = height() - 1 - toInt((avgNote-0.5) / zoomY) + viewBottomOffset; //y2 = height() - 1 - toInt((data->shortTermMean + data->shortTermDeviation) / zoomY) + viewBottomOffset; //y3 = height() - 1 - toInt((data->shortTermMean - data->shortTermDeviation) / zoomY) + viewBottomOffset; if(gdata->showMeanVarianceBars()) { //longTermMean bars y2 = height() - 1 - toInt((data->getLongTermMean() + data->getLongTermDeviation()) / zoomY) + viewBottomOffset; y3 = height() - 1 - toInt((data->getLongTermMean() - data->getLongTermDeviation()) / zoomY) + viewBottomOffset; if(ze.noteIndex() % 2 == 0) { evenMidPoints.setPoint(evenMidPointIndex++, n, y2); evenMidPoints.setPoint(evenMidPointIndex++, n, y3); } else { oddMidPoints.setPoint(oddMidPointIndex++, n, y2); oddMidPoints.setPoint(oddMidPointIndex++, n, y3); } //shortTermMean bars y2 = height() - 1 - toInt((data->getShortTermMean() + data->getShortTermDeviation()) / zoomY) + viewBottomOffset; y3 = height() - 1 - toInt((data->getShortTermMean() - data->getShortTermDeviation()) / zoomY) + viewBottomOffset; if(ze.noteIndex() % 2 == 0) { evenMidPoints2.setPoint(evenMidPointIndex2++, n, y2); evenMidPoints2.setPoint(evenMidPointIndex2++, n, y3); } else { oddMidPoints2.setPoint(oddMidPointIndex2++, n, y2); oddMidPoints2.setPoint(oddMidPointIndex2++, n, y3); } } //} else { // y2 = y3 = 0; } //topPoints.setPoint(pointIndex, n, 0); //topPoints.setPoint(pointIndex, n, y); bottomPoints.setPoint(pointIndex++, n, y); bottomPoints.setPoint(pointIndex++, n, height()); lastN = n; } //p.setPen(gdata->shading1Color()); //p.drawLineSegments(topPoints, 0, pointIndex/2); p.setPen(Qt::NoPen); p.setBrush(gdata->shading1Color()); p.drawRect(firstN, 0, lastN, height()); p.setPen(gdata->shading2Color()); //p.drawLineSegments(bottomPoints, 0, pointIndex/2); if(pointIndex > 1) p.drawLines(bottomPoints.constData(), pointIndex/2); if(gdata->showMeanVarianceBars()) { //shortTermMean bars p.setPen(Qt::green); //p.drawLineSegments(evenMidPoints2, 0, evenMidPointIndex2/2); if(evenMidPointIndex2 > 1) p.drawLines(evenMidPoints2.constData(), evenMidPointIndex2/2); p.setPen(Qt::yellow); //p.drawLineSegments(oddMidPoints2, 0, oddMidPointIndex2/2); if(oddMidPointIndex2 > 1) p.drawLines(oddMidPoints2.constData(), oddMidPointIndex2/2); //longTermMean bars p.setPen(Qt::yellow); //p.drawLineSegments(evenMidPoints, 0, evenMidPointIndex/2); if(evenMidPointIndex > 1) p.drawLines(evenMidPoints.constData(), evenMidPointIndex/2); p.setPen(Qt::green); //p.drawLineSegments(oddMidPoints, 0, oddMidPointIndex/2); if(oddMidPointIndex > 1) p.drawLines(oddMidPoints.constData(), oddMidPointIndex/2); } } else { // More pixels than samples float err = 0.0; float pitch = 0.0; 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, y2, y3; //double start = 0 - stepSize; double start = (double(intChunk) - frameTime) * stepSize; double stop = width() + (2 * stepSize); //int squareSize = (int(sqrt(stepSize)) / 2) * 2 + 1; //make it an odd number //int halfSquareSize = squareSize/2; //QPointArray topPoints(0); //QPointArray bottomPoints(0); //int pointIndex = 0; //topPoints.putPoints(pointIndex, 1, toInt(start), 0); //bottomPoints.putPoints(pointIndex, 1, toInt(start), height()); //pointIndex++; //topPoints.setPoint(pointIndex, toInt(start), 0); bottomPoints.setPoint(pointIndex++, toInt(start), height()); lastN = firstN = toInt(start); 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(); //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)); p.setPen(QPen(colorBetween(QColor(255, 255, 255), ch->color, err * dB2ViewVal(data->getLogRms())), lineWidth)); else p.setPen(QPen(ch->color, lineWidth)); x = toInt(n); lastN = x; //note = (data->isValid()) ? data->note : 0.0f; //note = (ch->isVisibleNote(data->noteIndex)) ? data->note : 0.0f; pitch = (ch->isVisibleChunk(data)) ? data->getPitch() : 0.0f; //if(ch->isVisibleChunk(data)) { if(data->getNoteIndex() >= 0) { isNoteRectEven[rectIndex] = (data->getNoteIndex() % 2) == 0; //note = data->note; //double avgNote = ch->noteData[data->noteIndex].avgNote(); //y2 = height() - 1 - toInt((avgNote+0.5) / zoomY) + viewBottomOffset; //y3 = height() - 1 - toInt((avgNote-0.5) / zoomY) + viewBottomOffset; //y2 = height() - 1 - toInt((data->shortTermMean + data->shortTermDeviation) / zoomY) + viewBottomOffset; //y3 = height() - 1 - toInt((data->shortTermMean - data->shortTermDeviation) / zoomY) + viewBottomOffset; if(gdata->showMeanVarianceBars()) { //longTermMean bars y2 = height() - 1 - toInt((data->getLongTermMean() + data->getLongTermDeviation()) / zoomY) + viewBottomOffset; y3 = height() - 1 - toInt((data->getLongTermMean() - data->getLongTermDeviation()) / zoomY) + viewBottomOffset; noteRect[rectIndex].setLeft(x); noteRect[rectIndex].setRight(toInt(n+stepSize)); noteRect[rectIndex].setTop(y2); noteRect[rectIndex++].setBottom(y3); //shortTermMean bars y2 = height() - 1 - toInt((data->getShortTermMean() + data->getShortTermDeviation()) / zoomY) + viewBottomOffset; y3 = height() - 1 - toInt((data->getShortTermMean() - data->getShortTermDeviation()) / zoomY) + viewBottomOffset; noteRect2[rectIndex2].setLeft(x); noteRect2[rectIndex2].setRight(toInt(n+stepSize)); noteRect2[rectIndex2].setTop(y2); noteRect2[rectIndex2++].setBottom(y3); } //} else { // note = 0.0f; } myassert(pitch >= 0.0 && pitch <= gdata->topPitch()); //note = bound(note, 0, gdata->topNote()); y = height() - 1 - toInt(pitch / zoomY) + viewBottomOffset; //y = height() - 1 - int((note / zoomY) - (viewBottom / zoomY)); //topPoints.putPoints(pointIndex, 1, x, y); //bottomPoints.putPoints(pointIndex, 1, x, y); //pointIndex++; //topPoints.setPoint(pointIndex, x, y); bottomPoints.setPoint(pointIndex++, x, y); } //topPoints.putPoints(pointIndex, 1, topPoints.point(pointIndex-1).x(), 0); //bottomPoints.putPoints(pointIndex, 1, bottomPoints.point(pointIndex-1).x(), height()); //pointIndex++; //topPoints.setPoint(pointIndex, topPoints.point(pointIndex-1).x(), 0); bottomPoints.setPoint(pointIndex, bottomPoints.point(pointIndex-1).x(), height()); pointIndex++; //p.setPen(gdata->shading1Color()); //p.setBrush(gdata->shading1Color()); //p.drawPolygon(topPoints); //p.setPen(gdata->shading2Color()); //p.setBrush(gdata->shading2Color()); //p.drawPolygon(bottomPoints); myassert(pointIndex <= width()*2); //p.setPen(gdata->shading1Color()); p.setPen(Qt::NoPen); p.setBrush(gdata->shading1Color()); //p.drawPolygon(topPoints, false, 0, pointIndex); p.drawRect(firstN, 0, lastN, height()); //p.setPen(gdata->shading2Color()); p.setBrush(gdata->shading2Color()); //p.drawPolygon(bottomPoints, false, 0, pointIndex); p.drawPolygon(bottomPoints.constData(), pointIndex, Qt::OddEvenFill); if(gdata->showMeanVarianceBars()) { //shortTermMean bars for(int j=0; j<rectIndex2; j++) { if(isNoteRectEven[j]) p.setBrush(Qt::green); else p.setBrush(Qt::yellow); p.drawRect(noteRect2[j]); } //longTermMean bars QColor seeThroughYellow = Qt::yellow; seeThroughYellow.setAlpha(255); QColor seeThroughGreen = Qt::green; seeThroughGreen.setAlpha(255); for(int j=0; j<rectIndex; j++) { //if(isNoteRectEven[j]) p.setBrush(QBrush(Qt::yellow, Qt::Dense3Pattern)); //else p.setBrush(QBrush(Qt::green, Qt::Dense3Pattern)); if(isNoteRectEven[j]) p.setBrush(seeThroughYellow); else p.setBrush(seeThroughGreen); p.drawRect(noteRect[j]); } } } }
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; } } }
void CorrelationWidget::paintEvent( QPaintEvent * ) { Channel *active = gdata->getActiveChannel(); AnalysisData *data = NULL; int chunk=0; double dh2 = double(height()-1) / 2.0; int j, x, y; beginDrawing(false); if(active) { active->lock(); chunk = active->currentChunk(); data = active->dataAtChunk(chunk); //int centerX = width() / 2; if(data) { double freq = data->getFundamentalFreq(); double period = double(active->rate()) / freq; //double numPeriods = double(active->size()) / period; double scaleX = period * double(width()) / double(active->nsdfData.size()); //pixels per period //draw alternating background color indicating period if(gdata->view->backgroundShading() && period > 4.0 && period < double(active->nsdfData.size())) { int n = int(ceil(double(width()) / scaleX)); //number of colored patches p.setPen(Qt::NoPen); QColor color1 = colorBetween(gdata->backgroundColor(), gdata->shading1Color(), data->getCorrelation()); QColor color2 = colorBetween(gdata->backgroundColor(), gdata->shading2Color(), data->getCorrelation()); for(j = 0; j<n; j++) { x = toInt(scaleX*double(j)); p.setBrush((j%2) ? color1 : color2); p.drawRect(x, 0, toInt(scaleX*double(j+1)) - toInt(scaleX*double(j)), height()); } p.setPen(colorBetween(gdata->backgroundColor(), Qt::black, 0.3 * data->getCorrelation())); for(j = 0; j<n; j++) { x = toInt(scaleX*double(j)); p.drawLine(x, 0, x, height()); } } else { clearBackground(); } QString numPeriodsText; numPeriodsText.sprintf("Period = %lf", period); p.setPen(Qt::black); p.drawText(5, height() - 8, numPeriodsText); } else { clearBackground(); } } else { clearBackground(); } //draw the horizontal center line p.setPen(QPen(colorBetween(colorGroup().background(), Qt::black, 0.3), 0)); p.drawLine(0, toInt(dh2), width(), toInt(dh2)); if(active) { if(gdata->doingFreqAnalysis()) { int w = width() / 2; //only do every second pixel (for speed) //draw the waveform if(int(pointArray.size()) != w) pointArray.resize(w); if(lookup.size() != w) lookup.resize(w); NoteData *currentNote = active->getCurrentNote(); Array1d<float> *input = &(active->nsdfData); if(currentNote) { if(aggregateMode == 1) input = ¤tNote->nsdfAggregateData; else if(aggregateMode == 2) input = ¤tNote->nsdfAggregateDataScaled; } //bresenham1d(*input, lookup); maxAbsDecimate1d(*input, lookup); for(int j=0; j<w; j++) { pointArray.setPoint(j, j*2, toInt(dh2 - lookup[j]*dh2)); } p.setPen(QPen(active->color, 0)); p.drawPolyline(pointArray); } if(data && (aggregateMode == 0)) { double ratio = double(width()) / double(active->nsdfData.size()); //pixels per index //float highest = active->nsdfData.at(data->highestCorrelationIndex); //float chosen = active->nsdfData.at(data->chosenCorrelationIndex); //draw a dot at all the period estimates p.setPen(Qt::blue); p.setBrush(Qt::blue); for(j=0; j<int(data->getPeriodEstimatesSize()); j++) { x = toInt(double(data->getPeriodEstimatesAt(j)) * ratio); y = toInt(dh2 - data->getPeriodEstimatesAmpAt(j) * dh2); p.drawEllipse(x-2, y-2, 5, 5); } if(data->getHighestCorrelationIndex() >= 0) { float highest = data->getPeriodEstimatesAmpAt(data->getHighestCorrelationIndex()); //draw threshold line p.setPen(QPen(colorBetween(colorGroup().background(), Qt::black, 0.3), 0)); y = toInt(dh2 - (highest * active->threshold()) * dh2); p.drawLine(0, y, width(), y); //draw a dot at the highest correlation period p.setPen(Qt::black); p.setBrush(Qt::black); //x = toInt(double(data->highestCorrelationIndex) * ratio); x = toInt(double(data->getPeriodEstimatesAt(data->getHighestCorrelationIndex())) * ratio); y = toInt(dh2 - highest * dh2); p.drawEllipse(x-2, y-2, 5, 5); } //draw a dot at the chosen correlation period if(data->getChosenCorrelationIndex() >= 0) { p.setPen(Qt::red); p.setBrush(Qt::red); //x = toInt(double(data->chosenCorrelationIndex) * ratio); //y = toInt(dh2 - chosen * dh2); x = toInt(double(data->getPeriodEstimatesAt(data->getChosenCorrelationIndex())) * ratio); y = toInt(dh2 - data->getPeriodEstimatesAmpAt(data->getChosenCorrelationIndex()) * dh2); p.drawEllipse(x-2, y-2, 5, 5); } //draw a line at the chosen correlation period if(data->getChosenCorrelationIndex() >= 0) { p.setPen(Qt::green); p.setBrush(Qt::green); //x = toInt(double(data->periodOctaveEstimate) * ratio); x = toInt(double(active->periodOctaveEstimate(chunk)) * ratio); p.drawLine(x, 0, x, height()); } } active->unlock(); } endDrawing(); }
//void MyTransforms::calculateAnalysisData(float *input, AnalysisData &analysisData, Channel *ch, float threshold) void MyTransforms::calculateAnalysisData(/*float *input, */int chunk, Channel *ch/*, float threshold*/) { myassert(ch); myassert(ch->dataAtChunk(chunk)); AnalysisData &analysisData = *ch->dataAtChunk(chunk); AnalysisData *prevAnalysisData = ch->dataAtChunk(chunk-1); //Array1d<float> output(k); float *output = ch->nsdfData.begin(); float *curInput = (equalLoudness) ? ch->filteredInput.begin() : ch->directInput.begin(); std::vector<int> nsdfMaxPositions; //int pos = 0; //int curMaxPos = 0; //float corrError = 0.0f; //freqPerBin = rate / 2.0 / double(size); //analysisData.maxIntensity = fabs(*std::max_element(input, input+n, absoluteLess())); analysisData.maxIntensityDB() = linear2dB(fabs(*std::max_element(curInput, curInput+n, absoluteLess<float>()))); //if(gdata->doingActiveFFT()) { //std::copy(curInput, curInput+n, dataTime); doChannelDataFFT(ch, curInput, chunk); //std::copy(dataTemp, dataTemp+n, dataTime); //} std::copy(curInput, curInput+n, dataTime); //if(!gdata->doingActiveAnalysis()) return; //if(gdata->doingFreqAnalysis()) { if(gdata->doingFreqAnalysis() && (ch->firstTimeThrough() || gdata->doingActiveAnalysis())) { //calculate the Normalised Square Difference Function //analysisData.rms = nsdf(dataTime, output.begin()) / double(n/*size*/); //analysisData.rms = nsdf(dataTime, output) / double(n/*size*/); double logrms = linear2dB(nsdf(dataTime, ch->nsdfData.begin()) / double(n)); /**< Do the NSDF calculation */ analysisData.logrms() = logrms; if(gdata->doingAutoNoiseFloor() && !analysisData.done) { //do it for gdata. this is only here for old code. remove some stage if(chunk == 0) { gdata->rmsFloor() = 0.0; gdata->rmsCeiling() = gdata->dBFloor(); } if(logrms+15 < gdata->rmsFloor()) gdata->rmsFloor() = logrms+15; if(logrms > gdata->rmsCeiling()) gdata->rmsCeiling() = logrms; //do it for the channel if(chunk == 0) { ch->rmsFloor = 0.0; ch->rmsCeiling = gdata->dBFloor(); } if(logrms+15 < ch->rmsFloor) ch->rmsFloor = logrms+15; if(logrms > ch->rmsCeiling) ch->rmsCeiling = logrms; } //if(!analysisData.done) { //analysisData.notePlaying = ch->isNotePlaying(); //if(ch->isNotePlaying()) // addTo(ch->nsdfData.begin(), ch->nsdfData.end(), ch->nsdfAggregateData.begin()); //} //analysisData.freqCentroid() = calcFreqCentroid(storeFFT, size); analysisData.freqCentroid() = calcFreqCentroidFromLogMagnitudes(ch->fftData1.begin(), ch->fftData1.size()); if(prevAnalysisData) analysisData.deltaFreqCentroid() = bound(fabs(analysisData.freqCentroid() - prevAnalysisData->freqCentroid())*20.0, 0.0, 1.0); else analysisData.deltaFreqCentroid() = 0.0; findNSDFMaxima(ch->nsdfData.begin(), k, nsdfMaxPositions); if(!analysisData.done) { //if(ch->isNotePlaying()) { //analysisData.periodOctaveEstimate = ch->calcOctaveEstimate(chunk, threshold); /* findNSDFMaxima(ch->nsdfAggregateData.begin(), k, nsdfAggregateMaxPositions); myassert(!nsdfAggregateMaxPositions.empty()); //get the highest nsdfAggregateMaxPosition uint j; int nsdfAggregateMaxIndex = 0; int nsdfAggregateChoosenIndex = 0; for(j=1; j<nsdfAggregateMaxPositions.size(); j++) { if(ch->nsdfAggregateData[nsdfAggregateMaxPositions[j]] > ch->nsdfAggregateData[nsdfAggregateMaxPositions[nsdfAggregateMaxIndex]]) nsdfAggregateMaxIndex = j; } //get the choosen nsdfAggregateMaxPosition float nsdfAggregateCutoff = ch->nsdfAggregateData[nsdfAggregateMaxPositions[nsdfAggregateMaxIndex]] * threshold; for(j=0; j<nsdfAggregateMaxPositions.size(); j++) { if(ch->nsdfAggregateData[nsdfAggregateMaxPositions[j]] >= nsdfAggregateCutoff) { nsdfAggregateChoosenIndex = j; break; } } analysisData.periodOctaveEstimate = float(nsdfAggregateMaxPositions[nsdfAggregateChoosenIndex]+1); //add 1 for index offset, ie position 0 = 1 period */ } //store some of the best period estimates analysisData.periodEstimates.clear(); analysisData.periodEstimatesAmp.clear(); //float smallThreshold = 0.7f; //float smallCutoff = output[overallMaxIndex] * smallThreshold; float smallCutoff = 0.4f; for(std::vector<int>::iterator iter = nsdfMaxPositions.begin(); iter < nsdfMaxPositions.end(); iter++) { if(output[*iter] >= smallCutoff) { //analysisData.periodEstimates.push_back(double(*iter + 1) + parabolaTurningPoint(output[*iter-1], output[*iter], output[*iter+1])); //analysisData.periodEstimatesAmp.push_back(output[*iter]); //TODO: These should be calculated more accurately float x, y; //do a parabola fit to find the maximum parabolaTurningPoint2(output[*iter-1], output[*iter], output[*iter+1], float(*iter + 1), &x, &y); y = bound(y, -1.0f, 1.0f); analysisData.periodEstimates.push_back(x); analysisData.periodEstimatesAmp.push_back(y); } } float periodDiff = 0.0f; //if(maxPositions.empty()) { //no period found if(analysisData.periodEstimates.empty()) { //no period found //analysisData.correlation() = 0.0f; analysisData.calcScores(); analysisData.done = true; //goto finished; //return; } else { //calc the periodDiff if(chunk > 0 && prevAnalysisData->highestCorrelationIndex!=-1) { float prevPeriod = prevAnalysisData->periodEstimates[prevAnalysisData->highestCorrelationIndex]; std::vector<float>::iterator closestIter = binary_search_closest(analysisData.periodEstimates.begin(), analysisData.periodEstimates.end(), prevPeriod); //print_elements(analysisData.periodEstimates.begin(), analysisData.periodEstimates.end()); //printf("closestIter = %f, %f\n", *closestIter, prevPeriod); periodDiff = *closestIter - prevPeriod; if(absolute(periodDiff) > 8.0f) periodDiff = 0.0f; } int nsdfMaxIndex = int(std::max_element(analysisData.periodEstimatesAmp.begin(), analysisData.periodEstimatesAmp.end()) - analysisData.periodEstimatesAmp.begin()); analysisData.highestCorrelationIndex = nsdfMaxIndex; if(!analysisData.done) { //if(gdata->doingActiveCepstrum()) { if(gdata->analysisType() == MPM_MODIFIED_CEPSTRUM) { ch->chooseCorrelationIndex(chunk, float(analysisData.cepstrumIndex)); //calculate pitch } else { if(ch->isNotePlaying() && chunk > 0) { //ch->chooseCorrelationIndex(chunk, ch->getLastNote()->periodOctaveEstimate()); //calculate pitch //ch->chooseCorrelationIndex(chunk, ch->periodOctaveEstimate(std::max(0, chunk-1))); //calculate pitch ch->chooseCorrelationIndex(chunk, ch->periodOctaveEstimate(chunk-1)); //calculate pitch } else { ch->chooseCorrelationIndex1(chunk); //calculate pitch } //ch->chooseCorrelationIndex(chunk, (float)ch->rate() / 440.0f); //calculate pitch } ch->calcDeviation(chunk); ch->doPronyFit(chunk); //calculate vibratoPitch, vibratoWidth, vibratoSpeed } analysisData.changeness() = 0.0f; //analysisData.changeness() = get_max_note_change(dataTime, analysisData.period); if(gdata->doingHarmonicAnalysis()) { std::copy(dataTime, dataTime+n, dataTemp); if(analysisData.chosenCorrelationIndex >= 0) doHarmonicAnalysis(dataTemp, analysisData, analysisData.periodEstimates[analysisData.chosenCorrelationIndex]/*period*/); //doHarmonicAnalysis(input, analysisData, period); } //analysisData.volumeValue = (dB2Normalised(analysisData.logrms) + (analysisData.correlation-1.0f)) * 0.2; } //float periodDiff = 0.0f; if(gdata->doingFreqAnalysis() && ch->doingDetailedPitch() && ch->firstTimeThrough()) { //periodDiff = ch->calcDetailedPitch(curInput, analysisData.period, chunk); float periodDiff2 = ch->calcDetailedPitch(curInput, analysisData.period, chunk); //printf("chunk=%d, %f, %f\n", chunk, periodDiff, periodDiff2); periodDiff = periodDiff2; ch->pitchLookup.push_back(ch->detailedPitchData.begin(), ch->detailedPitchData.size()); ch->pitchLookupSmoothed.push_back(ch->detailedPitchDataSmoothed.begin(), ch->detailedPitchDataSmoothed.size()); /* float periodDiff1 = (rate / pitch2freq(ch->detailedPitchData.back())); float periodDiff2 = (rate / pitch2freq(ch->detailedPitchData.front())); periodDiff = periodDiff1 - periodDiff2; printf("%f, %f, %f\n", periodDiff1, periodDiff2, periodDiff); */ } if(!analysisData.done) { analysisData.calcScores(); ch->processNoteDecisions(chunk, periodDiff); analysisData.done = true; } if(gdata->doingFreqAnalysis() && ch->doingDetailedPitch() && ch->firstTimeThrough()) { ch->calcVibratoData(chunk); } } if(gdata->doingFreqAnalysis() && ch->doingDetailedPitch() && (!ch->firstTimeThrough())) { ch->pitchLookup.copyTo(ch->detailedPitchData.begin(), chunk*ch->detailedPitchData.size(), ch->detailedPitchData.size()); ch->pitchLookupSmoothed.copyTo(ch->detailedPitchDataSmoothed.begin(), chunk*ch->detailedPitchDataSmoothed.size(), ch->detailedPitchDataSmoothed.size()); } if(!analysisData.done) { int j; //calc rms by hand double rms = 0.0; for(j=0; j<n; j++) { rms += sq(dataTime[j]); } //analysisData.rms = sqrt(analysisData.rms); analysisData.logrms() = linear2dB(rms / float(n)); analysisData.calcScores(); analysisData.done = true; } }
//------------------------------------------------------------------------------ bool lessFundametalFreq::operator()(const AnalysisData & x, const AnalysisData & y) { return x.getFundamentalFreq() < y.getFundamentalFreq(); }
void HBlockWidget::paintEvent( QPaintEvent * ) { Channel *active = gdata->getActiveChannel(); beginDrawing(); if(active) { AnalysisData *theData = active->dataAtCurrentChunk(); if(theData) { //get a copy of theData so we don't hold the mutex for too long active->lock(); AnalysisData data = *theData; active->unlock(); // We have harmonicFreq - the actual frequencies of the harmonies - and harmonicAmp, their amplitude //std::vector<float> harmonicFreq = active->lookup[frame].harmonicFreq; std::vector<float> harmonicFreq = data.harmonicFreq; // harmonicAmp values range between 0-1 //std::vector<float> harmonicAmp = active->lookup[frame].harmonicAmp; std::vector<float> harmonicAmp = data.harmonicAmp; // Get the frame's fundamental frequency //float fund = active->lookup[frame].fundamentalFreq; float fund = data.fundamentalFreq; // Work out the bar height for each harmonic double barHeight = double(height()) / double(harmonicFreq.size()); QColor fillColor = colorBetween(colorGroup().background(), active->color, data.volumeValue()); QColor outlineColor = colorBetween(colorGroup().background(), Qt::black, data.volumeValue()); p.setBrush(fillColor); int barStart = 0; float barWidth = 0; int diff = 0; /* * Each note has a fundamental frequency f, which comes from the lookup table. * The harmonic frequencies are defined as f, 2f, 3f, 4f, 5f... * harmonicFreq stores what the harmonics have been calculated to be. */ for (uint i = 0; i < harmonicFreq.size(); i++) { p.setPen(outlineColor); p.setBrush(colorBetween(fillColor, Qt::black, data.harmonicNoise[i])); // Work out how many pixels wide the harmonic should be barWidth = (harmonicAmp.at(i)) * width(); /* Work out how many pixels the harmonic should be offset from where it would be * if it were exactly (i+1)f */ //diff = toInt( (harmonicFreq.at(i) - (i+1) * fund) / fund * width() / 10.0 ); diff = toInt( (harmonicFreq.at(i) - (i+1) * fund) / fund * barWidth ); // Work out the starting position, and draw the bar barStart = toInt( ((width() / 2) + diff) - barWidth / 2); int barBottom = height() - toInt(barHeight * i); p.drawRect(barStart, barBottom, toInt(barWidth), -toInt(barHeight)); // Draw the centre line on the bar p.setPen(Qt::white); p.drawLine((width() / 2) + diff, barBottom, (width() / 2) + diff, barBottom - toInt(barHeight)); } // Draw the exact line (f, 2f, 3f...) p.setPen(Qt::white); p.drawLine(width() / 2, 0, width() /2, height()); } } endDrawing(); }
//------------------------------------------------------------------------------ bool greaterValue::operator()(const AnalysisData &x, const AnalysisData &y) { return x.getValue(v) > y.getValue(v); }
//------------------------------------------------------------------------------ bool lessValue::operator()(const AnalysisData &x, const AnalysisData &y) { return x.getValue(v) < y.getValue(v); }
//------------------------------------------------------------------------------ bool greaterPitch::operator()(const AnalysisData &x, const AnalysisData &y) { return x.getPitch() > y.getPitch(); }
//------------------------------------------------------------------------------ bool lessPitch::operator()(const AnalysisData &x, const AnalysisData &y) { return x.getPitch() < y.getPitch(); }
//------------------------------------------------------------------------------ bool greaterFundametalFreq::operator()(const AnalysisData &x, const AnalysisData &y) { return x.getFundamentalFreq() > y.getFundamentalFreq(); }
void VibratoTimeAxis::doUpdate() { Channel *active = gdata->getActiveChannel(); int myStartChunk = -1; int myCurrentChunk = -1; int myEndChunk = -1; double myNoteLength = 0.0; int myWindowOffset = -999999; if (active) { AnalysisData *data = active->dataAtCurrentChunk(); if(data && active->isVisibleNote(data->getNoteIndex()) && active->isLabelNote(data->getNoteIndex())) { NoteData *note = new NoteData(); note = &active->noteData[data->getNoteIndex()]; myStartChunk = note->startChunk(); myCurrentChunk = active->chunkAtCurrentTime(); myEndChunk = note->endChunk(); myNoteLength = note->noteLength(); // Calculate windowoffset if ((myEndChunk - myStartChunk) * zoomFactorX > width() - 2 * noteLabelOffset) { // The vibrato-polyline doesn't fit in the window if ((myCurrentChunk - myStartChunk) * zoomFactorX < (width() - 2 * noteLabelOffset)/2) { // We're at the left side of the vibrato-polyline myWindowOffset = 0 - noteLabelOffset; } else if ((myEndChunk - myCurrentChunk) * zoomFactorX < (width() - 2 * noteLabelOffset)/2) { // We're at the right side of the vibrato-polyline myWindowOffset = toInt((myEndChunk - myStartChunk) * zoomFactorX - width() + noteLabelOffset + 1); } else { // We're somewhere in the middle of the vibrato-polyline myWindowOffset = toInt((myCurrentChunk - myStartChunk) * zoomFactorX - width()/2); } } else { // The vibrato-polyline does fit in the window myWindowOffset = 0 - noteLabelOffset; } } } if (myCurrentChunk == -1) { // No note if (prevCurrentChunk == myCurrentChunk) { // Still no timeaxis needed, no update needed } else { // Timeaxis should be erased, update widget prevCurrentChunk = -1; prevWindowOffset = -999999; currentChunkToUse = -1; } } else { // Note if (prevWindowOffset == myWindowOffset) { // No movement, don't redraw timeaxis } else { // Position in note to draw has changed, so draw the timeaxis prevCurrentChunk = myCurrentChunk; prevWindowOffset = myWindowOffset; startChunkToUse = myStartChunk; currentChunkToUse = myCurrentChunk; endChunkToUse = myEndChunk; noteLengthToUse = myNoteLength; windowOffsetToUse = myWindowOffset; } } }
//void AmplitudeWidget::drawChannelAmplitudeFilled(Channel *ch, QPainter &p) void AmplitudeWidget::drawChannelAmplitudeFilledGL(Channel *ch) { View *view = gdata->view; ChannelLocker channelLocker(ch); ZoomLookup *z = &ch->amplitudeZoomLookup; // baseX is the no. of chunks a pixel must represent. double baseX = view->zoomX() / ch->timePerChunk(); z->setZoomLevel(baseX); double currentChunk = ch->chunkFractionAtTime(view->currentTime()); double leftFrameTime = currentChunk - ((view->currentTime() - view->viewLeft()) / ch->timePerChunk()); int n = 0; int baseElement = int(floor(leftFrameTime / baseX)); if(baseElement < 0) { n -= baseElement; baseElement = 0; } int lastBaseElement = int(floor(double(ch->totalChunks()) / baseX)); //double heightRatio = double(height()) / dBRange(); double heightRatio = double(height()) / range(); //int firstN = n; //int lastN = firstN; //Q3PointArray bottomPoints(width()*2); Array1d<MyGLfloat2d> vertexArray(width()*2); int pointIndex = 0; //int topBottomPointIndex = 0; if (baseX > 1) { // More samples than pixels int theWidth = 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(!z->hasValue(baseElement)) { if(!ze.isValid()) { if(!calcZoomElement(ze, ch, baseElement, baseX)) continue; } int y = height() - 1 - toInt((ze.high() - offsetInv()) * heightRatio); //bottomPoints.setPoint(topBottomPointIndex++, n, y); //bottomPoints.setPoint(topBottomPointIndex++, n, height()); vertexArray[pointIndex++] = MyGLfloat2d(n, y); vertexArray[pointIndex++] = MyGLfloat2d(n, height()); //lastN = n; } //p.setPen(Qt::NoPen); //p.setBrush(gdata->shading1Color()); //p.drawRect(firstN, 0, lastN, height()); //p.setPen(gdata->shading2Color()); //p.drawLineSegments(bottomPoints, 0, topBottomPointIndex/2); qglColor(gdata->shading2Color()); glVertexPointer(2, GL_FLOAT, 0, vertexArray.begin()); glDrawArrays(GL_QUAD_STRIP, 0, pointIndex); } else { //baseX <= 1 float err = 0.0; float val = 0.0; int intChunk = (int) floor(leftFrameTime); // Integer version of frame time double stepSize = 1.0 / baseX; // So we skip some pixels float x = 0.0f, y; //double start = 0 - stepSize; double start = (double(intChunk) - leftFrameTime) * stepSize; double stop = width() + (2 * stepSize); //int squareSize = (int(sqrt(stepSize)) / 2) * 2 + 1; //make it an odd number //int halfSquareSize = squareSize/2; double dn = start; int totalChunks = ch->totalChunks(); if(intChunk < 0) { dn += stepSize * -intChunk; intChunk = 0; } //bottomPoints.setPoint(topBottomPointIndex++, toInt(dn), height()); //vertexArray[pointIndex++] = MyGLfloat2d((GLfloat)dn, height()); //firstN = toInt(dn); for(; dn < stop && intChunk < totalChunks; dn += stepSize, intChunk++) { AnalysisData *data = ch->dataAtChunk(intChunk); myassert(data); if(!data) continue; err = data->correlation(); val = calculateElement(data); //p.setPen(QPen(colorBetween(colorGroup().background(), ch->color, val), 1)); x = dn; y = height() - 1 - ((val - offsetInv()) * heightRatio); //bottomPoints.setPoint(topBottomPointIndex++, x, y); vertexArray[pointIndex++] = MyGLfloat2d(x, y); vertexArray[pointIndex++] = MyGLfloat2d(x, height()); //lastN = x; } //bottomPoints.setPoint(topBottomPointIndex, bottomPoints.point(topBottomPointIndex-1).x(), height()); //if(pointIndex > 0) { // vertexArray[pointIndex] = MyGLfloat2d(vertexArray[pointIndex-1].x, height()); // pointIndex++; //} myassert(pointIndex <= width()*2); //p.setPen(Qt::NoPen); //p.setBrush(gdata->shading1Color()); //p.drawRect(firstN, 0, lastN, height()); //p.setPen(gdata->shading2Color()); //p.setBrush(gdata->shading2Color()); //p.drawPolygon(bottomPoints, false, 0, topBottomPointIndex); qglColor(gdata->shading2Color()); glVertexPointer(2, GL_FLOAT, 0, vertexArray.begin()); glDrawArrays(GL_QUAD_STRIP, 0, pointIndex); } }