Adding HP equailization for binaural session, and improving circluating source example

parent c944869f
...@@ -43,6 +43,7 @@ RedstartRunCirculatingSourceDialog::RedstartRunCirculatingSourceDialog( QWidget ...@@ -43,6 +43,7 @@ RedstartRunCirculatingSourceDialog::RedstartRunCirculatingSourceDialog( QWidget
m_dElevationDEG = 0.0f; m_dElevationDEG = 0.0f;
m_qVAUpdateTimer = new QTimer( this ); m_qVAUpdateTimer = new QTimer( this );
m_qVAUpdateTimer->setTimerType( Qt::TimerType::PreciseTimer );
connect( m_qVAUpdateTimer, SIGNAL( timeout() ), this, SLOT( UpdateScene() ) ); connect( m_qVAUpdateTimer, SIGNAL( timeout() ), this, SLOT( UpdateScene() ) );
} }
...@@ -148,20 +149,35 @@ void RedstartRunCirculatingSourceDialog::UpdateScene() ...@@ -148,20 +149,35 @@ void RedstartRunCirculatingSourceDialog::UpdateScene()
v3Pos.x = -std::sin( grad2rad( m_dAzimuthDEG ) ) * ui->doubleSpinBox_radius->value(); v3Pos.x = -std::sin( grad2rad( m_dAzimuthDEG ) ) * ui->doubleSpinBox_radius->value();
v3Pos.y = std::sin( grad2rad( m_dElevationDEG ) ) * ui->doubleSpinBox_radius->value(); v3Pos.y = std::sin( grad2rad( m_dElevationDEG ) ) * ui->doubleSpinBox_radius->value();
v3Pos.z = -std::cos( grad2rad( m_dAzimuthDEG ) ) * ui->doubleSpinBox_radius->value(); v3Pos.z = -std::cos( grad2rad( m_dAzimuthDEG ) ) * ui->doubleSpinBox_radius->value();
VAVec3 v3NewPos;
try try
{ {
m_pVAInterface->SetSoundSourcePosition( m_iSourceID, v3Pos ); m_pVAInterface->SetSoundSourcePosition( m_iSourceID, v3Pos );
v3NewPos = m_pVAInterface->GetSoundSourcePosition( m_iSourceID );
} }
catch( CVAException& e ) catch( CVAException& e )
{ {
Stop(); Stop();
} }
ui->doubleSpinBox_azimuth->setValue( m_dAzimuthDEG );
ui->doubleSpinBox_elevation->setValue( m_dElevationDEG );
ui->doubleSpinBox_source_pos_x->setValue( v3NewPos.x );
ui->doubleSpinBox_source_pos_y->setValue( v3NewPos.y );
ui->doubleSpinBox_source_pos_z->setValue( v3NewPos.z );
ui->doubleSpinBox_runtime_tracker->setValue( m_dRuntimeSeconds );
m_dAzimuthDEG += ui->doubleSpinBox_azi_inc->value(); m_dAzimuthDEG += ui->doubleSpinBox_azi_inc->value();
m_dAzimuthDEG = anglef_proj_0_360_DEG( m_dAzimuthDEG );
m_dElevationDEG += ui->doubleSpinBox_ele_inc->value(); m_dElevationDEG += ui->doubleSpinBox_ele_inc->value();
m_dRuntime += ui->doubleSpinBox_timeout->value(); m_dElevationDEG = anglef_proj_N90_90_DEG( m_dElevationDEG );
m_dRuntimeSeconds += ui->doubleSpinBox_timeout->value();
if( m_dRuntime > ui->doubleSpinBox_runtime->value() ) if( m_dRuntimeSeconds > ui->doubleSpinBox_runtime->value() )
Stop(); Stop();
} }
...@@ -171,13 +187,13 @@ void RedstartRunCirculatingSourceDialog::StartUpdateTimer() ...@@ -171,13 +187,13 @@ void RedstartRunCirculatingSourceDialog::StartUpdateTimer()
const int iIntervalMS = ceil( dTimeout * 1000.0f ); const int iIntervalMS = ceil( dTimeout * 1000.0f );
m_qVAUpdateTimer->setInterval( iIntervalMS ); m_qVAUpdateTimer->setInterval( iIntervalMS );
m_qVAUpdateTimer->start(); m_qVAUpdateTimer->start();
m_dRuntime = 0.0f; m_dRuntimeSeconds = 0.0f;
} }
void RedstartRunCirculatingSourceDialog::StopUpdateTimer() void RedstartRunCirculatingSourceDialog::StopUpdateTimer()
{ {
m_qVAUpdateTimer->stop(); m_qVAUpdateTimer->stop();
m_dRuntime = 0.0f; m_dRuntimeSeconds = 0.0f;
m_dAzimuthDEG = 0.0f; m_dAzimuthDEG = 0.0f;
m_dElevationDEG = 0.0f; m_dElevationDEG = 0.0f;
......
...@@ -62,7 +62,7 @@ private: ...@@ -62,7 +62,7 @@ private:
QString m_sSignalID; QString m_sSignalID;
double m_dAzimuthDEG, m_dElevationDEG; double m_dAzimuthDEG, m_dElevationDEG;
double m_dRuntime; double m_dRuntimeSeconds;
void StartUpdateTimer(); void StartUpdateTimer();
void StopUpdateTimer(); void StopUpdateTimer();
......
...@@ -26,13 +26,16 @@ RedstartSessionBinauralHeadphonesDialog::RedstartSessionBinauralHeadphonesDialog ...@@ -26,13 +26,16 @@ RedstartSessionBinauralHeadphonesDialog::RedstartSessionBinauralHeadphonesDialog
ui->setupUi( this ); ui->setupUi( this );
QDialog::setWindowTitle( "Binaural headphones session" ); QDialog::setWindowTitle( "Binaural headphones session" );
QSettings qSettings; QSettings qSettings;
QString sLastBrowseFolder = qSettings.value( "Redstart/last_browse_folder" ).toString(); QString sLastBrowseFolder = qSettings.value( "Redstart/last_browse_folder" ).toString();
std::string s = sLastBrowseFolder.toStdString(); std::string s = sLastBrowseFolder.toStdString();
if( QDir( sLastBrowseFolder ).exists() ) if( QDir( sLastBrowseFolder ).exists() )
m_oLastBasePath.setCurrent( sLastBrowseFolder ); m_oLastBasePath.setCurrent( sLastBrowseFolder );
if( ui->checkBox_hpir_auto_filter_length->isChecked() )
ui->spinBox_inverse_hpir_filter_length->setEnabled( false );
} }
RedstartSessionBinauralHeadphonesDialog::~RedstartSessionBinauralHeadphonesDialog() RedstartSessionBinauralHeadphonesDialog::~RedstartSessionBinauralHeadphonesDialog()
...@@ -51,11 +54,13 @@ QVariantHash RedstartSessionBinauralHeadphonesDialog::GetCoreConfig() const ...@@ -51,11 +54,13 @@ QVariantHash RedstartSessionBinauralHeadphonesDialog::GetCoreConfig() const
oPaths[ "DemoSoundBasePath" ] = m_oDemoSoundBasePath.absolutePath(); oPaths[ "DemoSoundBasePath" ] = m_oDemoSoundBasePath.absolutePath();
if( m_oHRIRBasePath.exists() && m_oHRIRBasePath != m_oDemoSoundBasePath ) if( m_oHRIRBasePath.exists() && m_oHRIRBasePath != m_oDemoSoundBasePath )
oPaths[ "DefaultHRIRBasePath" ] = m_oHRIRBasePath.absolutePath(); oPaths[ "DefaultHRIRBasePath" ] = m_oHRIRBasePath.absolutePath();
if( m_oInverseHPIRBasePath.exists() && m_oInverseHPIRBasePath != m_oHRIRBasePath )
oPaths[ "HPIRBaseFolder" ] = m_oInverseHPIRBasePath.absolutePath();
oFinalCoreConfig[ "Paths" ] = oPaths; oFinalCoreConfig[ "Paths" ] = oPaths;
QString sHRIRMacro = ui->lineEdit_macro_DefaultHRIR->text(); QString sHRIRMacro = ui->lineEdit_macro_DefaultHRIR->text();
if( ui->checkBox_folders_as_search_path->isChecked() ) if( ui->checkBox_folders_as_search_path->isChecked() )
{ {
QFileInfo oHRIR( sHRIRMacro ); QFileInfo oHRIR( sHRIRMacro );
...@@ -75,8 +80,6 @@ QVariantHash RedstartSessionBinauralHeadphonesDialog::GetCoreConfig() const ...@@ -75,8 +80,6 @@ QVariantHash RedstartSessionBinauralHeadphonesDialog::GetCoreConfig() const
oFinalCoreConfig[ "Macros" ] = oMacros; oFinalCoreConfig[ "Macros" ] = oMacros;
// @todo switch between talkthrough and headphone reproduction with equalization
QVariantHash oDevice; QVariantHash oDevice;
oDevice[ "Type" ] = "HP"; oDevice[ "Type" ] = "HP";
...@@ -90,17 +93,50 @@ QVariantHash RedstartSessionBinauralHeadphonesDialog::GetCoreConfig() const ...@@ -90,17 +93,50 @@ QVariantHash RedstartSessionBinauralHeadphonesDialog::GetCoreConfig() const
oFinalCoreConfig[ "Output:MyDesktopHP" ] = oOutput; oFinalCoreConfig[ "Output:MyDesktopHP" ] = oOutput;
QVariantHash oReproduction; if( ui->groupBox_headphone_equalization->isChecked() )
oReproduction[ "Class" ] = "Talkthrough"; {
oReproduction[ "Outputs" ] = "MyDesktopHP"; QVariantHash oReproduction;
oReproduction[ "Class" ] = "Headphones";
oReproduction[ "Outputs" ] = "MyDesktopHP";
if( ui->checkBox_inverse_hpir_calibration_gain_db->isChecked() )
oReproduction[ "HpIRInvCalibrationGainDecibel" ] = ui->doubleSpinBox_InvHPIRCalibrationGain->value();
else
oReproduction[ "HpIRInvCalibrationGain" ] = ui->doubleSpinBox_InvHPIRCalibrationGain->value(); // no decibel
QString sHPIRFile = ui->lineEdit_inverse_hpir_file->text();
if( ui->checkBox_folders_as_search_path->isChecked() )
{
QFileInfo oHRIR( sHPIRFile );
sHPIRFile = oHRIR.fileName();
}
oReproduction[ "HpIRInvFile" ] = sHPIRFile;
if( !ui->checkBox_hpir_auto_filter_length->isChecked() )
oReproduction[ "HpIRInvFilterLength" ] = ui->spinBox_inverse_hpir_filter_length->value();
oFinalCoreConfig[ "Reproduction:MyEqualizedHeadphones" ] = oReproduction;
QVariantHash oRenderer;
oRenderer[ "Class" ] = "BinauralFreeField";
oRenderer[ "Reproductions" ] = "MyEqualizedHeadphones";
oFinalCoreConfig[ "Renderer:MyBinauralRenderer" ] = oRenderer;
}
else
{
QVariantHash oReproduction;
oReproduction[ "Class" ] = "Talkthrough";
oReproduction[ "Outputs" ] = "MyDesktopHP";
oFinalCoreConfig[ "Reproduction:MyTalkthroughHeadphones" ] = oReproduction; oFinalCoreConfig[ "Reproduction:MyTalkthroughHeadphones" ] = oReproduction;
QVariantHash oRenderer; QVariantHash oRenderer;
oRenderer[ "Class" ] = "BinauralFreeField"; oRenderer[ "Class" ] = "BinauralFreeField";
oRenderer[ "Reproductions" ] = "MyTalkthroughHeadphones"; oRenderer[ "Reproductions" ] = "MyTalkthroughHeadphones";
oFinalCoreConfig[ "Renderer:MyBinauralRenderer" ] = oRenderer; oFinalCoreConfig[ "Renderer:MyBinauralRenderer" ] = oRenderer;
}
return oFinalCoreConfig; return oFinalCoreConfig;
} }
...@@ -173,3 +209,36 @@ void RedstartSessionBinauralHeadphonesDialog::on_pushButton_BrowseHRIR_clicked() ...@@ -173,3 +209,36 @@ void RedstartSessionBinauralHeadphonesDialog::on_pushButton_BrowseHRIR_clicked()
} }
} }
} }
void RedstartSessionBinauralHeadphonesDialog::on_pushButton_inverse_hpir_file_select_clicked()
{
QFileDialog fd;
fd.setNameFilter( "WAV files (*.wav)" );
fd.setViewMode( QFileDialog::Detail );
if( m_oLastBasePath.exists() )
fd.setDirectory( m_oLastBasePath );
else
fd.setDirectory( QDir( QApplication::applicationDirPath() ) );
if( fd.exec() )
{
QStringList lFiles = fd.selectedFiles();
if( lFiles.empty() == false )
{
QString sFilePath = lFiles[ 0 ];
QFile oFile( sFilePath );
if( oFile.exists() )
{
m_oHRIRBasePath = fd.directory();
m_oLastBasePath = m_oHRIRBasePath;
}
ui->lineEdit_inverse_hpir_file->setText( oFile.fileName() );
}
}
}
void RedstartSessionBinauralHeadphonesDialog::on_checkBox_hpir_auto_filter_length_clicked( bool bEnabled )
{
ui->spinBox_inverse_hpir_filter_length->setEnabled( !bEnabled );
}
...@@ -38,13 +38,15 @@ private slots: ...@@ -38,13 +38,15 @@ private slots:
void on_pushButton_CreateSession_clicked(); void on_pushButton_CreateSession_clicked();
void on_pushButton_BrowseDemoSound_clicked(); void on_pushButton_BrowseDemoSound_clicked();
void on_pushButton_BrowseHRIR_clicked(); void on_pushButton_BrowseHRIR_clicked();
void on_pushButton_inverse_hpir_file_select_clicked();
void on_checkBox_hpir_auto_filter_length_clicked( bool );
private: private:
Ui::RedstartDialogSessionBinauralHeadphones* ui; Ui::RedstartDialogSessionBinauralHeadphones* ui;
QDir m_oLastBasePath; QDir m_oLastBasePath;
QDir m_oHRIRBasePath; QDir m_oHRIRBasePath;
QDir m_oInverseHPIRBasePath;
QDir m_oDemoSoundBasePath; QDir m_oDemoSoundBasePath;
QString m_sFileBaseName;
QSettings m_qSettings; QSettings m_qSettings;
}; };
......
...@@ -719,7 +719,7 @@ void RedstartWindow::on_pushButton_start_stop_clicked() ...@@ -719,7 +719,7 @@ void RedstartWindow::on_pushButton_start_stop_clicked()
m_pVAInterface = NULL; m_pVAInterface = NULL;
} }
ui->statusBar->showMessage( QString::fromStdString( ex.ToString() ) ); ui->statusBar->showMessage( QString::fromStdString( ex.ToString() ) + ". Will deactivate auto-start checkbox." );
ui->checkBox_redstart_auto_start->setChecked( false ); ui->checkBox_redstart_auto_start->setChecked( false );
} }
} }
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>545</width> <width>579</width>
<height>325</height> <height>312</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
...@@ -16,14 +16,7 @@ ...@@ -16,14 +16,7 @@
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="3"> <item row="1" column="1" colspan="3">
<widget class="QPushButton" name="pushButton_BrowseHRIR">
<property name="text">
<string>Select</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QLineEdit" name="lineEdit_macro_DefaultHRIR"> <widget class="QLineEdit" name="lineEdit_macro_DefaultHRIR">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
...@@ -36,92 +29,101 @@ ...@@ -36,92 +29,101 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0"> <item row="0" column="1" colspan="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Demo sound</string>
</property>
<property name="buddy">
<cstring>lineEdit_macro_DemoSound</cstring>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="pushButton_BrowseDemoSound">
<property name="text">
<string>Select</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="lineEdit_macro_DemoSound"> <widget class="QLineEdit" name="lineEdit_macro_DemoSound">
<property name="text"> <property name="text">
<string>$(DemoSound)</string> <string>$(DemoSound)</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="3" column="4">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label_13">
<property name="text"> <property name="text">
<string>Default HRIR</string> <string>Current azimuth</string>
</property>
<property name="buddy">
<cstring>lineEdit_macro_DefaultHRIR</cstring>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1" colspan="2"> <item row="5" column="4">
<widget class="QCheckBox" name="checkBox_folders_as_search_path"> <widget class="QLabel" name="label_15">
<property name="text"> <property name="text">
<string>Add all folders as search paths (instead of using absolute paths)</string> <string>Source position</string>
</property>
<property name="checked">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="2"> <item row="5" column="3">
<widget class="QLabel" name="label_8"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="text"> <item>
<string>seconds</string> <widget class="QDoubleSpinBox" name="doubleSpinBox_source_pos_x">
</property> <property name="enabled">
</widget> <bool>false</bool>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999.000000000000000</double>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox_source_pos_y">
<property name="enabled">
<bool>false</bool>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999.000000000000000</double>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox_source_pos_z">
<property name="enabled">
<bool>false</bool>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>-999.000000000000000</double>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item> </item>
<item row="6" column="0"> <item row="4" column="4">
<widget class="QLabel" name="label_7"> <widget class="QLabel" name="label_14">
<property name="text"> <property name="text">
<string>Runtime</string> <string>Current elevation</string>
</property>
<property name="buddy">
<cstring>doubleSpinBox_runtime</cstring>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_runtime">
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>99999999.000000000000000</double>
</property>
<property name="value">
<double>20.000000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0" colspan="2"> <item row="7" column="2">
<widget class="QPushButton" name="pushButton_stop"> <widget class="QLabel" name="label_10">
<property name="enabled"> <property name="toolTip">
<bool>false</bool> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The runtime depends on the timer quality, CPU load and processing duration of the timout slot function. It may be deviating significantly from the actual time. For proper timing in VA, it is recommended to use high precision timer (ideally synchronized to the audio clock). In VAMatlab, an implementation of high performance timer is available.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Stop</string> <string>seconds</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="0"> <item row="7" column="0">
<widget class="QLabel" name="label_9"> <widget class="QLabel" name="label_9">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The runtime depends on the timer quality, CPU load and processing duration of the timout slot function. It may be deviating significantly from the actual time. For proper timing in VA, it is recommended to use high precision timer (ideally synchronized to the audio clock). In VAMatlab, an implementation of high performance timer is available.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Update timeout</string> <string>Update timeout</string>
</property> </property>
...@@ -132,6 +134,9 @@ ...@@ -132,6 +134,9 @@
</item> </item>
<item row="7" column="1"> <item row="7" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_timeout"> <widget class="QDoubleSpinBox" name="doubleSpinBox_timeout">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The runtime depends on the timer quality, CPU load and processing duration of the timout slot function. It may be deviating significantly from the actual time. For proper timing in VA, it is recommended to use high precision timer (ideally synchronized to the audio clock). In VAMatlab, an implementation of high performance timer is available.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="decimals"> <property name="decimals">
<number>3</number> <number>3</number>
</property> </property>
...@@ -149,20 +154,6 @@ ...@@ -149,20 +154,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="2">
<widget class="QLabel" name="label_10">
<property name="text">
<string>seconds</string>
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<widget class="QPushButton" name="pushButton_start">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
...@@ -173,18 +164,8 @@ ...@@ -173,18 +164,8 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="4" column="1">
<widget class="QLabel" name="label_4"> <widget class="QDoubleSpinBox" name="doubleSpinBox_ele_inc">
<property name="text">
<string>Elevation increment</string>
</property>
<property name="buddy">
<cstring>doubleSpinBox_ele_inc</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox_azi_inc">
<property name="decimals"> <property name="decimals">
<number>3</number> <number>3</number>
</property> </property>
...@@ -194,16 +175,17 @@ ...@@ -194,16 +175,17 @@
<property name="maximum"> <property name="maximum">
<double>999999.000000000000000</double> <double>999999.000000000000000</double>
</property> </property>
<property name="singleStep"> </widget>
<double>1.000000000000000</double> </item>
</property> <item row="4" column="2">
<property name="value">