First work on moving RtAudio Api back to C++.

This commit is contained in:
Anne de Jong 2020-10-04 22:29:54 +02:00
parent 5c6838c7e4
commit a73ef3d7a8
14 changed files with 335 additions and 32 deletions

4
.gitignore vendored
View File

@ -1,7 +1,6 @@
*.a
*.cxx
*.pyc
lasp_rtaudio.cxx
lasp_uldaq.cxx
dist
CMakeFiles
CMakeCache.txt
@ -20,6 +19,7 @@ test/test_bf
test/test_fft
test/test_math
test/test_workers
test/test_uldaq
doc
LASP.egg-info
lasp_octave_fir.*

View File

@ -1,5 +1,8 @@
cmake_minimum_required (VERSION 3.0)
# To allow linking to static libs from other directories
cmake_policy(SET CMP0079 NEW)
# This is used for code completion in vim
set(CMAKE_EXPORT_COMPILE_COMMANDS=ON)
project(LASP)
@ -72,6 +75,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
link_directories(C:\\mingw\\bin)
link_directories(..\\rtaudio)
link_directories(C:\\Users\\User\\Miniconda3)
add_definitions(-DHAS_RTAUDIO_WIN_WASAPI_API)
else()
set(win32 false)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -std=c11 \
@ -79,6 +83,14 @@ else()
include_directories(/usr/local/include/rtaudio)
link_directories(/usr/local/lib)
add_definitions(-DHAS_RTAUDIO)
add_definitions(-DHAS_RTAUDIO_PULSEAUDIO_API)
add_definitions(-DHAS_RTAUDIO_ALSA_API)
# This should become optional later on, and be added to the windows list as
# well.
add_definitions(-DHAS_ULDAQ)
add_definitions(-DHAS_ULDAQ_LINUX_API)
endif(CMAKE_SYSTEM_NAME STREQUAL "Windows")

View File

@ -1,21 +1,15 @@
include_directories(/usr/include/rtaudio)
add_library(cpp_daq lasp_cppuldaq.cpp)
add_library(cpp_daq lasp_cppdaq.cpp lasp_cppuldaq.cpp lasp_cpprtaudio.cpp)
set_source_files_properties(lasp_rtaudio.pyx PROPERTIES CYTHON_IS_CXX TRUE)
set_source_files_properties(lasp_uldaq.pyx PROPERTIES CYTHON_IS_CXX TRUE)
set_source_files_properties(lasp_rtaudio.cxx PROPERTIES COMPILE_FLAGS
set_source_files_properties(lasp_daq.pyx PROPERTIES CYTHON_IS_CXX TRUE)
set_source_files_properties(lasp_daq.cxx PROPERTIES COMPILE_FLAGS
"${CMAKE_CXX_FLAGS} ${CYTHON_EXTRA_CXX_FLAGS}")
cython_add_module(lasp_rtaudio lasp_rtaudio.pyx)
cython_add_module(lasp_uldaq lasp_uldaq.pyx)
cython_add_module(lasp_daq lasp_daq.pyx)
target_link_libraries(lasp_rtaudio pthread rtaudio)
target_link_libraries(lasp_uldaq cpp_daq uldaq pthread)
target_link_libraries(lasp_daq cpp_daq uldaq rtaudio pthread)
if(win32)
target_link_libraries(lasp_rtaudio python37)
target_link_libraries(lasp_uldaq python37)
target_link_libraries(lasp_daq python37)
endif(win32)
add_executable(test_uldaq test_uldaq.cpp)
target_link_libraries(test_uldaq cpp_daq uldaq pthread)

View File

@ -1,6 +1,5 @@
#!/usr/bin/python3
from .lasp_daqconfig import *
from .lasp_avtype import *
from .lasp_rtaudio import *
from .lasp_uldaq import *
from .lasp_daq import *

View File

@ -0,0 +1,92 @@
#include "lasp_cppdaq.h"
#define MAX_DEV_COUNT_PER_API 20
#ifdef HAS_ULDAQ_LINUX_API
void fillUlDaqDeviceInfo(vector<DeviceInfo>& devinfolist) {
UlError err;
unsigned int numdevs = MAX_DEV_COUNT_PER_API;
unsigned deviceno;
DaqDeviceDescriptor devdescriptors[MAX_DEV_COUNT_PER_API];
DaqDeviceDescriptor descriptor;
DaqDeviceInterface interfaceType = ANY_IFC;
err = ulGetDaqDeviceInventory(interfaceType,
devdescriptors,
&numdevs);
if(err != ERR_NO_ERROR)
throw std::runtime_error("Device inventarization failed");
for(unsigned i =0; i<numdevs; i++) {
descriptor = devdescriptors[i];
DeviceInfo devinfo;
devinfo.api = uldaqapi;
string name, interface;
if(string(descriptor.productName) == "DT9837A") {
if(descriptor.devInterface == USB_IFC) {
name = "USB - ";
} else if(descriptor.devInterface == BLUETOOTH_IFC) {
/* devinfo. */
name = "Bluetooth - ";
} else if(descriptor.devInterface == ETHERNET_IFC) {
/* devinfo. */
name = "Ethernet - ";
}
name += string(descriptor.productName) + " ";
name += string(descriptor.uniqueId);
devinfo.name = name;
devinfo.devindex = i;
devinfo.availableDataTypes.push_back(dtype_fl64);
devinfo.ninchannels = 4;
devinfo.noutchannels = 1;
devinfo.availableSampleRates.push_back(10000);
devinfo.availableSampleRates.push_back(12000);
devinfo.availableSampleRates.push_back(20000);
devinfo.availableSampleRates.push_back(24000);
devinfo.availableSampleRates.push_back(32000);
devinfo.availableSampleRates.push_back(48000);
devinfo.availableSampleRates.push_back(51000);
devinfo.prefSampleRateIndex = 5;
devinfo.prefSampleRate = 48000;
devinfo.hasInputIEPE = true;
devinfo.hasInputACCouplingSwitch = true;
devinfo.hasInputTrigger = true;
devinfolist.push_back(devinfo);
}
}
}
#endif
vector<DeviceInfo> DaqDevices::getDeviceInfo() {
vector<DeviceInfo> devs;
#ifdef HAS_ULDAQ_LINUX_API
fillUlDaqDeviceInfo(devs);
#endif
#ifdef HAS_RTAUDIO_ALSA_API
#endif
#ifdef HAS_RTAUDIO_PULSEAUDIO_API
#endif
#ifdef HAS_RTAUDIO_WIN_WASAPI_API
#endif
return devs;
}
Daq* DaqDevices::createDevice(const DeviceInfo&) {
return NULL;
}

View File

@ -1,18 +1,122 @@
#ifndef LAP_CPPDAQ_H
#define LAP_CPPDAQ_H
#ifndef LASP_CPPDAQ_H
#define LASP_CPPDAQ_H
#ifdef HAS_RTAUDIO
#include <RtAudio.h>
#endif
#ifdef HAS_ULDAQ
#include <uldaq.h>
#endif
#include "lasp_cppqueue.h"
#include "vector"
#include "string"
using std::vector;
using std::string;
class DataType {
public:
const string name;
unsigned sw;
bool is_floating;
DataType(const char* name,unsigned sw,bool is_floating):
name(name),
sw(sw),
is_floating(is_floating) {}
};
const DataType dtype_fl64("64-bits floating point",4,true);
const DataType dtype_int8("8-bits integers",1,false);
const DataType dtype_int16("16-bits integers",2,false);
const DataType dtype_int32("32-bits integers",4,false);
const std::vector<DataType> dataTypes = {
dtype_int8,
dtype_int16,
dtype_int32,
dtype_fl64,
};
class DaqApi {
public:
string apiname = "";
unsigned apicode = 0;
unsigned api_specific_subcode = 0;
DaqApi(string apiname,
unsigned apicode,
unsigned api_specific_subcode=0):
apiname(apiname),
apicode(apicode),
api_specific_subcode(api_specific_subcode) {}
DaqApi(){}
};
#ifdef HAS_ULDAQ_LINUX_API
const DaqApi uldaqapi = DaqApi("UlDaq", 0);
#endif
const vector<DaqApi> compiledApis = {
#ifdef HAS_ULDAQ_LINUX_API
uldaqapi,
#endif
#ifdef HAS_RTAUDIO_ALSA_API
DaqApi("RtAudio Linux ALSA", 1, RtAudio::Api::LINUX_ALSA),
#endif
#ifdef HAS_RTAUDIO_PULSEAUDIO_API
DaqApi("RtAudio Linux Pulseaudio",2, RtAudio::Api::LINUX_PULSE),
#endif
#ifdef HAS_RTAUDIO_WIN_WASAPI_API
DaqApi("RtAudio Windows Wasapi", 3, RtAudio::Api::WINDOWS_WASAPI),
#endif
};
// Structure containing device info parameters
class DeviceInfo {
public:
DaqApi api;
string name = "";
unsigned devindex;
vector<DataType> availableDataTypes;
vector<double> availableSampleRates;
unsigned prefSampleRateIndex = 0;
double prefSampleRate = 0;
unsigned ninchannels =0;
unsigned noutchannels =0;
bool hasInputIEPE = false;
bool hasInputACCouplingSwitch = false;
bool hasInputTrigger = false;
};
class Daq;
class DaqDevices {
public:
static vector<DeviceInfo> getDeviceInfo();
static Daq* createDevice(const DeviceInfo&);
};
class Daq{
public:
virtual void start(
SafeQueue<double*> *inqueue,
SafeQueue<double*> *outqueue) = 0;
SafeQueue<void*> *inqueue,
SafeQueue<void*> *outqueue) = 0;
virtual void stop() = 0;
virtual double samplerate() const = 0;
virtual DataType getDataType() const = 0;
virtual ~Daq() {};
};
#endif // LAP_CPPDAQ_H
#endif // LASP_CPPDAQ_H

View File

@ -0,0 +1,74 @@
#ifndef RTAUDIO_H
#define RTAUDIO_H
#include "lasp_cppqueue.h"
#include "lasp_cppdaq.h"
#include <algorithm>
#include <vector>
#include <mutex>
#include <atomic>
#include <thread>
using std::vector;
using std::atomic;
typedef vector<bool> boolvec;
typedef unsigned int us;
class RtA: public Daq {h
us samplesPerBlock;
double _samplerate;
boolvec inChannels;
boolvec high_range;
boolvec outChannels;
bool monitorOutput;
atomic<bool> stopThread;
DaqDeviceHandle handle = 0;
std::thread* thread = NULL;
mutable std::mutex mutex;
SafeQueue<double*> *inqueue = NULL;
SafeQueue<double*> *outqueue = NULL;
double* inbuffer = NULL;
double* outbuffer = NULL;
public:
double samplerate() const {return this->_samplerate;}
DT9837A(
us samplesPerBlock,
boolvec& inChannels,
boolvec& outChannels,
double samplerate,
bool monitorOutput,
us device_no = 0
);
DT9837A(const DT9837A&) = delete;
~DT9837A();
void setIEPEEnabled(boolvec& config);
// Coupling_ac: true, means AC coupling, false means DC coupling
void setACCouplingMode(boolvec& coupling_ac);
void setInputRange(boolvec& high_range);
us neninchannels() const;
us nenoutchannels() const;
bool isRunning() const { return bool(thread); }
virtual void start(
SafeQueue<double*> *inqueue,
SafeQueue<double*> *outqueue) final;
virtual void stop() final;
friend void threadfcn(DT9837A*);
};
#endif // RTAUDIO_H

View File

@ -1,5 +1,5 @@
#ifndef ULDAQ_THREAD_H
#define ULDAQ_THREAD_H
#ifndef ULDAQ_H
#define ULDAQ_H
#include "lasp_cppqueue.h"
#include "lasp_cppdaq.h"
#include <uldaq.h>
@ -59,8 +59,8 @@ class DT9837A: public Daq {
bool isRunning() const { return bool(thread); }
virtual void start(
SafeQueue<double*> *inqueue,
SafeQueue<double*> *outqueue) final;
SafeQueue<void*> *inqueue,
SafeQueue<void*> *outqueue) final;
virtual void stop() final;
@ -68,6 +68,6 @@ class DT9837A: public Daq {
friend void threadfcn(DT9837A*);
};
#endif // ULDAQ_THREAD_H
#endif // ULDAQ_H

View File

@ -9,10 +9,30 @@ Data Acquistiion (DAQ) device descriptors, and the DAQ devices themselves
"""
from dataclasses import dataclass, field
from dataclasses_json import dataclass_json
from ..lasp_common import lasp_shelve, Qty, SIQtys
from typing import List
from dataclasses_json import dataclass_json
from ..lasp_common import Qty, SIQtys, lasp_shelve
@dataclass
class DAQApi:
backendname: str
apiname: str
internal_nr: int
def description(self):
return self.backendname + ' - ' + self.apiname
class DAQApis:
apis = []
@staticmethod
def addApi(api):
DAQApis.apis.append(api)
class InputMode:
differential = 'Differential'
@ -20,16 +40,19 @@ class InputMode:
pseudo_differential = 'Pseudo-differential'
undefined = 'Undefined'
class CouplingMode:
ac = 'AC'
dc = 'DC'
undefined = 'Undefined'
class Range:
oneV = '+/- 1 V'
tenV = '+/- 10 V'
undefined = 'Undefined'
@dataclass
class DeviceInfo:
api: int

View File

@ -1,9 +1,14 @@
include_directories(${CMAKE_SOURCE_DIR}/lasp/c)
include_directories(${CMAKE_SOURCE_DIR}/lasp/device)
add_executable(test_bf test_bf.c)
add_executable(test_workers test_workers.c)
add_executable(test_fft test_fft.c)
add_executable(test_math test_math.c)
target_link_libraries(test_bf lasp_lib)
target_link_libraries(test_fft lasp_lib pthread)
target_link_libraries(test_workers lasp_lib pthread)
target_link_libraries(test_math lasp_lib pthread)
add_executable(test_uldaq test_uldaq.cpp)
target_link_libraries(test_uldaq cpp_daq uldaq pthread)

View File

@ -22,8 +22,8 @@ int main() {
true // monitor Output
);
SafeQueue<double*> inqueue;
SafeQueue<double*> outqueue;
SafeQueue<void*> inqueue;
SafeQueue<void*> outqueue;
double totalTime = 5;
double t = 0;
@ -52,7 +52,7 @@ int main() {
daq.stop();
while(!inqueue.empty()) {
double* buf = inqueue.dequeue();
double* buf = (double*) inqueue.dequeue();
for(us i=0;i<samplesPerBlock;i++) {
for(us ch=0;ch<daq.neninchannels();ch++) {
cout << buf[ch*samplesPerBlock+i] << " ";
@ -62,7 +62,7 @@ int main() {
free(buf);
}
while(!outqueue.empty()){
double* dat = outqueue.dequeue();
void* dat = outqueue.dequeue();
free(dat);
}