diff options
author | Chris Robinson <[email protected]> | 2023-12-13 22:18:09 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2023-12-13 22:18:09 -0800 |
commit | 760ada93e88d3c78f6613b52eb5ef15c1564ad80 (patch) | |
tree | e3aebec8d8a4c509163d4a155c525c8c0248ef01 | |
parent | 70b3776032adf05a92fda89ac5f56eb705d06748 (diff) |
Fix clang-tidy warnings from the examples and utilities
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | examples/alconvolve.c | 20 | ||||
-rw-r--r-- | examples/alstream.c | 18 | ||||
-rw-r--r-- | examples/alstreamcb.cpp | 4 | ||||
-rw-r--r-- | utils/alsoft-config/CMakeLists.txt | 2 | ||||
-rw-r--r-- | utils/alsoft-config/mainwindow.cpp | 296 | ||||
-rw-r--r-- | utils/alsoft-config/mainwindow.h | 20 | ||||
-rw-r--r-- | utils/makemhr/loaddef.cpp | 153 | ||||
-rw-r--r-- | utils/makemhr/loadsofa.cpp | 2 | ||||
-rw-r--r-- | utils/makemhr/makemhr.cpp | 168 | ||||
-rw-r--r-- | utils/makemhr/makemhr.h | 32 | ||||
-rw-r--r-- | utils/openal-info.c | 14 |
12 files changed, 360 insertions, 372 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ce287ba0..59c0711e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1339,7 +1339,8 @@ configure_file( add_library(alcommon STATIC EXCLUDE_FROM_ALL ${COMMON_OBJS}) -target_include_directories(alcommon PRIVATE ${OpenAL_BINARY_DIR} ${OpenAL_SOURCE_DIR}/include) +target_include_directories(alcommon PRIVATE ${OpenAL_BINARY_DIR} ${OpenAL_SOURCE_DIR}/include + PUBLIC ${OpenAL_SOURCE_DIR}/common) target_compile_definitions(alcommon PRIVATE ${CPP_DEFS}) target_compile_options(alcommon PRIVATE ${C_FLAGS}) set_target_properties(alcommon PROPERTIES ${DEFAULT_TARGET_PROPS} POSITION_INDEPENDENT_CODE TRUE) diff --git a/examples/alconvolve.c b/examples/alconvolve.c index 8198409c..d194d270 100644 --- a/examples/alconvolve.c +++ b/examples/alconvolve.c @@ -90,11 +90,11 @@ static LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv; /* This stuff defines a simple streaming player object, the same as alstream.c. * Comments are removed for brevity, see alstream.c for more details. */ -#define NUM_BUFFERS 4 -#define BUFFER_SAMPLES 8192 +enum { NumBuffers = 4 }; +enum { BufferSamples = 8192 }; typedef struct StreamPlayer { - ALuint buffers[NUM_BUFFERS]; + ALuint buffers[NumBuffers]; ALuint source; SNDFILE *sndfile; @@ -111,7 +111,7 @@ static StreamPlayer *NewPlayer(void) player = calloc(1, sizeof(*player)); assert(player != NULL); - alGenBuffers(NUM_BUFFERS, player->buffers); + alGenBuffers(NumBuffers, player->buffers); assert(alGetError() == AL_NO_ERROR && "Could not create buffers"); alGenSources(1, &player->source); @@ -140,11 +140,11 @@ static void DeletePlayer(StreamPlayer *player) ClosePlayerFile(player); alDeleteSources(1, &player->source); - alDeleteBuffers(NUM_BUFFERS, player->buffers); + alDeleteBuffers(NumBuffers, player->buffers); if(alGetError() != AL_NO_ERROR) fprintf(stderr, "Failed to delete object IDs\n"); - memset(player, 0, sizeof(*player)); + memset(player, 0, sizeof(*player)); /* NOLINT(clang-analyzer-security.insecureAPI.*) */ free(player); } @@ -186,7 +186,7 @@ static int OpenPlayerFile(StreamPlayer *player, const char *filename) return 0; } - frame_size = (size_t)(BUFFER_SAMPLES * player->sfinfo.channels) * sizeof(float); + frame_size = (size_t)(BufferSamples * player->sfinfo.channels) * sizeof(float); player->membuf = malloc(frame_size); return 1; @@ -199,9 +199,9 @@ static int StartPlayer(StreamPlayer *player) alSourceRewind(player->source); alSourcei(player->source, AL_BUFFER, 0); - for(i = 0;i < NUM_BUFFERS;i++) + for(i = 0;i < NumBuffers;i++) { - sf_count_t slen = sf_readf_float(player->sndfile, player->membuf, BUFFER_SAMPLES); + sf_count_t slen = sf_readf_float(player->sndfile, player->membuf, BufferSamples); if(slen < 1) break; slen *= player->sfinfo.channels * (sf_count_t)sizeof(float); @@ -245,7 +245,7 @@ static int UpdatePlayer(StreamPlayer *player) alSourceUnqueueBuffers(player->source, 1, &bufid); processed--; - slen = sf_readf_float(player->sndfile, player->membuf, BUFFER_SAMPLES); + slen = sf_readf_float(player->sndfile, player->membuf, BufferSamples); if(slen > 0) { slen *= player->sfinfo.channels * (sf_count_t)sizeof(float); diff --git a/examples/alstream.c b/examples/alstream.c index 7e62c50d..5cbbc2a7 100644 --- a/examples/alstream.c +++ b/examples/alstream.c @@ -44,8 +44,8 @@ * buffers at 200ms each gives a nice per-chunk size, and lets the queue last * for almost one second. */ -#define NUM_BUFFERS 4 -#define BUFFER_MILLISEC 200 +enum { NumBuffers = 4 }; +enum { BufferMillisec = 200 }; typedef enum SampleType { Int16, Float, IMA4, MSADPCM @@ -53,7 +53,7 @@ typedef enum SampleType { typedef struct StreamPlayer { /* These are the buffers and source to play out through OpenAL with. */ - ALuint buffers[NUM_BUFFERS]; + ALuint buffers[NumBuffers]; ALuint source; /* Handle for the audio file */ @@ -90,7 +90,7 @@ static StreamPlayer *NewPlayer(void) assert(player != NULL); /* Generate the buffers and source */ - alGenBuffers(NUM_BUFFERS, player->buffers); + alGenBuffers(NumBuffers, player->buffers); assert(alGetError() == AL_NO_ERROR && "Could not create buffers"); alGenSources(1, &player->source); @@ -113,11 +113,11 @@ static void DeletePlayer(StreamPlayer *player) ClosePlayerFile(player); alDeleteSources(1, &player->source); - alDeleteBuffers(NUM_BUFFERS, player->buffers); + alDeleteBuffers(NumBuffers, player->buffers); if(alGetError() != AL_NO_ERROR) fprintf(stderr, "Failed to delete object IDs\n"); - memset(player, 0, sizeof(*player)); + memset(player, 0, sizeof(*player)); /* NOLINT(clang-analyzer-security.insecureAPI.*) */ free(player); } @@ -293,7 +293,7 @@ static int OpenPlayerFile(StreamPlayer *player, const char *filename) } player->block_count = player->sfinfo.samplerate / player->sampleblockalign; - player->block_count = player->block_count * BUFFER_MILLISEC / 1000; + player->block_count = player->block_count * BufferMillisec / 1000; player->membuf = malloc((size_t)(player->block_count * player->byteblockalign)); return 1; @@ -312,7 +312,7 @@ static void ClosePlayerFile(StreamPlayer *player) if(player->sampleblockalign > 1) { ALsizei i; - for(i = 0;i < NUM_BUFFERS;i++) + for(i = 0;i < NumBuffers;i++) alBufferi(player->buffers[i], AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0); player->sampleblockalign = 0; player->byteblockalign = 0; @@ -330,7 +330,7 @@ static int StartPlayer(StreamPlayer *player) alSourcei(player->source, AL_BUFFER, 0); /* Fill the buffer queue */ - for(i = 0;i < NUM_BUFFERS;i++) + for(i = 0;i < NumBuffers;i++) { sf_count_t slen; diff --git a/examples/alstreamcb.cpp b/examples/alstreamcb.cpp index 0b0aeeb7..95f89bbe 100644 --- a/examples/alstreamcb.cpp +++ b/examples/alstreamcb.cpp @@ -167,8 +167,8 @@ struct StreamPlayer { mSampleFormat = SampleType::Int16; else { - auto fmtbuf = std::make_unique<ALubyte[]>(inf.datalen); - inf.data = fmtbuf.get(); + auto fmtbuf = std::vector<ALubyte>(inf.datalen); + inf.data = fmtbuf.data(); if(sf_get_chunk_data(iter, &inf) != SF_ERR_NO_ERROR) mSampleFormat = SampleType::Int16; else diff --git a/utils/alsoft-config/CMakeLists.txt b/utils/alsoft-config/CMakeLists.txt index c6a46075..d9e6ca9a 100644 --- a/utils/alsoft-config/CMakeLists.txt +++ b/utils/alsoft-config/CMakeLists.txt @@ -12,7 +12,7 @@ if(Qt5Widgets_FOUND) verstr.cpp verstr.h ${UIS} ${RSCS} ${TRS} ${MOCS}) - target_link_libraries(alsoft-config Qt5::Widgets) + target_link_libraries(alsoft-config PUBLIC Qt5::Widgets PRIVATE alcommon) target_include_directories(alsoft-config PRIVATE "${alsoft-config_BINARY_DIR}" "${OpenAL_BINARY_DIR}") set_target_properties(alsoft-config PROPERTIES ${DEFAULT_TARGET_PROPS} diff --git a/utils/alsoft-config/mainwindow.cpp b/utils/alsoft-config/mainwindow.cpp index 207c98c4..bf037203 100644 --- a/utils/alsoft-config/mainwindow.cpp +++ b/utils/alsoft-config/mainwindow.cpp @@ -3,8 +3,9 @@ #include "mainwindow.h" -#include <iostream> +#include <array> #include <cmath> +#include <iostream> #include <QFileDialog> #include <QMessageBox> @@ -19,137 +20,133 @@ #include <shlobj.h> #endif +#include "alspan.h" + namespace { -const struct { +struct BackendNamePair { + /* NOLINTBEGIN(*-avoid-c-arrays) */ char backend_name[16]; char full_string[32]; -} backendList[] = { -#ifdef HAVE_JACK - { "jack", "JACK" }, -#endif + /* NOLINTEND(*-avoid-c-arrays) */ +}; +constexpr std::array backendList{ #ifdef HAVE_PIPEWIRE - { "pipewire", "PipeWire" }, + BackendNamePair{ "pipewire", "PipeWire" }, #endif #ifdef HAVE_PULSEAUDIO - { "pulse", "PulseAudio" }, + BackendNamePair{ "pulse", "PulseAudio" }, #endif #ifdef HAVE_ALSA - { "alsa", "ALSA" }, + BackendNamePair{ "alsa", "ALSA" }, +#endif +#ifdef HAVE_JACK + BackendNamePair{ "jack", "JACK" }, #endif #ifdef HAVE_COREAUDIO - { "core", "CoreAudio" }, + BackendNamePair{ "core", "CoreAudio" }, #endif #ifdef HAVE_OSS - { "oss", "OSS" }, + BackendNamePair{ "oss", "OSS" }, #endif #ifdef HAVE_SOLARIS - { "solaris", "Solaris" }, + BackendNamePair{ "solaris", "Solaris" }, #endif #ifdef HAVE_SNDIO - { "sndio", "SoundIO" }, -#endif -#ifdef HAVE_QSA - { "qsa", "QSA" }, + BackendNamePair{ "sndio", "SoundIO" }, #endif #ifdef HAVE_WASAPI - { "wasapi", "WASAPI" }, + BackendNamePair{ "wasapi", "WASAPI" }, #endif #ifdef HAVE_DSOUND - { "dsound", "DirectSound" }, + BackendNamePair{ "dsound", "DirectSound" }, #endif #ifdef HAVE_WINMM - { "winmm", "Windows Multimedia" }, + BackendNamePair{ "winmm", "Windows Multimedia" }, #endif #ifdef HAVE_PORTAUDIO - { "port", "PortAudio" }, + BackendNamePair{ "port", "PortAudio" }, #endif #ifdef HAVE_OPENSL - { "opensl", "OpenSL" }, + BackendNamePair{ "opensl", "OpenSL" }, #endif - { "null", "Null Output" }, + BackendNamePair{ "null", "Null Output" }, #ifdef HAVE_WAVE - { "wave", "Wave Writer" }, + BackendNamePair{ "wave", "Wave Writer" }, #endif - { "", "" } }; -const struct NameValuePair { +struct NameValuePair { + /* NOLINTBEGIN(*-avoid-c-arrays) */ const char name[64]; const char value[16]; -} speakerModeList[] = { - { "Autodetect", "" }, - { "Mono", "mono" }, - { "Stereo", "stereo" }, - { "Quadraphonic", "quad" }, - { "5.1 Surround", "surround51" }, - { "6.1 Surround", "surround61" }, - { "7.1 Surround", "surround71" }, - { "3D7.1 Surround", "surround3d71" }, - - { "Ambisonic, 1st Order", "ambi1" }, - { "Ambisonic, 2nd Order", "ambi2" }, - { "Ambisonic, 3rd Order", "ambi3" }, - - { "", "" } -}, sampleTypeList[] = { - { "Autodetect", "" }, - { "8-bit int", "int8" }, - { "8-bit uint", "uint8" }, - { "16-bit int", "int16" }, - { "16-bit uint", "uint16" }, - { "32-bit int", "int32" }, - { "32-bit uint", "uint32" }, - { "32-bit float", "float32" }, - - { "", "" } -}, resamplerList[] = { - { "Point", "point" }, - { "Linear", "linear" }, - { "Cubic Spline", "cubic" }, - { "Default (Cubic Spline)", "" }, - { "11th order Sinc (fast)", "fast_bsinc12" }, - { "11th order Sinc", "bsinc12" }, - { "23rd order Sinc (fast)", "fast_bsinc24" }, - { "23rd order Sinc", "bsinc24" }, - - { "", "" } -}, stereoModeList[] = { - { "Autodetect", "" }, - { "Speakers", "speakers" }, - { "Headphones", "headphones" }, - - { "", "" } -}, stereoEncList[] = { - { "Default", "" }, - { "Basic", "panpot" }, - { "UHJ", "uhj" }, - { "Binaural", "hrtf" }, - - { "", "" } -}, ambiFormatList[] = { - { "Default", "" }, - { "AmbiX (ACN, SN3D)", "ambix" }, - { "Furse-Malham", "fuma" }, - { "ACN, N3D", "acn+n3d" }, - { "ACN, FuMa", "acn+fuma" }, - - { "", "" } -}, hrtfModeList[] = { - { "1st Order Ambisonic", "ambi1" }, - { "2nd Order Ambisonic", "ambi2" }, - { "3rd Order Ambisonic", "ambi3" }, - { "Default (Full)", "" }, - { "Full", "full" }, - - { "", "" } + /* NOLINTEND(*-avoid-c-arrays) */ +}; +constexpr std::array speakerModeList{ + NameValuePair{ "Autodetect", "" }, + NameValuePair{ "Mono", "mono" }, + NameValuePair{ "Stereo", "stereo" }, + NameValuePair{ "Quadraphonic", "quad" }, + NameValuePair{ "5.1 Surround", "surround51" }, + NameValuePair{ "6.1 Surround", "surround61" }, + NameValuePair{ "7.1 Surround", "surround71" }, + NameValuePair{ "3D7.1 Surround", "surround3d71" }, + + NameValuePair{ "Ambisonic, 1st Order", "ambi1" }, + NameValuePair{ "Ambisonic, 2nd Order", "ambi2" }, + NameValuePair{ "Ambisonic, 3rd Order", "ambi3" }, +}; +constexpr std::array sampleTypeList{ + NameValuePair{ "Autodetect", "" }, + NameValuePair{ "8-bit int", "int8" }, + NameValuePair{ "8-bit uint", "uint8" }, + NameValuePair{ "16-bit int", "int16" }, + NameValuePair{ "16-bit uint", "uint16" }, + NameValuePair{ "32-bit int", "int32" }, + NameValuePair{ "32-bit uint", "uint32" }, + NameValuePair{ "32-bit float", "float32" }, +}; +constexpr std::array resamplerList{ + NameValuePair{ "Point", "point" }, + NameValuePair{ "Linear", "linear" }, + NameValuePair{ "Cubic Spline", "cubic" }, + NameValuePair{ "Default (Cubic Spline)", "" }, + NameValuePair{ "11th order Sinc (fast)", "fast_bsinc12" }, + NameValuePair{ "11th order Sinc", "bsinc12" }, + NameValuePair{ "23rd order Sinc (fast)", "fast_bsinc24" }, + NameValuePair{ "23rd order Sinc", "bsinc24" }, +}; +constexpr std::array stereoModeList{ + NameValuePair{ "Autodetect", "" }, + NameValuePair{ "Speakers", "speakers" }, + NameValuePair{ "Headphones", "headphones" }, +}; +constexpr std::array stereoEncList{ + NameValuePair{ "Default", "" }, + NameValuePair{ "Basic", "panpot" }, + NameValuePair{ "UHJ", "uhj" }, + NameValuePair{ "Binaural", "hrtf" }, +}; +constexpr std::array ambiFormatList{ + NameValuePair{ "Default", "" }, + NameValuePair{ "AmbiX (ACN, SN3D)", "ambix" }, + NameValuePair{ "Furse-Malham", "fuma" }, + NameValuePair{ "ACN, N3D", "acn+n3d" }, + NameValuePair{ "ACN, FuMa", "acn+fuma" }, +}; +constexpr std::array hrtfModeList{ + NameValuePair{ "1st Order Ambisonic", "ambi1" }, + NameValuePair{ "2nd Order Ambisonic", "ambi2" }, + NameValuePair{ "3rd Order Ambisonic", "ambi3" }, + NameValuePair{ "Default (Full)", "" }, + NameValuePair{ "Full", "full" }, }; QString getDefaultConfigName() { #ifdef Q_OS_WIN32 - static const char fname[] = "alsoft.ini"; + static constexpr char fname[] = "alsoft.ini"; /* NOLINT(*-avoid-c-arrays) */ auto get_appdata_path = []() noexcept -> QString { WCHAR buffer[MAX_PATH]; @@ -159,7 +156,7 @@ QString getDefaultConfigName() }; QString base = get_appdata_path(); #else - static const char fname[] = "alsoft.conf"; + static constexpr char fname[] = "alsoft.conf"; /* NOLINT(*-avoid-c-arrays) */ QByteArray base = qgetenv("XDG_CONFIG_HOME"); if(base.isEmpty()) { @@ -226,10 +223,9 @@ QStringList getAllDataPaths(const QString &append) return list; } -template<size_t N> -QString getValueFromName(const NameValuePair (&list)[N], const QString &str) +QString getValueFromName(const al::span<const NameValuePair> list, const QString &str) { - for(size_t i = 0;i < N-1;i++) + for(size_t i{0};i < list.size();++i) { if(str == list[i].name) return list[i].value; @@ -237,10 +233,9 @@ QString getValueFromName(const NameValuePair (&list)[N], const QString &str) return QString{}; } -template<size_t N> -QString getNameFromValue(const NameValuePair (&list)[N], const QString &str) +QString getNameFromValue(const al::span<const NameValuePair> list, const QString &str) { - for(size_t i = 0;i < N-1;i++) + for(size_t i{0};i < list.size();++i) { if(str == list[i].value) return list[i].name; @@ -270,44 +265,29 @@ QString getCheckValue(const QCheckBox *checkbox) } -MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::MainWindow), - mPeriodSizeValidator(nullptr), - mPeriodCountValidator(nullptr), - mSourceCountValidator(nullptr), - mEffectSlotValidator(nullptr), - mSourceSendValidator(nullptr), - mSampleRateValidator(nullptr), - mJackBufferValidator(nullptr), - mNeedsSave(false) +MainWindow::MainWindow(QWidget *parent) : QMainWindow{parent} + , ui{std::make_unique<Ui::MainWindow>()} { ui->setupUi(this); - for(int i = 0;speakerModeList[i].name[0];i++) - ui->channelConfigCombo->addItem(speakerModeList[i].name); + for(auto &item : speakerModeList) + ui->channelConfigCombo->addItem(item.name); ui->channelConfigCombo->adjustSize(); - for(int i = 0;sampleTypeList[i].name[0];i++) - ui->sampleFormatCombo->addItem(sampleTypeList[i].name); + for(auto &item : sampleTypeList) + ui->sampleFormatCombo->addItem(item.name); ui->sampleFormatCombo->adjustSize(); - for(int i = 0;stereoModeList[i].name[0];i++) - ui->stereoModeCombo->addItem(stereoModeList[i].name); + for(auto &item : stereoModeList) + ui->stereoModeCombo->addItem(item.name); ui->stereoModeCombo->adjustSize(); - for(int i = 0;stereoEncList[i].name[0];i++) - ui->stereoEncodingComboBox->addItem(stereoEncList[i].name); + for(auto &item : stereoEncList) + ui->stereoEncodingComboBox->addItem(item.name); ui->stereoEncodingComboBox->adjustSize(); - for(int i = 0;ambiFormatList[i].name[0];i++) - ui->ambiFormatComboBox->addItem(ambiFormatList[i].name); + for(auto &item : ambiFormatList) + ui->ambiFormatComboBox->addItem(item.name); ui->ambiFormatComboBox->adjustSize(); - int count; - for(count = 0;resamplerList[count].name[0];count++) { - } - ui->resamplerSlider->setRange(0, count-1); - - for(count = 0;hrtfModeList[count].name[0];count++) { - } - ui->hrtfmodeSlider->setRange(0, count-1); + ui->resamplerSlider->setRange(0, resamplerList.size()-1); + ui->hrtfmodeSlider->setRange(0, hrtfModeList.size()-1); #if !defined(HAVE_NEON) && !defined(HAVE_SSE) ui->cpuExtDisabledLabel->move(ui->cpuExtDisabledLabel->x(), ui->cpuExtDisabledLabel->y() - 60); @@ -355,22 +335,22 @@ MainWindow::MainWindow(QWidget *parent) : ui->enableEaxCheck->setVisible(false); #endif - mPeriodSizeValidator = new QIntValidator{64, 8192, this}; - ui->periodSizeEdit->setValidator(mPeriodSizeValidator); - mPeriodCountValidator = new QIntValidator{2, 16, this}; - ui->periodCountEdit->setValidator(mPeriodCountValidator); + mPeriodSizeValidator = std::make_unique<QIntValidator>(64, 8192, this); + ui->periodSizeEdit->setValidator(mPeriodSizeValidator.get()); + mPeriodCountValidator = std::make_unique<QIntValidator>(2, 16, this); + ui->periodCountEdit->setValidator(mPeriodCountValidator.get()); - mSourceCountValidator = new QIntValidator{0, 4096, this}; - ui->srcCountLineEdit->setValidator(mSourceCountValidator); - mEffectSlotValidator = new QIntValidator{0, 64, this}; - ui->effectSlotLineEdit->setValidator(mEffectSlotValidator); - mSourceSendValidator = new QIntValidator{0, 16, this}; - ui->srcSendLineEdit->setValidator(mSourceSendValidator); - mSampleRateValidator = new QIntValidator{8000, 192000, this}; - ui->sampleRateCombo->lineEdit()->setValidator(mSampleRateValidator); + mSourceCountValidator = std::make_unique<QIntValidator>(0, 4096, this); + ui->srcCountLineEdit->setValidator(mSourceCountValidator.get()); + mEffectSlotValidator = std::make_unique<QIntValidator>(0, 64, this); + ui->effectSlotLineEdit->setValidator(mEffectSlotValidator.get()); + mSourceSendValidator = std::make_unique<QIntValidator>(0, 16, this); + ui->srcSendLineEdit->setValidator(mSourceSendValidator.get()); + mSampleRateValidator = std::make_unique<QIntValidator>(8000, 192000, this); + ui->sampleRateCombo->lineEdit()->setValidator(mSampleRateValidator.get()); - mJackBufferValidator = new QIntValidator{0, 8192, this}; - ui->jackBufferSizeLine->setValidator(mJackBufferValidator); + mJackBufferValidator = std::make_unique<QIntValidator>(0, 8192, this); + ui->jackBufferSizeLine->setValidator(mJackBufferValidator.get()); connect(ui->actionLoad, &QAction::triggered, this, &MainWindow::loadConfigFromFile); connect(ui->actionSave_As, &QAction::triggered, this, &MainWindow::saveConfigAsFile); @@ -495,7 +475,7 @@ MainWindow::MainWindow(QWidget *parent) : for(int i = 1;i < ui->backendListWidget->count();i++) ui->backendListWidget->setRowHidden(i, true); - for(int i = 0;backendList[i].backend_name[0];i++) + for(size_t i{0};i < backendList.size();++i) { QList<QListWidgetItem*> items = ui->backendListWidget->findItems( backendList[i].full_string, Qt::MatchFixedString); @@ -506,17 +486,7 @@ MainWindow::MainWindow(QWidget *parent) : loadConfig(getDefaultConfigName()); } -MainWindow::~MainWindow() -{ - delete ui; - delete mPeriodSizeValidator; - delete mPeriodCountValidator; - delete mSourceCountValidator; - delete mEffectSlotValidator; - delete mSourceSendValidator; - delete mSampleRateValidator; - delete mJackBufferValidator; -} +MainWindow::~MainWindow() = default; void MainWindow::closeEvent(QCloseEvent *event) { @@ -789,7 +759,7 @@ void MainWindow::loadConfig(const QString &fname) /* The "basic" mode name is no longer supported. Use "ambi2" instead. */ if(hrtfmode == "basic") hrtfmode = "ambi2"; - for(int i = 0;hrtfModeList[i].name[0];i++) + for(size_t i{0};i < hrtfModeList.size();++i) { if(hrtfmode == hrtfModeList[i].value) { @@ -869,7 +839,8 @@ void MainWindow::loadConfig(const QString &fname) if(lastWasEmpty) continue; if(!backend.startsWith(QChar('-'))) - for(int j = 0;backendList[j].backend_name[0];j++) + { + for(size_t j{0};j < backendList.size();++j) { if(backend == backendList[j].backend_name) { @@ -877,10 +848,11 @@ void MainWindow::loadConfig(const QString &fname) break; } } + } else if(backend.size() > 1) { QStringRef backendref{backend.rightRef(backend.size()-1)}; - for(int j = 0;backendList[j].backend_name[0];j++) + for(size_t j{0};j < backendList.size();++j) { if(backendref == backendList[j].backend_name) { @@ -1070,7 +1042,7 @@ void MainWindow::saveConfig(const QString &fname) const for(int i = 0;i < ui->enabledBackendList->count();i++) { QString label{ui->enabledBackendList->item(i)->text()}; - for(int j = 0;backendList[j].backend_name[0];j++) + for(size_t j{0};j < backendList.size();++j) { if(label == backendList[j].full_string) { @@ -1082,7 +1054,7 @@ void MainWindow::saveConfig(const QString &fname) const for(int i = 0;i < ui->disabledBackendList->count();i++) { QString label{ui->disabledBackendList->item(i)->text()}; - for(int j = 0;backendList[j].backend_name[0];j++) + for(size_t j{0};j < backendList.size();++j) { if(label == backendList[j].full_string) { @@ -1294,7 +1266,7 @@ void MainWindow::updateJackBufferSizeSlider() void MainWindow::updateHrtfModeLabel(int num) { - ui->hrtfmodeLabel->setText(hrtfModeList[num].name); + ui->hrtfmodeLabel->setText(hrtfModeList[static_cast<uint>(num)].name); enableApplyButton(); } @@ -1336,7 +1308,7 @@ void MainWindow::showEnabledBackendMenu(QPoint pt) if(ui->enabledBackendList->selectedItems().empty()) removeAction->setEnabled(false); ctxmenu.addSeparator(); - for(size_t i = 0;backendList[i].backend_name[0];i++) + for(size_t i{0};i < backendList.size();++i) { QString backend{backendList[i].full_string}; QAction *action{ctxmenu.addAction(QString("Add ")+backend)}; @@ -1374,7 +1346,7 @@ void MainWindow::showDisabledBackendMenu(QPoint pt) if(ui->disabledBackendList->selectedItems().empty()) removeAction->setEnabled(false); ctxmenu.addSeparator(); - for(size_t i = 0;backendList[i].backend_name[0];i++) + for(size_t i{0};i < backendList.size();++i) { QString backend{backendList[i].full_string}; QAction *action{ctxmenu.addAction(QString("Add ")+backend)}; diff --git a/utils/alsoft-config/mainwindow.h b/utils/alsoft-config/mainwindow.h index e2d30b86..96151ca2 100644 --- a/utils/alsoft-config/mainwindow.h +++ b/utils/alsoft-config/mainwindow.h @@ -1,6 +1,8 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H +#include <memory> + #include <QMainWindow> #include <QListWidget> @@ -60,15 +62,15 @@ private slots: void selectWaveOutput(); private: - Ui::MainWindow *ui; - - QValidator *mPeriodSizeValidator{}; - QValidator *mPeriodCountValidator{}; - QValidator *mSourceCountValidator{}; - QValidator *mEffectSlotValidator{}; - QValidator *mSourceSendValidator{}; - QValidator *mSampleRateValidator{}; - QValidator *mJackBufferValidator{}; + std::unique_ptr<QValidator> mPeriodSizeValidator; + std::unique_ptr<QValidator> mPeriodCountValidator; + std::unique_ptr<QValidator> mSourceCountValidator; + std::unique_ptr<QValidator> mEffectSlotValidator; + std::unique_ptr<QValidator> mSourceSendValidator; + std::unique_ptr<QValidator> mSampleRateValidator; + std::unique_ptr<QValidator> mJackBufferValidator; + + std::unique_ptr<Ui::MainWindow> ui; bool mNeedsSave{}; diff --git a/utils/makemhr/loaddef.cpp b/utils/makemhr/loaddef.cpp index 54ba96a3..04489173 100644 --- a/utils/makemhr/loaddef.cpp +++ b/utils/makemhr/loaddef.cpp @@ -46,12 +46,12 @@ #include "mysofa.h" // Constants for accessing the token reader's ring buffer. -#define TR_RING_BITS (16) -#define TR_RING_SIZE (1 << TR_RING_BITS) -#define TR_RING_MASK (TR_RING_SIZE - 1) +constexpr uint TRRingBits{16}; +constexpr uint TRRingSize{1 << TRRingBits}; +constexpr uint TRRingMask{TRRingSize - 1}; // The token reader's load interval in bytes. -#define TR_LOAD_SIZE (TR_RING_SIZE >> 2) +constexpr uint TRLoadSize{TRRingSize >> 2}; // Token reader state for parsing the data set definition. struct TokenReaderT { @@ -59,7 +59,7 @@ struct TokenReaderT { const char *mName{}; uint mLine{}; uint mColumn{}; - char mRing[TR_RING_SIZE]{}; + std::array<char,TRRingSize> mRing{}; std::streamsize mIn{}; std::streamsize mOut{}; @@ -70,44 +70,48 @@ struct TokenReaderT { // The maximum identifier length used when processing the data set // definition. -#define MAX_IDENT_LEN (16) +constexpr uint MaxIdentLen{16}; // The limits for the listener's head 'radius' in the data set definition. -#define MIN_RADIUS (0.05) -#define MAX_RADIUS (0.15) +constexpr double MinRadius{0.05}; +constexpr double MaxRadius{0.15}; // The maximum number of channels that can be addressed for a WAVE file // source listed in the data set definition. -#define MAX_WAVE_CHANNELS (65535) +constexpr uint MaxWaveChannels{65535}; // The limits to the byte size for a binary source listed in the definition // file. -#define MIN_BIN_SIZE (2) -#define MAX_BIN_SIZE (4) - -// The minimum number of significant bits for binary sources listed in the -// data set definition. The maximum is calculated from the byte size. -#define MIN_BIN_BITS (16) +enum : uint { + MinBinSize = 2, + MaxBinSize = 4 +}; // The limits to the number of significant bits for an ASCII source listed in // the data set definition. -#define MIN_ASCII_BITS (16) -#define MAX_ASCII_BITS (32) +enum : uint { + MinASCIIBits = 16, + MaxASCIIBits = 32 +}; // The four-character-codes for RIFF/RIFX WAVE file chunks. -#define FOURCC_RIFF (0x46464952) // 'RIFF' -#define FOURCC_RIFX (0x58464952) // 'RIFX' -#define FOURCC_WAVE (0x45564157) // 'WAVE' -#define FOURCC_FMT (0x20746D66) // 'fmt ' -#define FOURCC_DATA (0x61746164) // 'data' -#define FOURCC_LIST (0x5453494C) // 'LIST' -#define FOURCC_WAVL (0x6C766177) // 'wavl' -#define FOURCC_SLNT (0x746E6C73) // 'slnt' +enum : uint { + FOURCC_RIFF = 0x46464952, // 'RIFF' + FOURCC_RIFX = 0x58464952, // 'RIFX' + FOURCC_WAVE = 0x45564157, // 'WAVE' + FOURCC_FMT = 0x20746D66, // 'fmt ' + FOURCC_DATA = 0x61746164, // 'data' + FOURCC_LIST = 0x5453494C, // 'LIST' + FOURCC_WAVL = 0x6C766177, // 'wavl' + FOURCC_SLNT = 0x746E6C73, // 'slnt' +}; // The supported wave formats. -#define WAVE_FORMAT_PCM (0x0001) -#define WAVE_FORMAT_IEEE_FLOAT (0x0003) -#define WAVE_FORMAT_EXTENSIBLE (0xFFFE) +enum : uint { + WAVE_FORMAT_PCM = 0x0001, + WAVE_FORMAT_IEEE_FLOAT = 0x0003, + WAVE_FORMAT_EXTENSIBLE = 0xFFFE, +}; enum ByteOrderT { @@ -197,13 +201,14 @@ static int TrLoad(TokenReaderT *tr) { std::istream &istream = tr->mIStream; - std::streamsize toLoad{TR_RING_SIZE - static_cast<std::streamsize>(tr->mIn - tr->mOut)}; - if(toLoad >= TR_LOAD_SIZE && istream.good()) + std::streamsize toLoad{TRRingSize - static_cast<std::streamsize>(tr->mIn - tr->mOut)}; + if(toLoad >= TRLoadSize && istream.good()) { - // Load TR_LOAD_SIZE (or less if at the end of the file) per read. - toLoad = TR_LOAD_SIZE; - std::streamsize in{tr->mIn&TR_RING_MASK}; - std::streamsize count{TR_RING_SIZE - in}; + // Load TRLoadSize (or less if at the end of the file) per read. + toLoad = TRLoadSize; + + const auto in = static_cast<uint>(tr->mIn&TRRingMask); + std::streamsize count{TRRingSize - in}; if(count < toLoad) { istream.read(&tr->mRing[in], count); @@ -217,10 +222,10 @@ static int TrLoad(TokenReaderT *tr) tr->mIn += istream.gcount(); } - if(tr->mOut >= TR_RING_SIZE) + if(tr->mOut >= TRRingSize) { - tr->mOut -= TR_RING_SIZE; - tr->mIn -= TR_RING_SIZE; + tr->mOut -= TRRingSize; + tr->mIn -= TRRingSize; } } if(tr->mIn > tr->mOut) @@ -264,7 +269,7 @@ static void TrSkipLine(TokenReaderT *tr) while(TrLoad(tr)) { - ch = tr->mRing[tr->mOut&TR_RING_MASK]; + ch = tr->mRing[tr->mOut&TRRingMask]; tr->mOut++; if(ch == '\n') { @@ -281,7 +286,7 @@ static int TrSkipWhitespace(TokenReaderT *tr) { while(TrLoad(tr)) { - char ch{tr->mRing[tr->mOut&TR_RING_MASK]}; + char ch{tr->mRing[tr->mOut&TRRingMask]}; if(isspace(ch)) { tr->mOut++; @@ -315,7 +320,7 @@ static int TrIsIdent(TokenReaderT *tr) { if(!TrSkipWhitespace(tr)) return 0; - char ch{tr->mRing[tr->mOut&TR_RING_MASK]}; + char ch{tr->mRing[tr->mOut&TRRingMask]}; return ch == '_' || isalpha(ch); } @@ -334,7 +339,7 @@ static int TrIsOperator(TokenReaderT *tr, const char *op) len = 0; while(op[len] != '\0' && out < tr->mIn) { - ch = tr->mRing[out&TR_RING_MASK]; + ch = tr->mRing[out&TRRingMask]; if(ch != op[len]) break; len++; out++; @@ -359,7 +364,7 @@ static int TrReadIdent(TokenReaderT *tr, const uint maxLen, char *ident) if(TrSkipWhitespace(tr)) { col = tr->mColumn; - ch = tr->mRing[tr->mOut&TR_RING_MASK]; + ch = tr->mRing[tr->mOut&TRRingMask]; if(ch == '_' || isalpha(ch)) { len = 0; @@ -370,7 +375,7 @@ static int TrReadIdent(TokenReaderT *tr, const uint maxLen, char *ident) tr->mOut++; if(!TrLoad(tr)) break; - ch = tr->mRing[tr->mOut&TR_RING_MASK]; + ch = tr->mRing[tr->mOut&TRRingMask]; } while(ch == '_' || isdigit(ch) || isalpha(ch)); tr->mColumn += len; @@ -396,7 +401,7 @@ static int TrReadInt(TokenReaderT *tr, const int loBound, const int hiBound, int col = tr->mColumn; uint len{0}; std::array<char,64+1> temp{}; - char ch{tr->mRing[tr->mOut&TR_RING_MASK]}; + char ch{tr->mRing[tr->mOut&TRRingMask]}; if(ch == '+' || ch == '-') { temp[len] = ch; @@ -406,7 +411,7 @@ static int TrReadInt(TokenReaderT *tr, const int loBound, const int hiBound, int uint digis{0}; while(TrLoad(tr)) { - ch = tr->mRing[tr->mOut&TR_RING_MASK]; + ch = tr->mRing[tr->mOut&TRRingMask]; if(!isdigit(ch)) break; if(len < 64) temp[len] = ch; @@ -445,7 +450,7 @@ static int TrReadFloat(TokenReaderT *tr, const double loBound, const double hiBo col = tr->mColumn; std::array<char,64+1> temp{}; uint len{0}; - char ch{tr->mRing[tr->mOut&TR_RING_MASK]}; + char ch{tr->mRing[tr->mOut&TRRingMask]}; if(ch == '+' || ch == '-') { temp[len] = ch; @@ -456,7 +461,7 @@ static int TrReadFloat(TokenReaderT *tr, const double loBound, const double hiBo uint digis{0}; while(TrLoad(tr)) { - ch = tr->mRing[tr->mOut&TR_RING_MASK]; + ch = tr->mRing[tr->mOut&TRRingMask]; if(!isdigit(ch)) break; if(len < 64) temp[len] = ch; @@ -473,7 +478,7 @@ static int TrReadFloat(TokenReaderT *tr, const double loBound, const double hiBo } while(TrLoad(tr)) { - ch = tr->mRing[tr->mOut&TR_RING_MASK]; + ch = tr->mRing[tr->mOut&TRRingMask]; if(!isdigit(ch)) break; if(len < 64) temp[len] = ch; @@ -499,7 +504,7 @@ static int TrReadFloat(TokenReaderT *tr, const double loBound, const double hiBo } while(TrLoad(tr)) { - ch = tr->mRing[tr->mOut&TR_RING_MASK]; + ch = tr->mRing[tr->mOut&TRRingMask]; if(!isdigit(ch)) break; if(len < 64) temp[len] = ch; @@ -543,14 +548,14 @@ static int TrReadString(TokenReaderT *tr, const uint maxLen, char *text) if(TrSkipWhitespace(tr)) { col = tr->mColumn; - ch = tr->mRing[tr->mOut&TR_RING_MASK]; + ch = tr->mRing[tr->mOut&TRRingMask]; if(ch == '\"') { tr->mOut++; len = 0; while(TrLoad(tr)) { - ch = tr->mRing[tr->mOut&TR_RING_MASK]; + ch = tr->mRing[tr->mOut&TRRingMask]; tr->mOut++; if(ch == '\"') break; @@ -596,7 +601,7 @@ static int TrReadOperator(TokenReaderT *tr, const char *op) len = 0; while(op[len] != '\0' && TrLoad(tr)) { - ch = tr->mRing[tr->mOut&TR_RING_MASK]; + ch = tr->mRing[tr->mOut&TRRingMask]; if(ch != op[len]) break; len++; tr->mOut++; @@ -1225,7 +1230,7 @@ static int ProcessMetrics(TokenReaderT *tr, const uint fftSize, const uint trunc { int hasRate = 0, hasType = 0, hasPoints = 0, hasRadius = 0; int hasDistance = 0, hasAzimuths = 0; - std::array<char,MAX_IDENT_LEN+1> ident; + std::array<char,MaxIdentLen+1> ident; uint line, col; double fpVal; uint points; @@ -1240,7 +1245,7 @@ static int ProcessMetrics(TokenReaderT *tr, const uint fftSize, const uint trunc while(TrIsIdent(tr)) { TrIndication(tr, &line, &col); - if(!TrReadIdent(tr, MAX_IDENT_LEN, ident.data())) + if(!TrReadIdent(tr, MaxIdentLen, ident.data())) return 0; if(al::strcasecmp(ident.data(), "rate") == 0) { @@ -1258,7 +1263,7 @@ static int ProcessMetrics(TokenReaderT *tr, const uint fftSize, const uint trunc } else if(al::strcasecmp(ident.data(), "type") == 0) { - std::array<char,MAX_IDENT_LEN+1> type; + std::array<char,MaxIdentLen+1> type; if(hasType) { @@ -1268,7 +1273,7 @@ static int ProcessMetrics(TokenReaderT *tr, const uint fftSize, const uint trunc if(!TrReadOperator(tr, "=")) return 0; - if(!TrReadIdent(tr, MAX_IDENT_LEN, type.data())) + if(!TrReadIdent(tr, MaxIdentLen, type.data())) return 0; hData->mChannelType = MatchChannelType(type.data()); if(hData->mChannelType == CT_NONE) @@ -1322,7 +1327,7 @@ static int ProcessMetrics(TokenReaderT *tr, const uint fftSize, const uint trunc } if(!TrReadOperator(tr, "=")) return 0; - if(!TrReadFloat(tr, MIN_RADIUS, MAX_RADIUS, &fpVal)) + if(!TrReadFloat(tr, MinRadius, MaxRadius, &fpVal)) return 0; hData->mRadius = fpVal; hasRadius = 1; @@ -1511,13 +1516,13 @@ static ElementTypeT MatchElementType(const char *ident) // Parse and validate a source reference from the data set definition. static int ReadSourceRef(TokenReaderT *tr, SourceRefT *src) { - std::array<char,MAX_IDENT_LEN+1> ident; + std::array<char,MaxIdentLen+1> ident; uint line, col; double fpVal; int intVal; TrIndication(tr, &line, &col); - if(!TrReadIdent(tr, MAX_IDENT_LEN, ident.data())) + if(!TrReadIdent(tr, MaxIdentLen, ident.data())) return 0; src->mFormat = MatchSourceFormat(ident.data()); if(src->mFormat == SF_NONE) @@ -1544,7 +1549,7 @@ static int ReadSourceRef(TokenReaderT *tr, SourceRefT *src) src->mAzimuth = fpVal; if(!TrReadOperator(tr, ":")) return 0; - if(!TrReadInt(tr, 0, MAX_WAVE_CHANNELS, &intVal)) + if(!TrReadInt(tr, 0, MaxWaveChannels, &intVal)) return 0; src->mType = ET_NONE; src->mSize = 0; @@ -1554,7 +1559,7 @@ static int ReadSourceRef(TokenReaderT *tr, SourceRefT *src) } else if(src->mFormat == SF_WAVE) { - if(!TrReadInt(tr, 0, MAX_WAVE_CHANNELS, &intVal)) + if(!TrReadInt(tr, 0, MaxWaveChannels, &intVal)) return 0; src->mType = ET_NONE; src->mSize = 0; @@ -1565,7 +1570,7 @@ static int ReadSourceRef(TokenReaderT *tr, SourceRefT *src) else { TrIndication(tr, &line, &col); - if(!TrReadIdent(tr, MAX_IDENT_LEN, ident.data())) + if(!TrReadIdent(tr, MaxIdentLen, ident.data())) return 0; src->mType = MatchElementType(ident.data()); if(src->mType == ET_NONE) @@ -1579,7 +1584,7 @@ static int ReadSourceRef(TokenReaderT *tr, SourceRefT *src) return 0; if(src->mType == ET_INT) { - if(!TrReadInt(tr, MIN_BIN_SIZE, MAX_BIN_SIZE, &intVal)) + if(!TrReadInt(tr, MinBinSize, MaxBinSize, &intVal)) return 0; src->mSize = static_cast<uint>(intVal); if(!TrIsOperator(tr, ",")) @@ -1590,9 +1595,9 @@ static int ReadSourceRef(TokenReaderT *tr, SourceRefT *src) TrIndication(tr, &line, &col); if(!TrReadInt(tr, -2147483647-1, 2147483647, &intVal)) return 0; - if(std::abs(intVal) < MIN_BIN_BITS || static_cast<uint>(std::abs(intVal)) > (8*src->mSize)) + if(std::abs(intVal) < int{MinBinSize}*8 || static_cast<uint>(std::abs(intVal)) > (8*src->mSize)) { - TrErrorAt(tr, line, col, "Expected a value of (+/-) %d to %d.\n", MIN_BIN_BITS, 8*src->mSize); + TrErrorAt(tr, line, col, "Expected a value of (+/-) %d to %d.\n", MinBinSize*8, 8*src->mSize); return 0; } src->mBits = intVal; @@ -1616,7 +1621,7 @@ static int ReadSourceRef(TokenReaderT *tr, SourceRefT *src) { if(!TrReadOperator(tr, ",")) return 0; - if(!TrReadInt(tr, MIN_ASCII_BITS, MAX_ASCII_BITS, &intVal)) + if(!TrReadInt(tr, MinASCIIBits, MaxASCIIBits, &intVal)) return 0; src->mSize = 0; src->mBits = intVal; @@ -1658,12 +1663,12 @@ static int ReadSourceRef(TokenReaderT *tr, SourceRefT *src) // Parse and validate a SOFA source reference from the data set definition. static int ReadSofaRef(TokenReaderT *tr, SourceRefT *src) { - std::array<char,MAX_IDENT_LEN+1> ident; + std::array<char,MaxIdentLen+1> ident; uint line, col; int intVal; TrIndication(tr, &line, &col); - if(!TrReadIdent(tr, MAX_IDENT_LEN, ident.data())) + if(!TrReadIdent(tr, MaxIdentLen, ident.data())) return 0; src->mFormat = MatchSourceFormat(ident.data()); if(src->mFormat != SF_SOFA) @@ -1780,9 +1785,9 @@ static int ProcessSources(TokenReaderT *tr, HrirDataT *hData, const uint outRate if(hData->mChannelType == CT_STEREO) { - std::array<char,MAX_IDENT_LEN+1> type{}; + std::array<char,MaxIdentLen+1> type{}; - if(!TrReadIdent(tr, MAX_IDENT_LEN, type.data())) + if(!TrReadIdent(tr, MaxIdentLen, type.data())) return 0; const ChannelTypeT channelType{MatchChannelType(type.data())}; @@ -1801,8 +1806,8 @@ static int ProcessSources(TokenReaderT *tr, HrirDataT *hData, const uint outRate } else { - std::array<char,MAX_IDENT_LEN+1> type{}; - if(!TrReadIdent(tr, MAX_IDENT_LEN, type.data())) + std::array<char,MaxIdentLen+1> type{}; + if(!TrReadIdent(tr, MaxIdentLen, type.data())) return 0; ChannelTypeT channelType{MatchChannelType(type.data())}; @@ -1925,8 +1930,8 @@ static int ProcessSources(TokenReaderT *tr, HrirDataT *hData, const uint outRate uint ti{0}; if(hData->mChannelType == CT_STEREO) { - std::array<char,MAX_IDENT_LEN+1> ident{}; - if(!TrReadIdent(tr, MAX_IDENT_LEN, ident.data())) + std::array<char,MaxIdentLen+1> ident{}; + if(!TrReadIdent(tr, MaxIdentLen, ident.data())) return 0; ti = static_cast<uint>(MatchTargetEar(ident.data())); if(static_cast<int>(ti) < 0) diff --git a/utils/makemhr/loadsofa.cpp b/utils/makemhr/loadsofa.cpp index 4b2ba2f4..eaddd31b 100644 --- a/utils/makemhr/loadsofa.cpp +++ b/utils/makemhr/loadsofa.cpp @@ -144,7 +144,7 @@ float GetSampleRate(MYSOFA_HRTF *sofaHrtf) return 0.0f; } /* I dimensions guarantees 1 element, so just extract it. */ - if(srate_array->values[0] < MIN_RATE || srate_array->values[0] > MAX_RATE) + if(srate_array->values[0] < float{MIN_RATE} || srate_array->values[0] > float{MAX_RATE}) { fprintf(stderr, "Sample rate out of range: %f (expected %u to %u)", srate_array->values[0], MIN_RATE, MAX_RATE); diff --git a/utils/makemhr/makemhr.cpp b/utils/makemhr/makemhr.cpp index 3c0da19f..80e217ee 100644 --- a/utils/makemhr/makemhr.cpp +++ b/utils/makemhr/makemhr.cpp @@ -90,6 +90,7 @@ #include "alcomplex.h" #include "alfstream.h" +#include "alnumbers.h" #include "alspan.h" #include "alstring.h" #include "loaddef.h" @@ -98,61 +99,56 @@ #include "win_main_utf8.h" -namespace { - -using namespace std::placeholders; - -} // namespace - -#ifndef M_PI -#define M_PI (3.14159265358979323846) -#endif - - HrirDataT::~HrirDataT() = default; -// Head model used for calculating the impulse delays. -enum HeadModelT { - HM_NONE, - HM_DATASET, // Measure the onset from the dataset. - HM_SPHERE // Calculate the onset using a spherical head model. -}; +namespace { +using namespace std::placeholders; // The epsilon used to maintain signal stability. -#define EPSILON (1e-9) +constexpr double Epsilon{1e-9}; // The limits to the FFT window size override on the command line. -#define MIN_FFTSIZE (65536) -#define MAX_FFTSIZE (131072) +constexpr uint MinFftSize{65536}; +constexpr uint MaxFftSize{131072}; // The limits to the equalization range limit on the command line. -#define MIN_LIMIT (2.0) -#define MAX_LIMIT (120.0) +constexpr double MinLimit{2.0}; +constexpr double MaxLimit{120.0}; // The limits to the truncation window size on the command line. -#define MIN_TRUNCSIZE (16) -#define MAX_TRUNCSIZE (128) +constexpr uint MinTruncSize{16}; +constexpr uint MaxTruncSize{128}; // The limits to the custom head radius on the command line. -#define MIN_CUSTOM_RADIUS (0.05) -#define MAX_CUSTOM_RADIUS (0.15) - -// The defaults for the command line options. -#define DEFAULT_FFTSIZE (65536) -#define DEFAULT_EQUALIZE (1) -#define DEFAULT_SURFACE (1) -#define DEFAULT_LIMIT (24.0) -#define DEFAULT_TRUNCSIZE (64) -#define DEFAULT_HEAD_MODEL (HM_DATASET) -#define DEFAULT_CUSTOM_RADIUS (0.0) +constexpr double MinCustomRadius{0.05}; +constexpr double MaxCustomRadius{0.15}; // The maximum propagation delay value supported by OpenAL Soft. -#define MAX_HRTD (63.0) +constexpr double MaxHrtd{63.0}; // The OpenAL Soft HRTF format marker. It stands for minimum-phase head // response protocol 03. -#define MHR_FORMAT ("MinPHR03") +constexpr char MHRFormat[] = "MinPHR03"; // NOLINT(*-avoid-c-arrays) + + +// Head model used for calculating the impulse delays. +enum HeadModelT { + HM_NONE, + HM_DATASET, // Measure the onset from the dataset. + HM_SPHERE, // Calculate the onset using a spherical head model. + + DEFAULT_HEAD_MODEL = HM_DATASET +}; + + +// The defaults for the command line options. +constexpr uint DefaultFftSize{65536}; +constexpr bool DefaultEqualize{true}; +constexpr bool DefaultSurface{true}; +constexpr double DefaultLimit{24.0}; +constexpr uint DefaultTruncSize{64}; +constexpr double DefaultCustomRadius{0.0}; /* Channel index enums. Mono uses LeftChannel only. */ enum ChannelIndex : uint { @@ -165,7 +161,7 @@ enum ChannelIndex : uint { * pattern string are replaced with the replacement string. The result is * truncated if necessary. */ -static std::string StrSubst(al::span<const char> in, const al::span<const char> pat, +std::string StrSubst(al::span<const char> in, const al::span<const char> pat, const al::span<const char> rep) { std::string ret; @@ -198,12 +194,12 @@ static std::string StrSubst(al::span<const char> in, const al::span<const char> *********************/ // Simple clamp routine. -static double Clamp(const double val, const double lower, const double upper) +double Clamp(const double val, const double lower, const double upper) { return std::min(std::max(val, lower), upper); } -static inline uint dither_rng(uint *seed) +inline uint dither_rng(uint *seed) { *seed = *seed * 96314165 + 907633515; return *seed; @@ -211,8 +207,8 @@ static inline uint dither_rng(uint *seed) // Performs a triangular probability density function dither. The input samples // should be normalized (-1 to +1). -static void TpdfDither(double *RESTRICT out, const double *RESTRICT in, const double scale, - const uint count, const uint step, uint *seed) +void TpdfDither(double *RESTRICT out, const double *RESTRICT in, const double scale, + const uint count, const uint step, uint *seed) { static constexpr double PRNG_SCALE = 1.0 / std::numeric_limits<uint>::max(); @@ -231,9 +227,11 @@ static void TpdfDither(double *RESTRICT out, const double *RESTRICT in, const do * of a signal's magnitude response, the imaginary components can be used as * the angles for minimum-phase reconstruction. */ -inline static void Hilbert(const uint n, complex_d *inout) +inline void Hilbert(const uint n, complex_d *inout) { complex_hilbert({inout, n}); } +} // namespace + /* Calculate the magnitude response of the given input. This is used in * place of phase decomposition, since the phase residuals are discarded for * minimum phase reconstruction. The mirrored half of the response is also @@ -244,7 +242,7 @@ void MagnitudeResponse(const uint n, const complex_d *in, double *out) const uint m = 1 + (n / 2); uint i; for(i = 0;i < m;i++) - out[i] = std::max(std::abs(in[i]), EPSILON); + out[i] = std::max(std::abs(in[i]), Epsilon); } /* Apply a range limit (in dB) to the given magnitude response. This is used @@ -295,7 +293,7 @@ static void MinimumPhase(const uint n, double *mags, complex_d *out) } Hilbert(n, out); // Remove any DC offset the filter has. - mags[0] = EPSILON; + mags[0] = Epsilon; for(i = 0;i < n;i++) out[i] = std::polar(mags[i], out[i].imag()); } @@ -350,7 +348,7 @@ static int StoreMhr(const HrirDataT *hData, const char *filename) fprintf(stderr, "\nError: Could not open MHR file '%s'.\n", filename); return 0; } - if(!WriteAscii(MHR_FORMAT, fp, filename)) + if(!WriteAscii(MHRFormat, fp, filename)) return 0; if(!WriteBin4(4, hData->mIrRate, fp, filename)) return 0; @@ -385,7 +383,7 @@ static int StoreMhr(const HrirDataT *hData, const char *filename) for(ai = 0;ai < hData->mFds[fi].mEvs[ei].mAzs.size();ai++) { HrirAzT *azd = &hData->mFds[fi].mEvs[ei].mAzs[ai]; - std::array<double,2*MAX_TRUNCSIZE> out{}; + std::array<double,2*MaxTruncSize> out{}; TpdfDither(out.data(), azd->mIrs[0], scale, n, channels, &dither_seed); if(hData->mChannelType == CT_STEREO) @@ -494,17 +492,17 @@ static void CalculateDfWeights(const HrirDataT *hData, double *weights) outerRa = 10.0f; const double raPowDiff{std::pow(outerRa, 3.0) - std::pow(innerRa, 3.0)}; - evs = M_PI / 2.0 / static_cast<double>(hData->mFds[fi].mEvs.size() - 1); + evs = al::numbers::pi / 2.0 / static_cast<double>(hData->mFds[fi].mEvs.size() - 1); for(ei = hData->mFds[fi].mEvStart;ei < hData->mFds[fi].mEvs.size();ei++) { const auto &elev = hData->mFds[fi].mEvs[ei]; // For each elevation, calculate the upper and lower limits of // the patch band. ev = elev.mElevation; - lowerEv = std::max(-M_PI / 2.0, ev - evs); - upperEv = std::min(M_PI / 2.0, ev + evs); + lowerEv = std::max(-al::numbers::pi / 2.0, ev - evs); + upperEv = std::min(al::numbers::pi / 2.0, ev + evs); // Calculate the surface area of the patch band. - solidAngle = 2.0 * M_PI * (std::sin(upperEv) - std::sin(lowerEv)); + solidAngle = 2.0 * al::numbers::pi * (std::sin(upperEv) - std::sin(lowerEv)); // Then the volume of the extruded patch band. solidVolume = solidAngle * raPowDiff / 3.0; // Each weight is the volume of one extruded patch. @@ -583,7 +581,7 @@ static void CalculateDiffuseFieldAverage(const HrirDataT *hData, const uint chan } // Finish the average calculation and keep it from being too small. for(i = 0;i < m;i++) - dfa[(ti * m) + i] = std::max(sqrt(dfa[(ti * m) + i]), EPSILON); + dfa[(ti * m) + i] = std::max(sqrt(dfa[(ti * m) + i]), Epsilon); // Apply a limit to the magnitude range of the diffuse-field average // if desired. if(limit > 0.0) @@ -619,7 +617,8 @@ static void DiffuseFieldEqualize(const uint channels, const uint m, const double */ static void CalcAzIndices(const HrirFdT &field, const uint ei, const double az, uint *a0, uint *a1, double *af) { - double f{(2.0*M_PI + az) * static_cast<double>(field.mEvs[ei].mAzs.size()) / (2.0*M_PI)}; + double f{(2.0*al::numbers::pi + az) * static_cast<double>(field.mEvs[ei].mAzs.size()) / + (2.0*al::numbers::pi)}; const uint i{static_cast<uint>(f) % static_cast<uint>(field.mEvs[ei].mAzs.size())}; f -= std::floor(f); @@ -669,7 +668,7 @@ static void SynthesizeOnsets(HrirDataT *hData) * the mirrored elevation to find the indices for the polar * opposite position (may need blending). */ - const double az{field.mEvs[ei].mAzs[ai].mAzimuth + M_PI}; + const double az{field.mEvs[ei].mAzs[ai].mAzimuth + al::numbers::pi}; CalcAzIndices(field, topElev, az, &a0, &a1, &af); /* Blend the delays, and again, swap the ears. */ @@ -701,8 +700,8 @@ static void SynthesizeOnsets(HrirDataT *hData) * measurement). */ double az{field.mEvs[ei].mAzs[ai].mAzimuth}; - if(az <= M_PI) az = M_PI - az; - else az = (M_PI*2.0)-az + M_PI; + if(az <= al::numbers::pi) az = al::numbers::pi - az; + else az = (al::numbers::pi*2.0)-az + al::numbers::pi; CalcAzIndices(field, topElev, az, &a0, &a1, &af); field.mEvs[ei].mAzs[ai].mDelays[0] = Lerp( @@ -780,7 +779,7 @@ static void SynthesizeHrirs(HrirDataT *hData) * and vice-versa, this produces a decent phantom-center response * underneath the head. */ - CalcAzIndices(field, oi, ((ti==0) ? -M_PI : M_PI) / 2.0, &a0, &a1, &af); + CalcAzIndices(field, oi, al::numbers::pi / ((ti==0) ? -2.0 : 2.0), &a0, &a1, &af); for(uint i{0u};i < m;i++) { field.mEvs[0].mAzs[0].mIrs[ti][i] = Lerp(field.mEvs[oi].mAzs[a0].mIrs[ti][i], @@ -902,7 +901,7 @@ struct HrirReconstructor { * time-domain response. */ for(size_t i{0};i < m;++i) - mags[i] = std::max(mIrs[idx][i], EPSILON); + mags[i] = std::max(mIrs[idx][i], Epsilon); MinimumPhase(mFftSize, mags.data(), h.data()); FftInverse(mFftSize, h.data()); for(uint i{0u};i < mIrPoints;++i) @@ -1030,7 +1029,7 @@ static double CalcLTD(const double ev, const double az, const double rad, const azp = std::asin(std::cos(ev) * std::sin(az)); dlp = std::sqrt((dist*dist) + (rad*rad) + (2.0*dist*rad*sin(azp))); l = std::sqrt((dist*dist) - (rad*rad)); - al = (0.5 * M_PI) + azp; + al = (0.5 * al::numbers::pi) + azp; if(dlp > l) dlp = l + (rad * (al - std::acos(rad / dist))); return dlp / 343.3; @@ -1098,10 +1097,10 @@ static void CalculateHrtds(const HeadModelT model, const double radius, HrirData } } } - if(maxHrtd > MAX_HRTD) + if(maxHrtd > MaxHrtd) { - fprintf(stdout, " Scaling for max delay of %f samples to %f\n...\n", maxHrtd, MAX_HRTD); - const double scale{MAX_HRTD / maxHrtd}; + fprintf(stdout, " Scaling for max delay of %f samples to %f\n...\n", maxHrtd, MaxHrtd); + const double scale{MaxHrtd / maxHrtd}; for(auto &field : hData->mFds) { for(auto &elev : field.mEvs) @@ -1148,11 +1147,12 @@ bool PrepareHrirData(const al::span<const double> distances, { uint azCount = azCounts[fi][ei]; - hData->mFds[fi].mEvs[ei].mElevation = -M_PI / 2.0 + M_PI * ei / (evCounts[fi] - 1); + hData->mFds[fi].mEvs[ei].mElevation = -al::numbers::pi / 2.0 + al::numbers::pi * ei / + (evCounts[fi] - 1); hData->mFds[fi].mEvs[ei].mAzs = {&hData->mAzsBase[azTotal], azCount}; for(uint ai{0};ai < azCount;ai++) { - hData->mFds[fi].mEvs[ei].mAzs[ai].mAzimuth = 2.0 * M_PI * ai / azCount; + hData->mFds[fi].mEvs[ei].mAzs[ai].mAzimuth = 2.0 * al::numbers::pi * ai / azCount; hData->mFds[fi].mEvs[ei].mAzs[ai].mIndex = azTotal + ai; hData->mFds[fi].mEvs[ei].mAzs[ai].mDelays[0] = 0.0; hData->mFds[fi].mEvs[ei].mAzs[ai].mDelays[1] = 0.0; @@ -1260,7 +1260,7 @@ static int ProcessDefinition(const char *inName, const uint outRate, const Chann fprintf(stdout, "Normalizing final HRIRs...\n"); NormalizeHrirs(&hData); fprintf(stdout, "Calculating impulse delays...\n"); - CalculateHrtds(model, (radius > DEFAULT_CUSTOM_RADIUS) ? radius : hData.mRadius, &hData); + CalculateHrtds(model, (radius > DefaultCustomRadius) ? radius : hData.mRadius, &hData); const auto rateStr = std::to_string(hData.mIrRate); const auto expName = StrSubst({outName, strlen(outName)}, {"%r", 2}, @@ -1279,13 +1279,13 @@ static void PrintHelp(const char *argv0, FILE *ofile) fprintf(ofile, " right ear.\n"); fprintf(ofile, " -a Change the data set to single field, using the farthest field.\n"); fprintf(ofile, " -j <threads> Number of threads used to process HRIRs (default: 2).\n"); - fprintf(ofile, " -f <points> Override the FFT window size (default: %u).\n", DEFAULT_FFTSIZE); - fprintf(ofile, " -e {on|off} Toggle diffuse-field equalization (default: %s).\n", (DEFAULT_EQUALIZE ? "on" : "off")); - fprintf(ofile, " -s {on|off} Toggle surface-weighted diffuse-field average (default: %s).\n", (DEFAULT_SURFACE ? "on" : "off")); + fprintf(ofile, " -f <points> Override the FFT window size (default: %u).\n", DefaultFftSize); + fprintf(ofile, " -e {on|off} Toggle diffuse-field equalization (default: %s).\n", (DefaultEqualize ? "on" : "off")); + fprintf(ofile, " -s {on|off} Toggle surface-weighted diffuse-field average (default: %s).\n", (DefaultSurface ? "on" : "off")); fprintf(ofile, " -l {<dB>|none} Specify a limit to the magnitude range of the diffuse-field\n"); - fprintf(ofile, " average (default: %.2f).\n", DEFAULT_LIMIT); + fprintf(ofile, " average (default: %.2f).\n", DefaultLimit); fprintf(ofile, " -w <points> Specify the size of the truncation window that's applied\n"); - fprintf(ofile, " after minimum-phase reconstruction (default: %u).\n", DEFAULT_TRUNCSIZE); + fprintf(ofile, " after minimum-phase reconstruction (default: %u).\n", DefaultTruncSize); fprintf(ofile, " -d {dataset| Specify the model used for calculating the head-delay timing\n"); fprintf(ofile, " sphere} values (default: %s).\n", ((DEFAULT_HEAD_MODEL == HM_DATASET) ? "dataset" : "sphere")); fprintf(ofile, " -c <radius> Use a customized head radius measured to-ear in meters.\n"); @@ -1320,14 +1320,14 @@ int main(int argc, char *argv[]) outName = "./oalsoft_hrtf_%r.mhr"; outRate = 0; chanMode = CM_AllowStereo; - fftSize = DEFAULT_FFTSIZE; - equalize = DEFAULT_EQUALIZE; - surface = DEFAULT_SURFACE; - limit = DEFAULT_LIMIT; + fftSize = DefaultFftSize; + equalize = DefaultEqualize; + surface = DefaultSurface; + limit = DefaultLimit; numThreads = 2; - truncSize = DEFAULT_TRUNCSIZE; + truncSize = DefaultTruncSize; model = DEFAULT_HEAD_MODEL; - radius = DEFAULT_CUSTOM_RADIUS; + radius = DefaultCustomRadius; farfield = false; while((opt=getopt(argc, argv, "r:maj:f:e:s:l:w:d:c:e:i:o:h")) != -1) @@ -1364,9 +1364,9 @@ int main(int argc, char *argv[]) case 'f': fftSize = static_cast<uint>(strtoul(optarg, &end, 10)); - if(end[0] != '\0' || (fftSize&(fftSize-1)) || fftSize < MIN_FFTSIZE || fftSize > MAX_FFTSIZE) + if(end[0] != '\0' || (fftSize&(fftSize-1)) || fftSize < MinFftSize || fftSize > MaxFftSize) { - fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected a power-of-two between %u to %u.\n", optarg, opt, MIN_FFTSIZE, MAX_FFTSIZE); + fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected a power-of-two between %u to %u.\n", optarg, opt, MinFftSize, MaxFftSize); exit(EXIT_FAILURE); } break; @@ -1401,9 +1401,9 @@ int main(int argc, char *argv[]) else { limit = strtod(optarg, &end); - if(end[0] != '\0' || limit < MIN_LIMIT || limit > MAX_LIMIT) + if(end[0] != '\0' || limit < MinLimit || limit > MaxLimit) { - fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %.0f to %.0f.\n", optarg, opt, MIN_LIMIT, MAX_LIMIT); + fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %.0f to %.0f.\n", optarg, opt, MinLimit, MaxLimit); exit(EXIT_FAILURE); } } @@ -1411,9 +1411,9 @@ int main(int argc, char *argv[]) case 'w': truncSize = static_cast<uint>(strtoul(optarg, &end, 10)); - if(end[0] != '\0' || truncSize < MIN_TRUNCSIZE || truncSize > MAX_TRUNCSIZE) + if(end[0] != '\0' || truncSize < MinTruncSize || truncSize > MaxTruncSize) { - fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %u to %u.\n", optarg, opt, MIN_TRUNCSIZE, MAX_TRUNCSIZE); + fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %u to %u.\n", optarg, opt, MinTruncSize, MaxTruncSize); exit(EXIT_FAILURE); } break; @@ -1432,9 +1432,9 @@ int main(int argc, char *argv[]) case 'c': radius = strtod(optarg, &end); - if(end[0] != '\0' || radius < MIN_CUSTOM_RADIUS || radius > MAX_CUSTOM_RADIUS) + if(end[0] != '\0' || radius < MinCustomRadius || radius > MaxCustomRadius) { - fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %.2f to %.2f.\n", optarg, opt, MIN_CUSTOM_RADIUS, MAX_CUSTOM_RADIUS); + fprintf(stderr, "\nError: Got unexpected value \"%s\" for option -%c, expected between %.2f to %.2f.\n", optarg, opt, MinCustomRadius, MaxCustomRadius); exit(EXIT_FAILURE); } break; diff --git a/utils/makemhr/makemhr.h b/utils/makemhr/makemhr.h index 3a105fc2..71c2e55b 100644 --- a/utils/makemhr/makemhr.h +++ b/utils/makemhr/makemhr.h @@ -9,35 +9,43 @@ // The maximum path length used when processing filenames. -#define MAX_PATH_LEN (256) +enum { MAX_PATH_LEN = 256u }; // The limit to the number of 'distances' listed in the data set definition. // Must be less than 256 -#define MAX_FD_COUNT (16) +enum { MAX_FD_COUNT = 16u }; // The limits to the number of 'elevations' listed in the data set definition. // Must be less than 256. -#define MIN_EV_COUNT (5) -#define MAX_EV_COUNT (181) +enum { + MIN_EV_COUNT = 5u, + MAX_EV_COUNT = 181u +}; // The limits for each of the 'azimuths' listed in the data set definition. // Must be less than 256. -#define MIN_AZ_COUNT (1) -#define MAX_AZ_COUNT (255) +enum { + MIN_AZ_COUNT = 1u, + MAX_AZ_COUNT = 255u +}; // The limits for the 'distance' from source to listener for each field in // the definition file. -#define MIN_DISTANCE (0.05) -#define MAX_DISTANCE (2.50) +inline constexpr double MIN_DISTANCE{0.05}; +inline constexpr double MAX_DISTANCE{2.50}; // The limits for the sample 'rate' metric in the data set definition and for // resampling. -#define MIN_RATE (32000) -#define MAX_RATE (96000) +enum { + MIN_RATE = 32000u, + MAX_RATE = 96000u +}; // The limits for the HRIR 'points' metric in the data set definition. -#define MIN_POINTS (16) -#define MAX_POINTS (8192) +enum { + MIN_POINTS = 16u, + MAX_POINTS = 8192u +}; using uint = unsigned int; diff --git a/utils/openal-info.c b/utils/openal-info.c index cb013098..669727a6 100644 --- a/utils/openal-info.c +++ b/utils/openal-info.c @@ -45,11 +45,11 @@ #define FUNCTION_CAST(T, ptr) (T)(ptr) #endif -#define MAX_WIDTH 80 +enum { MaxWidth = 80 }; static void printList(const char *list, char separator) { - size_t col = MAX_WIDTH, len; + size_t col = MaxWidth, len; const char *indent = " "; const char *next; @@ -71,7 +71,7 @@ static void printList(const char *list, char separator) else len = strlen(list); - if(len + col + 2 >= MAX_WIDTH) + if(len + col + 2 >= MaxWidth) { fprintf(stdout, "\n%s", indent); col = strlen(indent); @@ -393,7 +393,7 @@ static void printEFXInfo(ALCdevice *device) palFilteri(object, AL_FILTER_TYPE, filters[i]); if(alGetError() != AL_NO_ERROR) - memmove(current, next+1, strlen(next)); + memmove(current, next+1, strlen(next)); /* NOLINT(clang-analyzer-security.insecureAPI.*) */ else current = next+1; } @@ -412,7 +412,7 @@ static void printEFXInfo(ALCdevice *device) palEffecti(object, AL_EFFECT_TYPE, effects[i]); if(alGetError() != AL_NO_ERROR) - memmove(current, next+1, strlen(next)); + memmove(current, next+1, strlen(next)); /* NOLINT(clang-analyzer-security.insecureAPI.*) */ else current = next+1; } @@ -425,7 +425,7 @@ static void printEFXInfo(ALCdevice *device) palEffecti(object, AL_EFFECT_TYPE, dedeffects[i]); if(alGetError() != AL_NO_ERROR) - memmove(current, next+1, strlen(next)); + memmove(current, next+1, strlen(next)); /* NOLINT(clang-analyzer-security.insecureAPI.*) */ else current = next+1; } @@ -436,7 +436,7 @@ static void printEFXInfo(ALCdevice *device) { char *next = strchr(current, ','); assert(next != NULL); - memmove(current, next+1, strlen(next)); + memmove(current, next+1, strlen(next)); /* NOLINT(clang-analyzer-security.insecureAPI.*) */ } } printf("Supported effects:"); |