// ResidualsSpecgramGraphicsScene class implementation // // The QGraphicsScene-derived residual bands spectrogram scene // // QATSH Copyright 2009 Jean-Philippe MEURET #include #include #include #include #include #include #include #include #include #include "ATSMath.h" #include "ResidualsSpecgramGraphicsScene.h" #include "ATSModelManager.h" #include "ATSModel.h" #include "ATSModelItems.h" #include "ATSPropertiesProxyModel.h" #include "ATSResidualsProxyModel.h" ResidualsSpecgramGraphicsScene::ResidualsSpecgramGraphicsScene(QObject *parent) : QGraphicsScene(parent), _pModelMgr(0) { } ResidualsSpecgramGraphicsScene::~ResidualsSpecgramGraphicsScene() { clear(); } void ResidualsSpecgramGraphicsScene::setModelManager(ATSModelManager* pModelMgr) { // Save pointer to model for later. _pModelMgr = pModelMgr; // Connect to any model change. if (_pModelMgr) { connect(_pModelMgr->residualsModel(), SIGNAL(modelReset()), this, SLOT(onModelReset())); connect(_pModelMgr->residualsModel(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(onDataChanged(const QModelIndex&, const QModelIndex&))); } // Load scene from model : create graphic items from partials data loadFromModel(); } void ResidualsSpecgramGraphicsScene::onModelReset() { std::cout << "ResidualsSpecgramGraphicsScene::onModelReset()" << std::endl; clear(); loadFromModel(); } void ResidualsSpecgramGraphicsScene::onDataChanged(const QModelIndex& qmiTopLeft, const QModelIndex& qmiBotRight) { // TODO : Check really changed rect if usefull here ... // TODO : Update item properties (and add/remove items ?) std::cout << "ResidualsSpecgramGraphicsScene::onDataChanged : Not yet implemented" << std::endl; } // Set amplitude color contrast in [0, 1] void ResidualsSpecgramGraphicsScene::setAmplitudeContrast(double dContrast) { //std::cout << "ResidualsSpecgramGraphicsScene::setAmplitudeContrast(" // << dContrast << ")" << std::endl; clear(); _cmAmplColorMap.setContrast(dContrast); loadResidual(); emit colorMapChanged(&_cmAmplColorMap); } // Set amplitude color brightness in [0, 1] void ResidualsSpecgramGraphicsScene::setAmplitudeBrightness(double dBrightness) { //std::cout << "ResidualsSpecgramGraphicsScene::setAmplitudeBrightness(" // << dBrightness << ")" << std::endl; clear(); _cmAmplColorMap.setBrightness(dBrightness); loadResidual(); emit colorMapChanged(&_cmAmplColorMap); } void ResidualsSpecgramGraphicsScene::loadFromModel() { ATSPropertiesProxyModel* pPropsModel = _pModelMgr->propertiesModel(); // Initialize scene rect from model // (x = time from 0 to sound.duration, y = frequency from 0 to sound.residualBandsMaxFreq). const QModelIndex miDuration = pPropsModel->index(0, ATSFilePropertiesItem::eSoundPropDuration, QModelIndex()); const double dMaxTime = pPropsModel->data(miDuration, Qt::DisplayRole).toDouble(); const double dMinTime = 0.0; const QModelIndex miMaxFreq = pPropsModel->index(0, ATSFilePropertiesItem::eSoundPropMaxResidualFrequency, QModelIndex()); const double dMaxFreq = pPropsModel->data(miMaxFreq, Qt::DisplayRole).toDouble(); const double dMinFreq = 0.0; setSceneRect(dMinTime, dMinFreq, dMaxTime - dMinTime, dMaxFreq - dMinFreq); // std::cout << "ResidualsSpecgramGraphicsScene::loadFromModel : " // << "duration = " << dMaxTime // << ", max. freq. = " << dMaxFreq << std::endl; // Reset amplitude color map. const QModelIndex miMaxAmpl = pPropsModel->index(0, ATSFilePropertiesItem::eSoundPropMaxResidualEnergy, QModelIndex()); const double dMinAmpl = 0.0; const double dMaxAmpl = pPropsModel->data(miMaxAmpl, Qt::DisplayRole).toDouble(); _cmAmplColorMap.reset(ColorMap::eStyleStandard, 256, dMinAmpl, dMaxAmpl); emit colorMapChanged(&_cmAmplColorMap); // Reset time ruler spec. const double dTimeRulerBaseStep = pow(10.0, floor(log10(dMaxTime - dMinTime))); _rsTimeRulerSpec.reset(RulerSpec::eHorizontal, RulerSpec::ePositive, RulerSpec::ePositiveSide, dMinTime, dMaxTime, 0.0, dTimeRulerBaseStep, 10.0, QList() << 2 << 5, QList() << 0.6 << 0.3); emit timeRangeChanged(&_rsTimeRulerSpec); // Reset frequency ruler spec. const double dFreqRulerBaseStep = pow(10.0, floor(log10(dMaxFreq - dMinFreq))); _rsFreqRulerSpec.reset(RulerSpec::eVertical, RulerSpec::ePositive, RulerSpec::ePositiveSide, dMinFreq, dMaxFreq, 0.0, dFreqRulerBaseStep, 10.0, QList() << 2 << 5, QList() << 0.4 << 0.2); emit frequencyRangeChanged(&_rsFreqRulerSpec); // Draw residual. loadResidual(); } void ResidualsSpecgramGraphicsScene::loadResidual() { ATSPropertiesProxyModel* pPropsModel = _pModelMgr->propertiesModel(); // Create items from model (1 rectangle for each frame of each band, // 1 item group of frame rectangle items for each band). // a) Get the number of bands. const QModelIndex miNbBands = pPropsModel->index(0, ATSFilePropertiesItem::eSoundPropNbResidualBands, QModelIndex()); const int nBands = pPropsModel->data(miNbBands, Qt::DisplayRole).toInt(); // b) Get the number of frames. const QModelIndex miNbFrames = pPropsModel->index(0, ATSFilePropertiesItem::eSoundPropNbFrames, QModelIndex()); const int nFrames = pPropsModel->data(miNbFrames, Qt::DisplayRole).toInt(); // c) Get the sampling rate. const QModelIndex miSampRate = pPropsModel->index(0, ATSFilePropertiesItem::eSoundPropSamplingRate, QModelIndex()); const double dSampRate = pPropsModel->data(miSampRate, Qt::DisplayRole).toDouble(); // d) Get the frame size (in samples). const QModelIndex miFrameSize = pPropsModel->index(0, ATSFilePropertiesItem::eSoundPropFrameSize, QModelIndex()); const int nFrameSize = pPropsModel->data(miFrameSize, Qt::DisplayRole).toInt(); // e) Compute frame duration (s). const double dFrameDur = nFrameSize / dSampRate; // std::cout << "ResidualsSpecgramGraphicsScene::loadFromModel : " // << "bands = " << nBands // << ", frames = " << nFrames // << ", samp. rate = " << dSampRate // << ", frame size = " << nFrameSize // << ", frame dur. = " << dFrameDur << std::endl; // f) For each band : ATSResidualsProxyModel* pResidsModel = _pModelMgr->residualsModel(); for (int nBandInd = 0; nBandInd < nBands; nBandInd++) { // g) Get index of "residual band" model item of index "nBandInd". const QModelIndex miBand = pResidsModel->index(0, nBandInd, QModelIndex()); //std::cout << "ResidualsSpecgramGraphicsScene::loadFromModel : " // << "Band #" << nBandInd << " : " << std::endl; // h) For each frame : QGraphicsItemGroup* pgigBand = new QGraphicsItemGroup; for (int nFrameInd = 0; nFrameInd < nFrames; nFrameInd++) { // i) Get band start time, min/max frequency and energy for that frame const QModelIndex miBandFrameStartTime = pResidsModel->index(nFrameInd, ATSResidualBandItem::ePropTime, miBand); const double dStartTime = pResidsModel->data(miBandFrameStartTime, Qt::DisplayRole).toDouble(); const QModelIndex miBandFrameMinFreq = pResidsModel->index(nFrameInd, ATSResidualBandItem::ePropMinFrequency, miBand); const double dMinFreq = pResidsModel->data(miBandFrameMinFreq, Qt::DisplayRole).toDouble(); const QModelIndex miBandFrameMaxFreq = pResidsModel->index(nFrameInd, ATSResidualBandItem::ePropMaxFrequency, miBand); const double dMaxFreq = pResidsModel->data(miBandFrameMaxFreq, Qt::DisplayRole).toDouble(); const QModelIndex miBandFrameEnergy = pResidsModel->index(nFrameInd, ATSResidualBandItem::ePropEnergy, miBand); const double dEnergy = pResidsModel->data(miBandFrameEnergy, Qt::DisplayRole).toDouble(); //std::cout << " Frame #" << nFrameInd // << " : dStartTime = " << dStartTime // << ", minFreq = " << dMinFreq // << ", maxFreq = " << dMaxFreq // << ", energy = " << dEnergy << std::endl; // j) Create a rectangle item for a constant fill color (energy), // with the right frequency range, along the whole frame. QGraphicsRectItem* pgilBandFrame = new QGraphicsRectItem(0.0, 0.0, dFrameDur, dMaxFreq - dMinFreq); pgilBandFrame->setPos(dStartTime, dMinFreq); pgilBandFrame->setPen(Qt::NoPen); pgilBandFrame->setBrush(QBrush(_cmAmplColorMap.color(dEnergy))); pgigBand->addToGroup(pgilBandFrame); } addItem(pgigBand); } }