Split up indatahandler with python callback in part and part that calls the Python function. Threading is now handled using a thread pool. Some bugfixes
This commit is contained in:
parent
1e8b18aabe
commit
c75f0dddc5
@ -1,3 +1,4 @@
|
||||
#define DEBUGTRACE_ENABLED
|
||||
#include "debugtrace.hpp"
|
||||
#include "lasp_daqconfig.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* #define DEBUGTRACE_ENABLED */
|
||||
#define DEBUGTRACE_ENABLED
|
||||
#include "debugtrace.hpp"
|
||||
|
||||
#include "lasp_daqconfig.h"
|
||||
@ -7,8 +7,6 @@
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
#define MAX_DEV_COUNT_PER_API 20
|
||||
|
||||
using std::vector;
|
||||
|
||||
vector<DaqApi> DaqApi::getAvailableApis() {
|
||||
|
@ -1,6 +1,8 @@
|
||||
#define DEBUGTRACE_ENABLED
|
||||
#include "debugtrace.hpp"
|
||||
|
||||
#include "lasp_rtaudiodaq.h"
|
||||
#if LASP_HAS_RTAUDIO == 1
|
||||
#include "debugtrace.hpp"
|
||||
#include "lasp_daq.h"
|
||||
#include <RtAudio.h>
|
||||
#include <atomic>
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "lasp_streammgr.h"
|
||||
#define DEBUGTRACE_ENABLED
|
||||
#include "debugtrace.hpp"
|
||||
#include "lasp_thread.h"
|
||||
#include "lasp_streammgr.h"
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <functional>
|
||||
@ -37,6 +39,7 @@ InDataHandler::~InDataHandler() {
|
||||
StreamMgr &StreamMgr::getInstance() {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
getPool();
|
||||
static StreamMgr mgr;
|
||||
return mgr;
|
||||
}
|
||||
@ -198,6 +201,29 @@ void StreamMgr::startStream(const DeviceInfo &devinfo,
|
||||
_outputStream = std::move(daq);
|
||||
}
|
||||
}
|
||||
void StreamMgr::stopStream(const StreamType t) {
|
||||
switch (t) {
|
||||
case (StreamType::input): {
|
||||
if (!_inputStream) {
|
||||
throw std::runtime_error("Input stream is not running");
|
||||
}
|
||||
_inputStream = nullptr;
|
||||
} break;
|
||||
case (StreamType::output): {
|
||||
if (_inputStream && _inputStream->duplexMode()) {
|
||||
_inputStream = nullptr;
|
||||
} else {
|
||||
if (!_outputStream) {
|
||||
throw std::runtime_error("Output stream is not running");
|
||||
}
|
||||
_outputStream = nullptr;
|
||||
} // end else
|
||||
} break;
|
||||
default:
|
||||
throw std::runtime_error("BUG");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void StreamMgr::addInDataHandler(InDataHandler &handler) {
|
||||
std::scoped_lock<std::mutex> lck(_inDataHandler_mtx);
|
||||
|
@ -155,7 +155,7 @@ public:
|
||||
*
|
||||
* @param stype The stream type to stop.
|
||||
*/
|
||||
void stopStream(StreamType stype);
|
||||
void stopStream(const StreamType stype);
|
||||
|
||||
/**
|
||||
* @brief Stop and delete all streams. Also called on destruction of the
|
||||
|
@ -11,12 +11,15 @@ set(lasp_dsp_files
|
||||
lasp_thread.cpp
|
||||
lasp_timebuffer.cpp
|
||||
lasp_slm.cpp
|
||||
lasp_threadedindatahandler.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
add_library(lasp_dsp_lib STATIC ${lasp_dsp_files})
|
||||
target_compile_definitions(lasp_dsp_lib PUBLIC "-DARMA_DONT_USE_WRAPPER")
|
||||
|
||||
target_link_libraries(lasp_dsp_lib PRIVATE ${BLAS_LIBRARIES})
|
||||
target_include_directories(lasp_dsp_lib INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_include_directories(lasp_dsp_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_include_directories(lasp_dsp_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../device)
|
||||
|
||||
|
@ -1,9 +1,25 @@
|
||||
#define DEBUGTRACE_ENABLED
|
||||
#include "lasp_thread.h"
|
||||
#include "BS_thread_pool.hpp"
|
||||
#include "debugtrace.hpp"
|
||||
#include <memory>
|
||||
|
||||
BS::thread_pool& getPool() {
|
||||
static BS::thread_pool pool;
|
||||
|
||||
return pool;
|
||||
/**
|
||||
* @brief It seems to work much better in cooperation with Pybind11 when this
|
||||
* singleton is implemented with a unique_ptr.
|
||||
*/
|
||||
std::unique_ptr<BS::thread_pool> _static_storage_threadpool;
|
||||
|
||||
void destroyThreadPool() {
|
||||
DEBUGTRACE_ENTER;
|
||||
_static_storage_threadpool = nullptr;
|
||||
}
|
||||
|
||||
BS::thread_pool &getPool() {
|
||||
/* DEBUGTRACE_ENTER; */
|
||||
if (!_static_storage_threadpool) {
|
||||
DEBUGTRACE_PRINT("Creating new thread pool");
|
||||
_static_storage_threadpool = std::make_unique<BS::thread_pool>();
|
||||
}
|
||||
return *_static_storage_threadpool;
|
||||
}
|
||||
|
@ -9,3 +9,11 @@
|
||||
* @return Thread pool ref.
|
||||
*/
|
||||
BS::thread_pool& getPool();
|
||||
|
||||
|
||||
/**
|
||||
* @brief The global thread pool is stored in a unique_ptr, so in normal C++
|
||||
* code the thread pool is deleted at the end of main(). However this does not
|
||||
* hold when LASP code is run
|
||||
*/
|
||||
void destroyThreadPool();
|
||||
|
65
src/lasp/dsp/lasp_threadedindatahandler.cpp
Normal file
65
src/lasp/dsp/lasp_threadedindatahandler.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#define DEBUGTRACE_ENABLED
|
||||
#include "lasp_threadedindatahandler.h"
|
||||
#include "debugtrace.hpp"
|
||||
#include "lasp_thread.h"
|
||||
#include <future>
|
||||
#include <thread>
|
||||
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
ThreadedInDataHandler::ThreadedInDataHandler(StreamMgr &mgr)
|
||||
: InDataHandler(mgr) {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
|
||||
// Initialize thread pool, if not already done
|
||||
getPool();
|
||||
}
|
||||
|
||||
bool ThreadedInDataHandler::inCallback(const DaqData &daqdata) {
|
||||
/* DEBUGTRACE_ENTER; */
|
||||
|
||||
if (!_lastCallbackResult) {
|
||||
return false;
|
||||
}
|
||||
dataqueue.push(daqdata);
|
||||
|
||||
auto &pool = getPool();
|
||||
|
||||
if (!_thread_running && (!_stopThread) && _lastCallbackResult) {
|
||||
pool.push_task(&ThreadedInDataHandler::threadFcn, this);
|
||||
}
|
||||
|
||||
return _lastCallbackResult;
|
||||
}
|
||||
|
||||
ThreadedInDataHandler::~ThreadedInDataHandler() {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
_stopThread = true;
|
||||
|
||||
// Then wait in steps for the thread to stop running.
|
||||
while (_thread_running) {
|
||||
std::this_thread::sleep_for(10us);
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadedInDataHandler::threadFcn() {
|
||||
|
||||
/* DEBUGTRACE_ENTER; */
|
||||
_thread_running = true;
|
||||
|
||||
DaqData d{};
|
||||
|
||||
if (dataqueue.pop(d) && !_stopThread) {
|
||||
|
||||
// Call inCallback_threaded
|
||||
if (inCallback_threaded(d) == false) {
|
||||
_lastCallbackResult = false;
|
||||
_thread_running = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_lastCallbackResult = true;
|
||||
_thread_running = false;
|
||||
}
|
36
src/lasp/dsp/lasp_threadedindatahandler.h
Normal file
36
src/lasp/dsp/lasp_threadedindatahandler.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include <boost/lockfree/spsc_queue.hpp>
|
||||
#include "lasp_streammgr.h"
|
||||
|
||||
const us RINGBUFFER_SIZE = 1024;
|
||||
|
||||
class ThreadedInDataHandler: public InDataHandler {
|
||||
/**
|
||||
* @brief The queue used to push elements to the handling thread.
|
||||
*/
|
||||
boost::lockfree::spsc_queue<DaqData,
|
||||
boost::lockfree::capacity<RINGBUFFER_SIZE>>
|
||||
dataqueue;
|
||||
|
||||
std::atomic<bool> _thread_running{false};
|
||||
std::atomic<bool> _stopThread{false};
|
||||
std::atomic<bool> _lastCallbackResult{true};
|
||||
|
||||
void threadFcn();
|
||||
|
||||
public:
|
||||
ThreadedInDataHandler(StreamMgr& mgr);
|
||||
~ThreadedInDataHandler();
|
||||
|
||||
/**
|
||||
* @brief Pushes a copy of the daqdata to the thread queue and returns
|
||||
*
|
||||
* @param daqdata the daq info to push
|
||||
*
|
||||
* @return true, to continue with sampling.
|
||||
*/
|
||||
virtual bool inCallback(const DaqData &daqdata) override;
|
||||
|
||||
virtual bool inCallback_threaded(const DaqData&) = 0;
|
||||
|
||||
};
|
@ -1,8 +1,8 @@
|
||||
#define DEBUGTRACE_ENABLED
|
||||
#include "debugtrace.hpp"
|
||||
#include "lasp_streammgr.h"
|
||||
#include "lasp_threadedindatahandler.h"
|
||||
#include <atomic>
|
||||
#include <boost/lockfree/policies.hpp>
|
||||
#include <boost/lockfree/spsc_queue.hpp>
|
||||
#include <chrono>
|
||||
#include <pybind11/buffer_info.h>
|
||||
#include <pybind11/cast.h>
|
||||
@ -17,8 +17,6 @@ using namespace std::literals::chrono_literals;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
const us RINGBUFFER_SIZE = 1024;
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
/**
|
||||
@ -30,7 +28,7 @@ namespace py = pybind11;
|
||||
*
|
||||
* @return Numpy array
|
||||
*/
|
||||
template <typename T> py::array_t<T> getPyArray(DaqData &d) {
|
||||
template <typename T> py::array_t<T> getPyArray(const DaqData &d) {
|
||||
// https://github.com/pybind/pybind11/issues/323
|
||||
//
|
||||
// When a valid object is passed as 'base', it tells pybind not to take
|
||||
@ -49,16 +47,17 @@ template <typename T> py::array_t<T> getPyArray(DaqData &d) {
|
||||
|
||||
return py::array_t<T>(
|
||||
py::array::ShapeContainer({d.nframes, d.nchannels}), // Shape
|
||||
//
|
||||
py::array::StridesContainer( // Strides
|
||||
{sizeof(T),
|
||||
sizeof(T) * d.nframes}), // Strides (in bytes) for each index
|
||||
|
||||
(T *)d.raw_ptr(), // Pointer to buffer
|
||||
py::array::StridesContainer( // Strides
|
||||
{sizeof(T),
|
||||
sizeof(T) * d.nframes}), // Strides (in bytes) for each index
|
||||
|
||||
reinterpret_cast<T *>(
|
||||
const_cast<DaqData &>(d).raw_ptr()), // Pointer to buffer
|
||||
|
||||
dummyDataOwner // As stated above, now Numpy does not take ownership of
|
||||
// the data pointer.
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,130 +65,79 @@ template <typename T> py::array_t<T> getPyArray(DaqData &d) {
|
||||
* buffer of sample data. The Python callback is called from a different
|
||||
* thread, using a Numpy argument as
|
||||
*/
|
||||
class PyIndataHandler : public InDataHandler {
|
||||
class PyIndataHandler : public ThreadedInDataHandler {
|
||||
/**
|
||||
* @brief The callback function that is called.
|
||||
*/
|
||||
py::function cb;
|
||||
/**
|
||||
* @brief The thread that is handling callbacks from the queue
|
||||
*/
|
||||
std::thread pythread;
|
||||
/**
|
||||
* @brief The queue used to push elements to the handling thread.
|
||||
*/
|
||||
boost::lockfree::spsc_queue<DaqData,
|
||||
boost::lockfree::capacity<RINGBUFFER_SIZE>>
|
||||
dataqueue;
|
||||
std::atomic<bool> stopThread{false};
|
||||
|
||||
public:
|
||||
public:
|
||||
PyIndataHandler(StreamMgr &mgr, py::function cb)
|
||||
: ThreadedInDataHandler(mgr), cb(cb) {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
/// TODO: Note that if start() throws an exception, which means that the
|
||||
/// destructor of PyIndataHandler is not called and the thread destructor
|
||||
/// calls terminate(). It is a kind of rude way to crash, but it is also
|
||||
/// *very* unlikely to happen, as start() does only add a reference to this
|
||||
/// handler to a list in the stream mgr.
|
||||
start();
|
||||
}
|
||||
~PyIndataHandler() {
|
||||
DEBUGTRACE_ENTER;
|
||||
stop();
|
||||
stopThread = true;
|
||||
if(pythread.joinable()) {
|
||||
pythread.join();
|
||||
}
|
||||
}
|
||||
PyIndataHandler(StreamMgr &mgr, py::function cb)
|
||||
: InDataHandler(mgr), cb(cb),
|
||||
pythread(&PyIndataHandler::threadfcn, this) {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
/// TODO: Note that if start() throws an exception, which means that the
|
||||
/// destructor of PyIndataHandler is not called and the thread destructor
|
||||
/// calls terminate(). It is a kind of rude way to crash, but it is also
|
||||
/// *very* unlikely to happen, as start() does only add a reference to this
|
||||
/// handler to a list in the stream mgr.
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads from the
|
||||
* @brief Reads from the buffer
|
||||
*/
|
||||
void threadfcn() {
|
||||
bool inCallback_threaded(const DaqData &d) {
|
||||
|
||||
/* DEBUGTRACE_ENTER; */
|
||||
|
||||
using DataType = DataTypeDescriptor::DataType;
|
||||
|
||||
DaqData d{};
|
||||
py::gil_scoped_acquire acquire;
|
||||
try {
|
||||
py::array binfo;
|
||||
switch (d.dtype) {
|
||||
case (DataType::dtype_int8):
|
||||
binfo = getPyArray<int8_t>(d);
|
||||
break;
|
||||
case (DataType::dtype_int16):
|
||||
binfo = getPyArray<int16_t>(d);
|
||||
break;
|
||||
case (DataType::dtype_int32):
|
||||
binfo = getPyArray<int32_t>(d);
|
||||
break;
|
||||
case (DataType::dtype_fl32):
|
||||
binfo = getPyArray<float>(d);
|
||||
break;
|
||||
case (DataType::dtype_fl64):
|
||||
binfo = getPyArray<double>(d);
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("BUG");
|
||||
} // End of switch
|
||||
|
||||
while (!stopThread) {
|
||||
if (dataqueue.pop(d)) {
|
||||
/* DEBUGTRACE_PRINT("pop() returned true"); */
|
||||
py::object bool_val = cb(binfo);
|
||||
bool res = bool_val.cast<bool>();
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
py::gil_scoped_acquire acquire;
|
||||
try {
|
||||
py::array binfo;
|
||||
switch (d.dtype) {
|
||||
case (DataType::dtype_int8):
|
||||
binfo = getPyArray<uint8_t>(d);
|
||||
break;
|
||||
case (DataType::dtype_int16):
|
||||
binfo = getPyArray<uint16_t>(d);
|
||||
break;
|
||||
case (DataType::dtype_int32):
|
||||
binfo = getPyArray<uint32_t>(d);
|
||||
break;
|
||||
case (DataType::dtype_fl32):
|
||||
binfo = getPyArray<float>(d);
|
||||
break;
|
||||
case (DataType::dtype_fl64):
|
||||
binfo = getPyArray<double>(d);
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("BUG");
|
||||
} // End of switch
|
||||
} catch (py::error_already_set &e) {
|
||||
cerr << "ERROR: Python raised exception from callback function: ";
|
||||
cerr << e.what() << endl;
|
||||
return false;
|
||||
|
||||
py::object bool_val = cb(binfo);
|
||||
bool res = bool_val.cast<bool>();
|
||||
if (!res)
|
||||
stopThread = true;
|
||||
|
||||
} catch (py::error_already_set &e) {
|
||||
cerr << "ERROR: Python raised exception from callback function: ";
|
||||
cerr << e.what() << endl;
|
||||
stopThread = true;
|
||||
|
||||
} catch (py::cast_error &e) {
|
||||
cerr << e.what() << endl;
|
||||
cerr << "ERROR: Python callback does not return boolean value."
|
||||
<< endl;
|
||||
stopThread = true;
|
||||
}
|
||||
}
|
||||
// When there is nothing to pop from the queue, just sleep for a some
|
||||
// time.
|
||||
else {
|
||||
std::this_thread::sleep_for(2ms);
|
||||
}
|
||||
} // end of while loop
|
||||
|
||||
} // end of threadfcn
|
||||
|
||||
/**
|
||||
* @brief Pushes a copy of the daqdata to the thread queuue and returns
|
||||
*
|
||||
* @param daqdata the daq info to push
|
||||
*
|
||||
* @return true, to continue with sampling.
|
||||
*/
|
||||
virtual bool inCallback(const DaqData &daqdata) override {
|
||||
/* DEBUGTRACE_ENTER; */
|
||||
if (!stopThread) {
|
||||
if (!dataqueue.push(daqdata)) {
|
||||
stopThread = true;
|
||||
cerr << "Pushing DaqData object failed. Probably the ringbuffer is "
|
||||
"full. Try reducing the load"
|
||||
<< endl;
|
||||
}
|
||||
} catch (py::cast_error &e) {
|
||||
cerr << e.what() << endl;
|
||||
cerr << "ERROR: Python callback does not return boolean value." << endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void init_datahandler(py::module &m) {
|
||||
py::class_<PyIndataHandler> h(m, "InDataHandler");
|
||||
|
||||
|
@ -18,7 +18,7 @@ void init_streammgr(py::module &m) {
|
||||
.export_values();
|
||||
|
||||
smgr.def("startStream", &StreamMgr::startStream);
|
||||
smgr.def("stopStream", &StreamMgr::startStream);
|
||||
smgr.def("stopStream", &StreamMgr::stopStream);
|
||||
smgr.def_static("getInstance", []() {
|
||||
return std::unique_ptr<StreamMgr, py::nodelete>(&StreamMgr::getInstance());
|
||||
});
|
||||
|
@ -3,6 +3,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"id": "b0d15138",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@ -12,27 +13,15 @@
|
||||
"make: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"make[1]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"\u001b[35m\u001b[1mConsolidate compiler generated dependencies of target lasp_dsp_lib\u001b[0m\n",
|
||||
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"[ 26%] Built target lasp_dsp_lib\n",
|
||||
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"\u001b[35m\u001b[1mScanning dependencies of target lasp_device_lib\u001b[0m\n",
|
||||
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"[ 31%] \u001b[32mBuilding CXX object src/lasp/device/CMakeFiles/lasp_device_lib.dir/lasp_rtaudiodaq.cpp.o\u001b[0m\n",
|
||||
"\u001b[01m\u001b[K/home/anne/wip/mycode/lasp/src/lasp/device/lasp_rtaudiodaq.cpp:\u001b[m\u001b[K In lambda function:\n",
|
||||
"\u001b[01m\u001b[K/home/anne/wip/mycode/lasp/src/lasp/device/lasp_rtaudiodaq.cpp:258:20:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kvariable ‘\u001b[01m\u001b[Kstat\u001b[m\u001b[K’ set but not used [\u001b[01;35m\u001b[K-Wunused-but-set-variable\u001b[m\u001b[K]\n",
|
||||
" 258 | StreamStatus \u001b[01;35m\u001b[Kstat\u001b[m\u001b[K = _streamStatus;\n",
|
||||
" | \u001b[01;35m\u001b[K^~~~\u001b[m\u001b[K\n",
|
||||
"\u001b[01m\u001b[K/home/anne/wip/mycode/lasp/src/lasp/device/lasp_rtaudiodaq.cpp:\u001b[m\u001b[K In member function ‘\u001b[01m\u001b[Kint RtAudioDaq::streamCallback(void*, void*, unsigned int, double, RtAudioStreamStatus)\u001b[m\u001b[K’:\n",
|
||||
"\u001b[01m\u001b[K/home/anne/wip/mycode/lasp/src/lasp/device/lasp_rtaudiodaq.cpp:250:36:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kunused parameter ‘\u001b[01m\u001b[KstreamTime\u001b[m\u001b[K’ [\u001b[01;35m\u001b[K-Wunused-parameter\u001b[m\u001b[K]\n",
|
||||
" 250 | unsigned int nFrames, \u001b[01;35m\u001b[Kdouble streamTime\u001b[m\u001b[K,\n",
|
||||
" | \u001b[01;35m\u001b[K~~~~~~~^~~~~~~~~~\u001b[m\u001b[K\n",
|
||||
"\u001b[35m\u001b[1mConsolidate compiler generated dependencies of target lasp_device_lib\u001b[0m\n",
|
||||
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"[ 63%] Built target lasp_device_lib\n",
|
||||
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"[ 68%] \u001b[32m\u001b[1mLinking CXX shared module lasp_cpp.cpython-38-x86_64-linux-gnu.so\u001b[0m\n",
|
||||
"\u001b[35m\u001b[1mConsolidate compiler generated dependencies of target lasp_cpp\u001b[0m\n",
|
||||
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
||||
"[100%] Built target lasp_cpp\n",
|
||||
"make[1]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
||||
@ -47,8 +36,20 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"id": "1787e24c",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"2022-07-20 22:04:50+0200 DebugTrace-cpp 2.0.0a2 (g++ 12.1.0)\n",
|
||||
"2022-07-20 22:04:50+0200 \n",
|
||||
"2022-07-20 22:04:50+0200 Enter fillUlDaqDeviceInfo (lasp_uldaq.cpp: 514)\n",
|
||||
"2022-07-20 22:04:51+0200 Leave fillUlDaqDeviceInfo (lasp_uldaq.cpp)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import lasp\n",
|
||||
"ds = lasp.DeviceInfo.getDeviceInfo()"
|
||||
@ -57,6 +58,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"id": "cb4ab7d8",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
@ -74,17 +76,26 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"id": "22ae99b1",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0: Camera Mono\n",
|
||||
"0: Monitor of Starship/Matisse HD Audio Controller Analog Stereo\n",
|
||||
"1: Starship/Matisse HD Audio Controller Analog Stereo\n",
|
||||
"2: Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] Digital Stereo (HDMI)\n",
|
||||
"3: Monitor of Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] Digital Stereo (HDMI)\n",
|
||||
"4: Monitor of Starship/Matisse HD Audio Controller Analog Stereo\n"
|
||||
"2: GP108 High Definition Audio Controller Digital Stereo (HDMI)\n",
|
||||
"3: Monitor of GP108 High Definition Audio Controller Digital Stereo (HDMI)\n",
|
||||
"4: default\n",
|
||||
"5: hw:HDA NVidia,3\n",
|
||||
"6: hw:HDA NVidia,7\n",
|
||||
"7: hw:HDA NVidia,8\n",
|
||||
"8: hw:HDA NVidia,9\n",
|
||||
"9: hw:HDA NVidia,10\n",
|
||||
"10: hw:HD-Audio Generic,0\n",
|
||||
"11: hw:HD-Audio Generic,1\n",
|
||||
"12: hw:HD-Audio Generic,2\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@ -97,6 +108,7 @@
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"id": "47385b02",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -107,56 +119,28 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": 59,
|
||||
"id": "d12f84b7",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"2"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Out channels: 2\n",
|
||||
"In channels: 0\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"d.noutchannels"
|
||||
"print('Out channels:',d.noutchannels)\n",
|
||||
"print('In channels:',d.ninchannels)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#daq = lasp.Daq.createDaq(d, config)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"2"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"d.ninchannels"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"execution_count": 52,
|
||||
"id": "902ce309",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -165,16 +149,38 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"execution_count": 55,
|
||||
"id": "b209294b",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"2022-07-20 22:07:02+0200 \n",
|
||||
"2022-07-20 22:07:02+0200 Enter createDaq (lasp_daq.cpp: 18)\n",
|
||||
"2022-07-20 22:07:02+0200 | Enter Daq (lasp_daq.cpp: 39)\n",
|
||||
"2022-07-20 22:07:02+0200 | Leave Daq (lasp_daq.cpp)\n",
|
||||
"2022-07-20 22:07:02+0200 | \n",
|
||||
"2022-07-20 22:07:02+0200 | Enter RtAudioDaq (lasp_rtaudiodaq.cpp: 131)\n",
|
||||
"2022-07-20 22:07:02+0200 | Leave RtAudioDaq (lasp_rtaudiodaq.cpp)\n",
|
||||
"2022-07-20 22:07:02+0200 Leave createDaq (lasp_daq.cpp)\n",
|
||||
"2022-07-20 22:07:02+0200 isInput = false\n",
|
||||
"2022-07-20 22:07:02+0200 isOutput = true\n",
|
||||
"2022-07-20 22:07:02+0200 \n",
|
||||
"2022-07-20 22:07:02+0200 Enter start (lasp_rtaudiodaq.cpp: 211)\n",
|
||||
"2022-07-20 22:07:02+0200 Leave start (lasp_rtaudiodaq.cpp)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"mgr.startStream(d, config)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"execution_count": 27,
|
||||
"id": "0830ffb5",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -183,7 +189,8 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 60,
|
||||
"id": "a7fddc19",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@ -192,26 +199,36 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"execution_count": 57,
|
||||
"id": "f4610574",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"sine = lasp.Sine(1000)"
|
||||
"sine = lasp.Sine(200)\n",
|
||||
"sine.setLevel(-20, True)\n",
|
||||
"mgr.setSiggen(sine)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 21,
|
||||
"id": "d11c7dae",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"mgr.setSiggen(sine)"
|
||||
]
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "0eeb2311",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
@ -225,7 +242,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.10"
|
||||
"version": "3.10.5"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
Loading…
Reference in New Issue
Block a user