Bugfix in channel counter for getHighestEnabledOutChannel, added Api -subapis for Portaudio backend. Switch to defaulting Portaudio as audio backend. Added PulseAudio as extra sub-api to default compile in portaudio
All checks were successful
Building, testing and releasing LASP if it has a tag / Build-Test-Ubuntu (push) Successful in 3m2s
Building, testing and releasing LASP if it has a tag / Release-Ubuntu (push) Has been skipped

This commit is contained in:
Anne de Jong 2024-01-25 15:31:53 +01:00
parent c713806bbe
commit 6b337df2a9
7 changed files with 95 additions and 27 deletions

View File

@ -13,8 +13,8 @@ if(WIN32)
set(DEFAULT_PORTAUDIO ON) set(DEFAULT_PORTAUDIO ON)
set(DEFAULT_ULDAQ OFF) set(DEFAULT_ULDAQ OFF)
else() else()
set(DEFAULT_RTAUDIO ON) set(DEFAULT_RTAUDIO OFF)
set(DEFAULT_PORTAUDIO OFF) set(DEFAULT_PORTAUDIO ON)
set(DEFAULT_ULDAQ ON) set(DEFAULT_ULDAQ ON)
endif() endif()

View File

@ -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 target_link_libraries(lasp_cpp PRIVATE lasp_device_lib lasp_dsp_lib
${OpenMP_CXX_LIBRARIES} ${LASP_FFT_LIBS} ${TARGET_OS_LINKLIBS}) ${OpenMP_CXX_LIBRARIES} ${LASP_FFT_LIBS} ${TARGET_OS_LINKLIBS})
# Install the Python module if(DEFINED PY_BUILD_CMAKE_MODULE_NAME)
install(TARGETS lasp_cpp # Install the Python module
EXCLUDE_FROM_ALL install(TARGETS lasp_cpp
COMPONENT python_modules
DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME})
# Install the debug file for the Python module (Windows only)
if (WIN32)
install(FILES $<TARGET_PDB_FILE:_add_module>
EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL
COMPONENT python_modules COMPONENT python_modules
DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME} DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME})
OPTIONAL) # Install the debug file for the Python module (Windows only)
if (WIN32)
install(FILES $<TARGET_PDB_FILE:_add_module>
EXCLUDE_FROM_ALL
COMPONENT python_modules
DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME}
OPTIONAL)
endif()
endif() endif()

View File

@ -56,13 +56,29 @@ Daq::Daq(const DeviceInfo &devinfo, const DaqConfiguration &config)
if (!config.match(devinfo)) { if (!config.match(devinfo)) {
throw rte("DaqConfiguration does not match device info"); 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) + ".");
}
} }
} }

View File

@ -56,10 +56,12 @@ DaqConfiguration::DaqConfiguration(const DeviceInfo &device) {
} }
bool DaqConfiguration::match(const DeviceInfo &dev) const { bool DaqConfiguration::match(const DeviceInfo &dev) const {
DEBUGTRACE_ENTER;
return (dev.device_name == device_name && dev.api == api); return (dev.device_name == device_name && dev.api == api);
} }
int DaqConfiguration::getHighestEnabledInChannel() const { int DaqConfiguration::getHighestEnabledInChannel() const {
DEBUGTRACE_ENTER;
for (int i = inchannel_config.size() - 1; i > -1; i--) { for (int i = inchannel_config.size() - 1; i > -1; i--) {
if (inchannel_config.at(i).enabled) if (inchannel_config.at(i).enabled)
return i; return i;
@ -68,13 +70,15 @@ int DaqConfiguration::getHighestEnabledInChannel() const {
} }
int DaqConfiguration::getHighestEnabledOutChannel() 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) if (outchannel_config.at(i).enabled)
return i; return i;
} }
return -1; return -1;
} }
int DaqConfiguration::getLowestEnabledInChannel() const { int DaqConfiguration::getLowestEnabledInChannel() const {
DEBUGTRACE_ENTER;
for (us i = 0; i < inchannel_config.size(); i++) { for (us i = 0; i < inchannel_config.size(); i++) {
if (inchannel_config.at(i).enabled) if (inchannel_config.at(i).enabled)
return i; return i;

View File

@ -148,7 +148,14 @@ const DaqApi rtaudioAsioApi("RtAudio Windows ASIO", LASP_RTAUDIO_APICODE,
#endif #endif
#if LASP_HAS_PORTAUDIO == 1 #if LASP_HAS_PORTAUDIO == 1
const us LASP_PORTAUDIO_APICODE = 2; 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 #endif
class DeviceInfo; class DeviceInfo;

View File

@ -39,6 +39,9 @@ public:
{ {
return std::make_unique<OurPaDeviceInfo>(*this); return std::make_unique<OurPaDeviceInfo>(*this);
} }
OurPaDeviceInfo &operator=(const OurPaDeviceInfo &) = delete;
OurPaDeviceInfo(const OurPaDeviceInfo &) = default;
OurPaDeviceInfo(const PaDeviceInfo &o) : DeviceInfo(), _paDevInfo(o) {}
}; };
void fillPortAudioDeviceInfo(DeviceInfoList &devinfolist) void fillPortAudioDeviceInfo(DeviceInfoList &devinfolist)
@ -61,6 +64,11 @@ void fillPortAudioDeviceInfo(DeviceInfoList &devinfolist)
cerr << "Error terminating PortAudio. Do not know what to do." << endl; cerr << "Error terminating PortAudio. Do not know what to do." << endl;
} }); } });
const PaHostApiIndex apicount = Pa_GetHostApiCount();
if (apicount < 0)
{
return;
}
/* const PaDeviceInfo *deviceInfo; */ /* const PaDeviceInfo *deviceInfo; */
const int numDevices = Pa_GetDeviceCount(); const int numDevices = Pa_GetDeviceCount();
if (numDevices < 0) if (numDevices < 0)
@ -76,13 +84,44 @@ void fillPortAudioDeviceInfo(DeviceInfoList &devinfolist)
{ {
throw rte("No device info struct returned"); throw rte("No device info struct returned");
} }
OurPaDeviceInfo d; OurPaDeviceInfo d(*deviceInfo);
d._paDevInfo = *deviceInfo;
// We store the name in d.device_name // We store the name in d.device_name
d._paDevInfo.name = nullptr; d._paDevInfo.name = nullptr;
d.api = portaudioApi;
d.device_name = deviceInfo->name; 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, d.availableDataTypes = {DataTypeDescriptor::DataType::dtype_int16,
DataTypeDescriptor::DataType::dtype_int32, DataTypeDescriptor::DataType::dtype_int32,
DataTypeDescriptor::DataType::dtype_fl32}; DataTypeDescriptor::DataType::dtype_fl32};
@ -175,7 +214,7 @@ public:
std::unique_ptr<Daq> createPortAudioDevice(const DeviceInfo &devinfo, std::unique_ptr<Daq> createPortAudioDevice(const DeviceInfo &devinfo,
const DaqConfiguration &config) const DaqConfiguration &config)
{ {
DEBUGTRACE_ENTER;
const OurPaDeviceInfo *_info = const OurPaDeviceInfo *_info =
dynamic_cast<const OurPaDeviceInfo *>(&devinfo); dynamic_cast<const OurPaDeviceInfo *>(&devinfo);
if (_info == nullptr) if (_info == nullptr)

View File

@ -5,7 +5,7 @@ requires-python = ">=3.10"
description = "Library for Acoustic Signal Processing" description = "Library for Acoustic Signal Processing"
license = { "file" = "LICENSE" } license = { "file" = "LICENSE" }
authors = [{ "name" = "J.A. de Jong", "email" = "j.a.dejong@ascee.nl" }] 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"] keywords = ["DSP", "DAQ", "Signal processing"]
@ -53,7 +53,7 @@ include = [
build_type = "Release" build_type = "Release"
source_path = "." source_path = "."
options = { "LASP_HAS_PORTAUDIO" = "ON", "LASP_HAS_RTAUDIO" = "OFF" } options = { "LASP_HAS_PORTAUDIO" = "ON", "LASP_HAS_RTAUDIO" = "OFF" }
build_args = ["-j12"] build_args = ["-j"]
install_components = ["python_modules"] install_components = ["python_modules"]
[tool.py-build-cmake.editable] [tool.py-build-cmake.editable]