diff --git a/CMakeLists.txt b/CMakeLists.txt index d28253b..3e53eb5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,8 @@ if(WIN32) set(DEFAULT_PORTAUDIO ON) set(DEFAULT_ULDAQ OFF) else() - set(DEFAULT_RTAUDIO ON) - set(DEFAULT_PORTAUDIO OFF) + set(DEFAULT_RTAUDIO OFF) + set(DEFAULT_PORTAUDIO ON) set(DEFAULT_ULDAQ ON) endif() diff --git a/cpp_src/CMakeLists.txt b/cpp_src/CMakeLists.txt index 53f939e..b661f49 100644 --- a/cpp_src/CMakeLists.txt +++ b/cpp_src/CMakeLists.txt @@ -38,16 +38,18 @@ pybind11_add_module(lasp_cpp MODULE lasp_cpp.cpp target_link_libraries(lasp_cpp PRIVATE lasp_device_lib lasp_dsp_lib ${OpenMP_CXX_LIBRARIES} ${LASP_FFT_LIBS} ${TARGET_OS_LINKLIBS}) -# Install the Python module -install(TARGETS lasp_cpp - EXCLUDE_FROM_ALL - COMPONENT python_modules - DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME}) -# Install the debug file for the Python module (Windows only) -if (WIN32) - install(FILES $ +if(DEFINED PY_BUILD_CMAKE_MODULE_NAME) + # Install the Python module + install(TARGETS lasp_cpp EXCLUDE_FROM_ALL COMPONENT python_modules - DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME} - OPTIONAL) -endif() + DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME}) + # Install the debug file for the Python module (Windows only) + if (WIN32) + install(FILES $ + EXCLUDE_FROM_ALL + COMPONENT python_modules + DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME} + OPTIONAL) + endif() +endif() \ No newline at end of file diff --git a/cpp_src/device/lasp_daq.cpp b/cpp_src/device/lasp_daq.cpp index 7dfbdcd..bb161f3 100644 --- a/cpp_src/device/lasp_daq.cpp +++ b/cpp_src/device/lasp_daq.cpp @@ -56,13 +56,29 @@ Daq::Daq(const DeviceInfo &devinfo, const DaqConfiguration &config) if (!config.match(devinfo)) { throw rte("DaqConfiguration does not match device info"); } - if (neninchannels(false) > devinfo.ninchannels) { - throw rte( - "Number of enabled input channels is higher than device capability"); + + { + const int hich = getHighestEnabledInChannel(); + if (hich + 1 > devinfo.ninchannels) + { + throw rte( + string("Highest of enabled input channel: ") + + to_string(hich) + + string(" is higher than device capability, which is: ") + + to_string(ninchannels) + "."); + } } - if (nenoutchannels() > devinfo.noutchannels) { - throw rte( - "Number of enabled output channels is higher than device capability"); + + { + const int hoch = getHighestEnabledOutChannel(); + if (hoch + 1 > devinfo.noutchannels) + { + throw rte( + string("Highest of enabled output channel: ") + + to_string(hoch) + + string(" is higher than device capability, which is: ") + + to_string(noutchannels) + "."); + } } } diff --git a/cpp_src/device/lasp_daqconfig.cpp b/cpp_src/device/lasp_daqconfig.cpp index 8f503f3..a614df2 100644 --- a/cpp_src/device/lasp_daqconfig.cpp +++ b/cpp_src/device/lasp_daqconfig.cpp @@ -56,10 +56,12 @@ DaqConfiguration::DaqConfiguration(const DeviceInfo &device) { } bool DaqConfiguration::match(const DeviceInfo &dev) const { + DEBUGTRACE_ENTER; return (dev.device_name == device_name && dev.api == api); } int DaqConfiguration::getHighestEnabledInChannel() const { + DEBUGTRACE_ENTER; for (int i = inchannel_config.size() - 1; i > -1; i--) { if (inchannel_config.at(i).enabled) return i; @@ -68,13 +70,15 @@ int DaqConfiguration::getHighestEnabledInChannel() const { } int DaqConfiguration::getHighestEnabledOutChannel() const { - for (us i = outchannel_config.size() - 1; i >= 0; i--) { + DEBUGTRACE_ENTER; + for (int i = outchannel_config.size() - 1; i > -1; i--) { if (outchannel_config.at(i).enabled) return i; } return -1; } int DaqConfiguration::getLowestEnabledInChannel() const { + DEBUGTRACE_ENTER; for (us i = 0; i < inchannel_config.size(); i++) { if (inchannel_config.at(i).enabled) return i; diff --git a/cpp_src/device/lasp_daqconfig.h b/cpp_src/device/lasp_daqconfig.h index 80eb5cb..d2f7cb0 100644 --- a/cpp_src/device/lasp_daqconfig.h +++ b/cpp_src/device/lasp_daqconfig.h @@ -148,7 +148,14 @@ const DaqApi rtaudioAsioApi("RtAudio Windows ASIO", LASP_RTAUDIO_APICODE, #endif #if LASP_HAS_PORTAUDIO == 1 const us LASP_PORTAUDIO_APICODE = 2; -const DaqApi portaudioApi("PortAudio Linux ALSA", LASP_PORTAUDIO_APICODE, 0); +const DaqApi portaudioALSAApi("PortAudio Linux ALSA", LASP_PORTAUDIO_APICODE, 0); +const DaqApi portaudioPulseApi("PortAudio Linux PulseAudio", LASP_PORTAUDIO_APICODE, 1); +const DaqApi portaudioASIOApi("PortAudio Windows ASIO", LASP_PORTAUDIO_APICODE, 2); +const DaqApi portaudioDSApi("PortAudio Windows DirectSound", LASP_PORTAUDIO_APICODE, 3); +const DaqApi portaudioWMMEApi("PortAudio Windows WMME", LASP_PORTAUDIO_APICODE, 4); +const DaqApi portaudioWASAPIApi("PortAudio Windows WASAPI", LASP_PORTAUDIO_APICODE, 5); +const DaqApi portaudioWDMKS("PortAudio Windows WDMKS", LASP_PORTAUDIO_APICODE, 6); +const DaqApi portaudioDirectSoundApi("PortAudio Windows DirectSound", LASP_PORTAUDIO_APICODE, 7); #endif class DeviceInfo; diff --git a/cpp_src/device/portaudio/lasp_portaudiodaq.cpp b/cpp_src/device/portaudio/lasp_portaudiodaq.cpp index fd1acd0..d6f61bc 100644 --- a/cpp_src/device/portaudio/lasp_portaudiodaq.cpp +++ b/cpp_src/device/portaudio/lasp_portaudiodaq.cpp @@ -39,6 +39,9 @@ public: { return std::make_unique(*this); } + OurPaDeviceInfo &operator=(const OurPaDeviceInfo &) = delete; + OurPaDeviceInfo(const OurPaDeviceInfo &) = default; + OurPaDeviceInfo(const PaDeviceInfo &o) : DeviceInfo(), _paDevInfo(o) {} }; void fillPortAudioDeviceInfo(DeviceInfoList &devinfolist) @@ -61,6 +64,11 @@ void fillPortAudioDeviceInfo(DeviceInfoList &devinfolist) cerr << "Error terminating PortAudio. Do not know what to do." << endl; } }); + const PaHostApiIndex apicount = Pa_GetHostApiCount(); + if (apicount < 0) + { + return; + } /* const PaDeviceInfo *deviceInfo; */ const int numDevices = Pa_GetDeviceCount(); if (numDevices < 0) @@ -76,13 +84,44 @@ void fillPortAudioDeviceInfo(DeviceInfoList &devinfolist) { throw rte("No device info struct returned"); } - OurPaDeviceInfo d; - d._paDevInfo = *deviceInfo; + OurPaDeviceInfo d(*deviceInfo); // We store the name in d.device_name d._paDevInfo.name = nullptr; - d.api = portaudioApi; d.device_name = deviceInfo->name; + const PaHostApiInfo *hostapiinfo = Pa_GetHostApiInfo(deviceInfo->hostApi); + if (hostapiinfo == nullptr) + { + throw std::runtime_error("Hostapi nullptr!"); + } + switch (hostapiinfo->type) + { + case paALSA: + d.api = portaudioALSAApi; + break; + case paASIO: + d.api = portaudioASIOApi; + break; + case paDirectSound: + d.api = portaudioDirectSoundApi; + break; + case paMME: + d.api = portaudioWMMEApi; + break; + case paWDMKS: + d.api = portaudioWDMKS; + break; + case paWASAPI: + d.api = portaudioWASAPIApi; + break; + case paPulseAudio: + d.api = portaudioPulseApi; + break; + default: + throw rte("Unimplemented portaudio API!"); + break; + } + d.availableDataTypes = {DataTypeDescriptor::DataType::dtype_int16, DataTypeDescriptor::DataType::dtype_int32, DataTypeDescriptor::DataType::dtype_fl32}; @@ -175,7 +214,7 @@ public: std::unique_ptr createPortAudioDevice(const DeviceInfo &devinfo, const DaqConfiguration &config) { - + DEBUGTRACE_ENTER; const OurPaDeviceInfo *_info = dynamic_cast(&devinfo); if (_info == nullptr) diff --git a/pyproject.toml b/pyproject.toml index 1235212..ef3e2c6 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.3.1" +version = "1.4.2" keywords = ["DSP", "DAQ", "Signal processing"] @@ -53,7 +53,7 @@ include = [ build_type = "Release" source_path = "." options = { "LASP_HAS_PORTAUDIO" = "ON", "LASP_HAS_RTAUDIO" = "OFF" } -build_args = ["-j12"] +build_args = ["-j"] install_components = ["python_modules"] [tool.py-build-cmake.editable]