325 lines
11 KiB
C++
325 lines
11 KiB
C++
|
// DataSelectionWidget class definition
|
||
|
//
|
||
|
// The partials / residual bands selector widget
|
||
|
//
|
||
|
// QATSH Copyright 2009 Jean-Philippe MEURET <jpmeuret@free.fr>
|
||
|
|
||
|
#include <iostream>
|
||
|
|
||
|
#include "ATSModelManager.h"
|
||
|
#include "ATSPartialsProxyModel.h"
|
||
|
#include "ATSResidualsProxyModel.h"
|
||
|
|
||
|
#include "DataSelectionWidget.h"
|
||
|
#include "ui_DataSelectionWidget.h"
|
||
|
|
||
|
|
||
|
// Note for partial amplitude-related data types (for each partial, independently) :
|
||
|
// * Peak=Max. amplitude = max(partial.amp(frame) for frame in [0, nFrames])
|
||
|
// * RMS power amplitude = sqrt(sum(partial.amp(frame)**2 for frame in [0, nFrames]) / nFrames)
|
||
|
// Partial are selected iif computedAmplitude >= 10**(UserThreshold_dB/20)
|
||
|
|
||
|
// Const data for available value types for each possible data types
|
||
|
static const int KNMaxValueTypes = 5;
|
||
|
static const int KNValueTypes[TypesAndConstants::eDataTypeNumber] = { 5, 4 };
|
||
|
static const char* KPSZValueTypeNames[TypesAndConstants::eDataTypeNumber][KNMaxValueTypes] =
|
||
|
{
|
||
|
// ePartial
|
||
|
{ "Maximum amplitude (raw)", "Maximum amplitude (dB)", "RMS power amplitude (dB)",
|
||
|
"Signal to Mask Ratio (dB)", "Frequency (Hz)" },
|
||
|
|
||
|
// eResidualBand
|
||
|
{ "Maximum energy (raw)", "Maximum energy (dB)", "RMS power energy (dB)",
|
||
|
"Frequency (Hz)", 0 }
|
||
|
};
|
||
|
|
||
|
enum { eMin=0, eMax, eMinMax };
|
||
|
|
||
|
static const double KDValueRanges[TypesAndConstants::eDataTypeNumber]
|
||
|
[KNMaxValueTypes][eMinMax] =
|
||
|
{
|
||
|
// ePartial
|
||
|
{ // min max
|
||
|
{ 0.0, 100000.0 }, // Maximum amplitude (raw)
|
||
|
{ -1000.0, 1000.0 }, // Maximum amplitude (dB)
|
||
|
{ -1000.0, 1000.0 }, // RMS power amplitude (dB)
|
||
|
{ -1000.0, 1000.0 }, // Signal to Mask Ratio (dB)
|
||
|
{ 0.0, 100000.0 } // Frequency (Hz)
|
||
|
},
|
||
|
|
||
|
// eResidualBand
|
||
|
{ // min max
|
||
|
{ 0.0, 100000.0 }, // Maximum energy (raw)
|
||
|
{ -1000.0, 1000.0 }, // Maximum energy (dB)
|
||
|
{ -1000.0, 1000.0 }, // RMS power energy (dB)
|
||
|
{ 0.0, 100000.0 }, // Frequency (Hz)
|
||
|
{ 0.0, 0.0 } // Not used
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const double KDValueDefaults[TypesAndConstants::eDataTypeNumber]
|
||
|
[KNMaxValueTypes][eMinMax] =
|
||
|
{
|
||
|
// ePartial
|
||
|
{ // min max
|
||
|
{ 0.0, 1.0 }, // Maximum amplitude (raw)
|
||
|
{ -30.0, 0.0 }, // Maximum amplitude (dB)
|
||
|
{ -30.0, 0.0 }, // RMS power amplitude (dB)
|
||
|
{ -30.0, 0.0 }, // Mean Signal to Mask Ratio (dB)
|
||
|
{ 20.0, 20000.0 } // Mean frequency (Hz)
|
||
|
},
|
||
|
|
||
|
// eResidualBand
|
||
|
{ // min max
|
||
|
{ 0.0, 10.0 }, // Maximum energy (raw)
|
||
|
{ -30.0, 0.0 }, // Maximum energy (dB)
|
||
|
{ -30.0, 0.0 }, // RMS power energy (dB)
|
||
|
{ 20.0, 20000.0 }, // Minimal frequency (Hz)
|
||
|
{ 0.0, 0.0 } // Not used
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const DataSelectionWidget::EValueThresholdType
|
||
|
KEValueThresholdTypes[TypesAndConstants::eDataTypeNumber][KNMaxValueTypes] =
|
||
|
{
|
||
|
// ePartial
|
||
|
{ DataSelectionWidget::ePeakAmplitude, DataSelectionWidget::eRMSPowerAmplitude,
|
||
|
DataSelectionWidget::eSignalToMaskRatio, DataSelectionWidget::eFrequency },
|
||
|
|
||
|
// eResidualBand
|
||
|
{ DataSelectionWidget::ePeakAmplitude, DataSelectionWidget::eRMSPowerAmplitude,
|
||
|
DataSelectionWidget::eFrequency, DataSelectionWidget::eThresholdTypeNumber }
|
||
|
};
|
||
|
|
||
|
|
||
|
// Constructor / Destructor ==========================================
|
||
|
DataSelectionWidget::DataSelectionWidget(QWidget *parent)
|
||
|
: QWidget(parent), _pui(new Ui::DataSelectionWidget), _pModelMgr(0),
|
||
|
_eDataType(TypesAndConstants::ePartial), _nMaxItemIndex(0)
|
||
|
{
|
||
|
_pui->setupUi(this);
|
||
|
|
||
|
// Enable control value synchronization
|
||
|
_bSynchronizeControls = true;
|
||
|
|
||
|
// Connect controls to local changed() slots for synchronisation
|
||
|
// 1) Index sliders
|
||
|
connect(_pui->qsdFromIndex, SIGNAL(valueChanged(int)),
|
||
|
this, SLOT(onFromIndexChanged(int)));
|
||
|
connect(_pui->qsdToIndex, SIGNAL(valueChanged(int)),
|
||
|
this, SLOT(onToIndexChanged(int)));
|
||
|
|
||
|
// 2) Index spin-boxes
|
||
|
connect(_pui->qsbFromIndex, SIGNAL(valueChanged(int)),
|
||
|
this, SLOT(onFromIndexChanged(int)));
|
||
|
connect(_pui->qsbToIndex, SIGNAL(valueChanged(int)),
|
||
|
this, SLOT(onToIndexChanged(int)));
|
||
|
|
||
|
// 3) Min / max value use
|
||
|
connect(_pui->qckMinValue, SIGNAL(stateChanged(int)),
|
||
|
this, SLOT(onUseMinValueChanged(int)));
|
||
|
connect(_pui->qckMaxValue, SIGNAL(stateChanged(int)),
|
||
|
this, SLOT(onUseMaxValueChanged(int)));
|
||
|
|
||
|
// 4) Value type combo-box.
|
||
|
connect(_pui->qcbValueType, SIGNAL(currentIndexChanged(int)),
|
||
|
this, SLOT(onValueTypeChanged(int)));
|
||
|
}
|
||
|
|
||
|
DataSelectionWidget::~DataSelectionWidget()
|
||
|
{
|
||
|
delete _pui;
|
||
|
}
|
||
|
|
||
|
// Model management ==================================================
|
||
|
void DataSelectionWidget::setModelManager(ATSModelManager* pModelMgr)
|
||
|
{
|
||
|
_pModelMgr = pModelMgr;
|
||
|
}
|
||
|
|
||
|
void DataSelectionWidget::resetControls()
|
||
|
{
|
||
|
_pui->qsdFromIndex->setMaximum(_nMaxItemIndex);
|
||
|
_pui->qsdToIndex->setMaximum(_nMaxItemIndex);
|
||
|
|
||
|
// Reset maximum value for index spin-boxes
|
||
|
_pui->qsbFromIndex->setMaximum(_nMaxItemIndex);
|
||
|
_pui->qsbToIndex->setMaximum(_nMaxItemIndex);
|
||
|
|
||
|
// Reset tick interval for sliders
|
||
|
_pui->qsdFromIndex->setTickInterval(_nMaxItemIndex > 3 ? (_nMaxItemIndex + 1) / 4 : 1);
|
||
|
_pui->qsdToIndex->setTickInterval(_nMaxItemIndex > 3 ? (_nMaxItemIndex + 1) / 4 : 1);
|
||
|
|
||
|
// Reset value type combo-box.
|
||
|
_pui->qcbValueType->clear();
|
||
|
for (int nValTypInd = 0; nValTypInd < KNValueTypes[_eDataType]; nValTypInd++)
|
||
|
_pui->qcbValueType->addItem(tr(KPSZValueTypeNames[_eDataType][nValTypInd]));
|
||
|
}
|
||
|
|
||
|
void DataSelectionWidget::switchDataType(TypesAndConstants::EDataType eDataType)
|
||
|
{
|
||
|
// Save new current data type.
|
||
|
_eDataType = eDataType;
|
||
|
|
||
|
// Determine new current number of data items.
|
||
|
switch(eDataType)
|
||
|
{
|
||
|
case TypesAndConstants::ePartial:
|
||
|
disconnect(_pModelMgr->residualsModel(), SIGNAL(modelReset()),
|
||
|
this, SLOT(onModelReset()));
|
||
|
connect(_pModelMgr->partialsModel(), SIGNAL(modelReset()),
|
||
|
this, SLOT(onModelReset()));
|
||
|
_nMaxItemIndex = _pModelMgr->partialsModel()->nbPartials() - 1;
|
||
|
break;
|
||
|
case TypesAndConstants::eResidualBand:
|
||
|
disconnect(_pModelMgr->partialsModel(), SIGNAL(modelReset()),
|
||
|
this, SLOT(onModelReset()));
|
||
|
connect(_pModelMgr->residualsModel(), SIGNAL(modelReset()),
|
||
|
this, SLOT(onModelReset()));
|
||
|
_nMaxItemIndex = _pModelMgr->residualsModel()->nbResiduals() - 1;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Reset maximum value for sliders
|
||
|
resetControls();
|
||
|
}
|
||
|
|
||
|
// State management ==================================================
|
||
|
DataSelectionWidget::SState DataSelectionWidget::getState() const
|
||
|
{
|
||
|
// Get state from controls
|
||
|
SState state;
|
||
|
|
||
|
state.nFromIndex = _pui->qsbFromIndex->value();
|
||
|
state.nToIndex = _pui->qsbToIndex->value();
|
||
|
state.nIndexStep = _pui->qsbIndexStep->value();
|
||
|
|
||
|
state.nValueTypeIndex = _pui->qcbValueType->currentIndex();
|
||
|
state.bUseMinValue = _pui->qckMinValue->isChecked();
|
||
|
state.dMinValue = _pui->qsbMinValue->value();
|
||
|
state.bUseMaxValue = _pui->qckMaxValue->isChecked();
|
||
|
state.dMaxValue = _pui->qsbMaxValue->value();
|
||
|
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
void DataSelectionWidget::setState(const SState& state)
|
||
|
{
|
||
|
// Check/fix/initialize the selector state as needed.
|
||
|
SState fixedState = state;
|
||
|
if (fixedState.nToIndex < 0 || fixedState.nToIndex > _nMaxItemIndex)
|
||
|
fixedState.nToIndex = _nMaxItemIndex;
|
||
|
if (fixedState.nFromIndex > fixedState.nToIndex)
|
||
|
fixedState.nFromIndex = fixedState.nToIndex;
|
||
|
|
||
|
// Set state to controls (auto-synchonization will do its job for the sliders).
|
||
|
_pui->qsbFromIndex->setValue(fixedState.nFromIndex);
|
||
|
_pui->qsbToIndex->setValue(fixedState.nToIndex);
|
||
|
_pui->qsbIndexStep->setValue(fixedState.nIndexStep);
|
||
|
|
||
|
_pui->qcbValueType->setCurrentIndex(fixedState.nValueTypeIndex);
|
||
|
_pui->qckMinValue->setChecked(fixedState.bUseMinValue);
|
||
|
_pui->qsbMinValue->setValue(fixedState.dMinValue);
|
||
|
_pui->qckMaxValue->setChecked(fixedState.bUseMaxValue);
|
||
|
_pui->qsbMaxValue->setValue(fixedState.dMaxValue);
|
||
|
}
|
||
|
|
||
|
// Slots to synchronize with model ====================================
|
||
|
void DataSelectionWidget::onModelReset()
|
||
|
{
|
||
|
// Simply re-initialize controls for the current data type.
|
||
|
resetControls();
|
||
|
}
|
||
|
|
||
|
// Slots to synchronize control values/state===========================
|
||
|
void DataSelectionWidget::onFromIndexChanged(int nNewIndex)
|
||
|
{
|
||
|
// Nothing to do if control synchronization is blocked.
|
||
|
if (!_bSynchronizeControls)
|
||
|
return;
|
||
|
|
||
|
// Synchronize attached controls.
|
||
|
_bSynchronizeControls = false;
|
||
|
_pui->qsbFromIndex->setValue(nNewIndex);
|
||
|
_pui->qsdFromIndex->setValue(nNewIndex);
|
||
|
_bSynchronizeControls = true;
|
||
|
|
||
|
// From can't be greater than To
|
||
|
if (nNewIndex > _pui->qsbToIndex->value())
|
||
|
_pui->qsbToIndex->setValue(nNewIndex);
|
||
|
|
||
|
// Warn everyone of the selection change.
|
||
|
emit dataIndexSelectionChanged(_eDataType, nNewIndex, _pui->qsbToIndex->value());
|
||
|
}
|
||
|
|
||
|
void DataSelectionWidget::onToIndexChanged(int nNewIndex)
|
||
|
{
|
||
|
// Nothing to do if control synchronization is blocked.
|
||
|
if (!_bSynchronizeControls)
|
||
|
return;
|
||
|
|
||
|
// Synchronize attached controls.
|
||
|
_bSynchronizeControls = false;
|
||
|
_pui->qsbToIndex->setValue(nNewIndex);
|
||
|
_pui->qsdToIndex->setValue(nNewIndex);
|
||
|
_bSynchronizeControls = true;
|
||
|
|
||
|
// To can't be lower than From
|
||
|
if (nNewIndex < _pui->qsbFromIndex->value())
|
||
|
_pui->qsbFromIndex->setValue(nNewIndex);
|
||
|
|
||
|
// Warn everyone of the selection change.
|
||
|
emit dataIndexSelectionChanged(_eDataType, _pui->qsbFromIndex->value(), nNewIndex);
|
||
|
}
|
||
|
|
||
|
void DataSelectionWidget::onUseMinValueChanged(int nNewState)
|
||
|
{
|
||
|
// Enable or disable min value spin-box
|
||
|
_pui->qsbMinValue->setEnabled(nNewState != Qt::Unchecked);
|
||
|
|
||
|
// Warn everyone of the selection change.
|
||
|
emit dataValueSelectionChanged
|
||
|
(_eDataType, KEValueThresholdTypes[_eDataType][_pui->qcbValueType->currentIndex()],
|
||
|
_pui->qckMinValue->isChecked(), _pui->qsbMinValue->value(),
|
||
|
_pui->qckMaxValue->isChecked(), _pui->qsbMaxValue->value());
|
||
|
}
|
||
|
|
||
|
void DataSelectionWidget::onUseMaxValueChanged(int nNewState)
|
||
|
{
|
||
|
// Enable or disable min value spin-box
|
||
|
_pui->qsbMaxValue->setEnabled(nNewState != Qt::Unchecked);
|
||
|
|
||
|
// Warn everyone of the selection change.
|
||
|
emit dataValueSelectionChanged
|
||
|
(_eDataType, KEValueThresholdTypes[_eDataType][_pui->qcbValueType->currentIndex()],
|
||
|
_pui->qckMinValue->isChecked(), _pui->qsbMinValue->value(),
|
||
|
_pui->qckMaxValue->isChecked(), _pui->qsbMaxValue->value());
|
||
|
}
|
||
|
|
||
|
void DataSelectionWidget::onValueTypeChanged(int nNewIndex)
|
||
|
{
|
||
|
// Reset min/max and default value for min and max values.
|
||
|
_pui->qsbMinValue->setMinimum(KDValueRanges[_eDataType][nNewIndex][eMin]);
|
||
|
_pui->qsbMinValue->setMaximum(KDValueRanges[_eDataType][nNewIndex][eMax]);
|
||
|
_pui->qsbMinValue->setValue(KDValueDefaults[_eDataType][nNewIndex][eMin]);
|
||
|
|
||
|
_pui->qsbMaxValue->setMinimum(KDValueRanges[_eDataType][nNewIndex][eMin]);
|
||
|
_pui->qsbMaxValue->setMaximum(KDValueRanges[_eDataType][nNewIndex][eMax]);
|
||
|
_pui->qsbMaxValue->setValue(KDValueDefaults[_eDataType][nNewIndex][eMax]);
|
||
|
}
|
||
|
|
||
|
// Event management ==================================================
|
||
|
void DataSelectionWidget::changeEvent(QEvent *e)
|
||
|
{
|
||
|
switch (e->type()) {
|
||
|
case QEvent::LanguageChange:
|
||
|
_pui->retranslateUi(this);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|