From 514ed1aa3250335ece75f0d0617c8206746f31d1 Mon Sep 17 00:00:00 2001 From: "J.A. de Jong - Redu-Sone B.V., ASCEE V.O.F" Date: Wed, 10 Jan 2024 12:26:38 +0100 Subject: [PATCH] Added physicalOutputQty for daq devices, added possibility to inspect from Python whether device has monitor. Added unit for equation in Qtys. Version bump 1.3.0 --- cpp_src/device/lasp_daq.cpp | 13 ++-------- cpp_src/device/lasp_daqconfig.cpp | 2 ++ cpp_src/device/lasp_deviceinfo.h | 36 ++++++++++++++++++++++++---- cpp_src/device/lasp_rtaudiodaq.cpp | 1 + cpp_src/device/lasp_uldaq.cpp | 4 ++++ cpp_src/pybind11/lasp_deviceinfo.cpp | 10 ++++++-- pyproject.toml | 2 +- python_src/lasp/lasp_common.py | 15 +++++++++++- 8 files changed, 64 insertions(+), 19 deletions(-) diff --git a/cpp_src/device/lasp_daq.cpp b/cpp_src/device/lasp_daq.cpp index 24374a2..7dfbdcd 100644 --- a/cpp_src/device/lasp_daq.cpp +++ b/cpp_src/device/lasp_daq.cpp @@ -44,22 +44,13 @@ Daq::Daq(const DeviceInfo &devinfo, const DaqConfiguration &config) : DaqConfiguration(config), DeviceInfo(devinfo) { DEBUGTRACE_ENTER; - if (duplexMode()) { - if (neninchannels() == 0) { - throw rte("Duplex mode enabled, but no input channels enabled"); - } - - if (nenoutchannels() == 0) { - throw rte("Duplex mode enabled, but no output channels enabled"); - } - } if(!duplexMode() && monitorOutput) { - throw rte("Output monitoring only allowed when running in duplex mode"); + throw rte("Duplex mode requires enabling both input and output channels. Please make sure at least one output channel is enabled, or disable hardware output loopback in DAQ configuration."); } if (!hasInternalOutputMonitor && monitorOutput) { throw rte( - "Output monitor flag set, but device does not have output monitor"); + "Output monitor flag set, but device does not have hardware output monitor."); } if (!config.match(devinfo)) { diff --git a/cpp_src/device/lasp_daqconfig.cpp b/cpp_src/device/lasp_daqconfig.cpp index 3cde4a0..8f503f3 100644 --- a/cpp_src/device/lasp_daqconfig.cpp +++ b/cpp_src/device/lasp_daqconfig.cpp @@ -35,12 +35,14 @@ DaqConfiguration::DaqConfiguration(const DeviceInfo &device) { us i = 0; for (auto &inch : inchannel_config) { inch.name = "Unnamed input channel " + std::to_string(i); + inch.rangeIndex = device.prefInputRangeIndex; i++; } i = 0; for (auto &outch : outchannel_config) { outch.name = "Unnamed output channel " + std::to_string(i); + outch.rangeIndex = device.prefOutputRangeIndex; i++; } diff --git a/cpp_src/device/lasp_deviceinfo.h b/cpp_src/device/lasp_deviceinfo.h index 7d3d8ad..ffd221a 100644 --- a/cpp_src/device/lasp_deviceinfo.h +++ b/cpp_src/device/lasp_deviceinfo.h @@ -68,14 +68,26 @@ public: us prefFramesPerBlockIndex = 0; /** - * @brief Available ranges for the input, i.e. +/- 1V and/or +/- 10 V etc. + * @brief Available ranges for the input, i.e. +/- 1V and/or +/- 10 V etc. */ dvec availableInputRanges; + /** - * @brief Its preffered range + * @brief Available ranges for the output, i.e. +/- 1V and/or +/- 10 V etc. + */ + dvec availableOutputRanges; + + /** + * @brief Its preffered input range */ int prefInputRangeIndex = 0; + /** + * @brief Its preffered output range + */ + int prefOutputRangeIndex = 0; + + /** * @brief The number of input channels available for the device */ @@ -125,13 +137,29 @@ public: bool duplexModeForced = false; /** - * @brief The physical quantity of the output signal. For 'normal' audio + * @brief Indicates whether the device is able to run in duplex mode. If false, + * devices cannot run in duplex mode, and the `duplexModeForced` flag is meaningless. + */ + bool hasDuplexMode = false; + + /** + * @brief The physical quantity of the input signal from DAQ. For 'normal' audio + * interfaces, this is typically a 'number' between +/- full scale. For some + * real DAQ devices however, the input quantity corresponds to a physical signal, + * such a Volts. + */ + + DaqChannel::Qty physicalInputQty = DaqChannel::Qty::Number; + + /** + * @brief The physical quantity of the output signal from DAQ. For 'normal' audio * devices, this is typically a 'number' between +/- full scale. For some - * devices however, the output quantity corresponds to a physical signal, + * real DAQ devices however, the input quantity corresponds to a physical signal, * such a Volts. */ DaqChannel::Qty physicalOutputQty = DaqChannel::Qty::Number; + /** * @brief String representation of DeviceInfo * diff --git a/cpp_src/device/lasp_rtaudiodaq.cpp b/cpp_src/device/lasp_rtaudiodaq.cpp index f797fa0..c6acbb9 100644 --- a/cpp_src/device/lasp_rtaudiodaq.cpp +++ b/cpp_src/device/lasp_rtaudiodaq.cpp @@ -99,6 +99,7 @@ void fillRtAudioDeviceInfo(DeviceInfoList &devinfolist) { d.ninchannels = devinfo.inputChannels; d.availableInputRanges = {1.0}; + d.availableOutputRanges = {1.0}; RtAudioFormat formats = devinfo.nativeFormats; if (formats & RTAUDIO_SINT8) { diff --git a/cpp_src/device/lasp_uldaq.cpp b/cpp_src/device/lasp_uldaq.cpp index 04c21e5..b1f215e 100644 --- a/cpp_src/device/lasp_uldaq.cpp +++ b/cpp_src/device/lasp_uldaq.cpp @@ -68,6 +68,7 @@ void fillUlDaqDeviceInfo(DeviceInfoList &devinfolist) { } devinfo.physicalOutputQty = DaqChannel::Qty::Voltage; + devinfo.physicalInputQty = DaqChannel::Qty::Voltage; devinfo.availableDataTypes.push_back( DataTypeDescriptor::DataType::dtype_fl64); @@ -79,7 +80,9 @@ void fillUlDaqDeviceInfo(DeviceInfoList &devinfolist) { devinfo.availableFramesPerBlock = {512, 1024, 2048, 4096, 8192}; devinfo.availableInputRanges = {1.0, 10.0}; + devinfo.availableOutputRanges = {10.0}; devinfo.prefInputRangeIndex = 0; + devinfo.prefOutputRangeIndex = 0; devinfo.ninchannels = 4; devinfo.noutchannels = 1; @@ -90,6 +93,7 @@ void fillUlDaqDeviceInfo(DeviceInfoList &devinfolist) { devinfo.hasInternalOutputMonitor = true; + devinfo.hasDuplexMode = true; devinfo.duplexModeForced = true; // Finally, this devinfo is pushed back in list diff --git a/cpp_src/pybind11/lasp_deviceinfo.cpp b/cpp_src/pybind11/lasp_deviceinfo.cpp index 6034fcc..880f065 100644 --- a/cpp_src/pybind11/lasp_deviceinfo.cpp +++ b/cpp_src/pybind11/lasp_deviceinfo.cpp @@ -29,6 +29,9 @@ void init_deviceinfo(py::module& m) { devinfo.def_readonly("availableInputRanges", &DeviceInfo::availableInputRanges); devinfo.def_readonly("prefInputRangeIndex", &DeviceInfo::prefInputRangeIndex); + devinfo.def_readonly("availableOutputRanges", + &DeviceInfo::availableOutputRanges); + devinfo.def_readonly("prefOutputRangeIndex", &DeviceInfo::prefOutputRangeIndex); devinfo.def_readonly("ninchannels", &DeviceInfo::ninchannels); devinfo.def_readonly("noutchannels", &DeviceInfo::noutchannels); @@ -36,7 +39,10 @@ void init_deviceinfo(py::module& m) { devinfo.def_readonly("hasInputACCouplingSwitch", &DeviceInfo::hasInputACCouplingSwitch); + devinfo.def_readonly("hasDuplexMode", &DeviceInfo::hasDuplexMode); + devinfo.def_readonly("duplexModeForced", &DeviceInfo::duplexModeForced); + devinfo.def_readonly("hasInternalOutputMonitor", &DeviceInfo::hasInternalOutputMonitor); + + devinfo.def_readonly("physicalInputQty", &DeviceInfo::physicalInputQty); devinfo.def_readonly("physicalOutputQty", &DeviceInfo::physicalOutputQty); - } - diff --git a/pyproject.toml b/pyproject.toml index 8126b17..7eca1e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ requires-python = ">=3.10" description = "Library for Acoustic Signal Processing" license = { "file" = "LICENSE" } authors = [{ "name" = "J.A. de Jong", "email" = "j.a.dejong@ascee.nl" }] -version = "1.2.0" +version = "1.3.0" keywords = ["DSP", "DAQ", "Signal processing"] diff --git a/python_src/lasp/lasp_common.py b/python_src/lasp/lasp_common.py index 2594b37..c0c69ba 100644 --- a/python_src/lasp/lasp_common.py +++ b/python_src/lasp/lasp_common.py @@ -62,8 +62,9 @@ class Qty: name: str # I.e.: Pascal unit_name: str - # I.e.: Pa + # I.e.: -, Pa, V unit_symb: str + # I.e.: ('dB SPL') <== tuple of possible level units level_unit: object # Contains a tuple of possible level names, including its reference value. @@ -92,6 +93,18 @@ class Qty: """ return self.cpp_enum.value + @property + def unit_symb_eq(self): + """Unit symbol to be used in equations + + Returns: + String: V, Pa, 1, + """ + if self.unit_symb != '-': + return self.unit_symb + else: + return '1' + @unique