Probable fix of memory leak
This commit is contained in:
parent
8fee46a41f
commit
4339ecdbc0
44
README.md
44
README.md
@ -36,20 +36,40 @@ in a sister repository in a later stage.
|
|||||||
If you have any question(s), please feel free to contact us: info@ascee.nl.
|
If you have any question(s), please feel free to contact us: info@ascee.nl.
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
# Building from source
|
||||||
|
|
||||||
### Compilation
|
## Dependencies
|
||||||
|
|
||||||
#### Archlinux
|
Optional dependencies, which can be turned ON/OFF using CMake:
|
||||||
|
|
||||||
|
- Build tools, including [http://cmake.org](CMake).
|
||||||
|
- FFTW (For really fast FFT's)
|
||||||
|
- libUlDAQ, for the Measurement Computing DT9837A USB DAQ box
|
||||||
|
- GNU Autotools, for compiling libUlDAQ
|
||||||
|
- RtAudio, for Audio DAQ backends
|
||||||
|
- Cython, for wrapping the C-code to Python.
|
||||||
|
- The following Python packages need also be available:
|
||||||
|
- `Scipy` (which includes Numpy). Install with `sudo apt install
|
||||||
|
python3-scipy`, or `pacman -S scipy`.
|
||||||
|
- `appdirs`, which can be grabbed from [https://pypi.org](Pypi)
|
||||||
|
|
||||||
|
## Installation of dependencies
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Compilation of LASP
|
||||||
|
|
||||||
|
### Archlinux
|
||||||
|
|
||||||
Compiling the code on Archlinux requires the following packages to be available:
|
Compiling the code on Archlinux requires the following packages to be available:
|
||||||
|
|
||||||
- openblas-lapack (AUR)
|
- openblas-lapack (AUR)
|
||||||
- Python 3.7
|
- Python>=3.7
|
||||||
- Numpy (Python-numpy)
|
- Numpy (Python-numpy)
|
||||||
- Cython
|
- Cython
|
||||||
|
|
||||||
#### Ubuntu / Linux Mint
|
### Ubuntu / Linux Mint
|
||||||
|
|
||||||
*Only tested with Linux Mint 18.04*, we require the following packages for
|
*Only tested with Linux Mint 18.04*, we require the following packages for
|
||||||
compilation:
|
compilation:
|
||||||
@ -62,17 +82,3 @@ compilation:
|
|||||||
- libopenblas-base
|
- libopenblas-base
|
||||||
- libopenblas-dev
|
- libopenblas-dev
|
||||||
|
|
||||||
#### Windows specific
|
|
||||||
|
|
||||||
Tested using a Anacond / Miniconda Python environment. Please first run the following command:
|
|
||||||
|
|
||||||
`conda install fftw`
|
|
||||||
|
|
||||||
in case you want the *FFTW* fft backend.
|
|
||||||
|
|
||||||
### Dependencies
|
|
||||||
|
|
||||||
#### Ubuntu / Linux Mint
|
|
||||||
|
|
||||||
*Only tested with Linux Mint 18.04*. The following Dependencies are required
|
|
||||||
for Ubuntu:
|
|
||||||
|
@ -40,91 +40,91 @@ class DT9837A : public Daq {
|
|||||||
|
|
||||||
us nFramesPerBlock;
|
us nFramesPerBlock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DT9837A(const DeviceInfo &devinfo, const DaqConfiguration &config)
|
DT9837A(const DeviceInfo &devinfo, const DaqConfiguration &config)
|
||||||
: Daq(devinfo, config) {
|
: Daq(devinfo, config) {
|
||||||
|
|
||||||
// Some sanity checks
|
// Some sanity checks
|
||||||
if (eninchannels.size() != 4) {
|
if (eninchannels.size() != 4) {
|
||||||
throw runtime_error("Invalid length of enabled inChannels vector");
|
throw runtime_error("Invalid length of enabled inChannels vector");
|
||||||
}
|
|
||||||
|
|
||||||
if (enoutchannels.size() != 1) {
|
|
||||||
throw runtime_error("Invalid length of enabled outChannels vector");
|
|
||||||
}
|
|
||||||
|
|
||||||
stopThread = false;
|
|
||||||
|
|
||||||
nFramesPerBlock = availableFramesPerBlock[framesPerBlockIndex];
|
|
||||||
|
|
||||||
if (nFramesPerBlock < 24 || nFramesPerBlock > 8192) {
|
|
||||||
throw runtime_error("Unsensible number of samples per block chosen");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (samplerate() < 10000 || samplerate() > 51000) {
|
|
||||||
throw runtime_error("Invalid sample rate");
|
|
||||||
}
|
|
||||||
|
|
||||||
DaqDeviceDescriptor devdescriptors[MAX_DEV_COUNT_PER_API];
|
|
||||||
DaqDeviceDescriptor descriptor;
|
|
||||||
DaqDeviceInterface interfaceType = ANY_IFC;
|
|
||||||
|
|
||||||
UlError err;
|
|
||||||
|
|
||||||
us numdevs = MAX_DEV_COUNT_PER_API;
|
|
||||||
err = ulGetDaqDeviceInventory(interfaceType, devdescriptors, (unsigned*) &numdevs);
|
|
||||||
if (err != ERR_NO_ERROR) {
|
|
||||||
throw runtime_error("Device inventarization failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((us) api_specific_devindex >= numdevs) {
|
|
||||||
throw runtime_error("Device number {deviceno} too high {err}. This could "
|
|
||||||
"happen when the device is currently not connected");
|
|
||||||
}
|
|
||||||
|
|
||||||
descriptor = devdescriptors[api_specific_devindex];
|
|
||||||
|
|
||||||
// get a handle to the DAQ device associated with the first descriptor
|
|
||||||
handle = ulCreateDaqDevice(descriptor);
|
|
||||||
|
|
||||||
if (handle == 0) {
|
|
||||||
throw runtime_error("Unable to create a handle to the specified DAQ "
|
|
||||||
"device. Is the device currently in use? Please make sure to set "
|
|
||||||
"the DAQ configuration in duplex mode if simultaneous input and "
|
|
||||||
"output is required.");
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ulConnectDaqDevice(handle);
|
|
||||||
if (err != ERR_NO_ERROR) {
|
|
||||||
showErr(err);
|
|
||||||
ulReleaseDaqDevice(handle);
|
|
||||||
handle = 0;
|
|
||||||
throw runtime_error("Unable to connect to device: {err}");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (us ch = 0; ch < 4; ch++) {
|
|
||||||
|
|
||||||
err = ulAISetConfigDbl(handle, AI_CFG_CHAN_SENSOR_SENSITIVITY, ch, 1.0);
|
|
||||||
showErr(err);
|
|
||||||
if (err != ERR_NO_ERROR) {
|
|
||||||
throw runtime_error("Fatal: could normalize channel sensitivity");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CouplingMode cm = inputACCouplingMode[ch] ? CM_AC : CM_DC;
|
if (enoutchannels.size() != 1) {
|
||||||
err = ulAISetConfig(handle, AI_CFG_CHAN_COUPLING_MODE, ch, cm);
|
throw runtime_error("Invalid length of enabled outChannels vector");
|
||||||
|
}
|
||||||
|
|
||||||
|
stopThread = false;
|
||||||
|
|
||||||
|
nFramesPerBlock = availableFramesPerBlock[framesPerBlockIndex];
|
||||||
|
|
||||||
|
if (nFramesPerBlock < 24 || nFramesPerBlock > 8192) {
|
||||||
|
throw runtime_error("Unsensible number of samples per block chosen");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (samplerate() < 10000 || samplerate() > 51000) {
|
||||||
|
throw runtime_error("Invalid sample rate");
|
||||||
|
}
|
||||||
|
|
||||||
|
DaqDeviceDescriptor devdescriptors[MAX_DEV_COUNT_PER_API];
|
||||||
|
DaqDeviceDescriptor descriptor;
|
||||||
|
DaqDeviceInterface interfaceType = ANY_IFC;
|
||||||
|
|
||||||
|
UlError err;
|
||||||
|
|
||||||
|
us numdevs = MAX_DEV_COUNT_PER_API;
|
||||||
|
err = ulGetDaqDeviceInventory(interfaceType, devdescriptors, (unsigned*) &numdevs);
|
||||||
|
if (err != ERR_NO_ERROR) {
|
||||||
|
throw runtime_error("Device inventarization failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((us) api_specific_devindex >= numdevs) {
|
||||||
|
throw runtime_error("Device number {deviceno} too high {err}. This could "
|
||||||
|
"happen when the device is currently not connected");
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor = devdescriptors[api_specific_devindex];
|
||||||
|
|
||||||
|
// get a handle to the DAQ device associated with the first descriptor
|
||||||
|
handle = ulCreateDaqDevice(descriptor);
|
||||||
|
|
||||||
|
if (handle == 0) {
|
||||||
|
throw runtime_error("Unable to create a handle to the specified DAQ "
|
||||||
|
"device. Is the device currently in use? Please make sure to set "
|
||||||
|
"the DAQ configuration in duplex mode if simultaneous input and "
|
||||||
|
"output is required.");
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ulConnectDaqDevice(handle);
|
||||||
if (err != ERR_NO_ERROR) {
|
if (err != ERR_NO_ERROR) {
|
||||||
showErr(err);
|
showErr(err);
|
||||||
throw runtime_error("Fatal: could not set AC/DC coupling mode");
|
ulReleaseDaqDevice(handle);
|
||||||
|
handle = 0;
|
||||||
|
throw runtime_error("Unable to connect to device: {err}");
|
||||||
}
|
}
|
||||||
|
|
||||||
IepeMode iepe = inputIEPEEnabled[ch] ? IEPE_ENABLED : IEPE_DISABLED;
|
for (us ch = 0; ch < 4; ch++) {
|
||||||
err = ulAISetConfig(handle, AI_CFG_CHAN_IEPE_MODE, ch, iepe);
|
|
||||||
if (err != ERR_NO_ERROR) {
|
err = ulAISetConfigDbl(handle, AI_CFG_CHAN_SENSOR_SENSITIVITY, ch, 1.0);
|
||||||
showErr(err);
|
showErr(err);
|
||||||
throw runtime_error("Fatal: could not set IEPE mode");
|
if (err != ERR_NO_ERROR) {
|
||||||
|
throw runtime_error("Fatal: could normalize channel sensitivity");
|
||||||
|
}
|
||||||
|
|
||||||
|
CouplingMode cm = inputACCouplingMode[ch] ? CM_AC : CM_DC;
|
||||||
|
err = ulAISetConfig(handle, AI_CFG_CHAN_COUPLING_MODE, ch, cm);
|
||||||
|
if (err != ERR_NO_ERROR) {
|
||||||
|
showErr(err);
|
||||||
|
throw runtime_error("Fatal: could not set AC/DC coupling mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
IepeMode iepe = inputIEPEEnabled[ch] ? IEPE_ENABLED : IEPE_DISABLED;
|
||||||
|
err = ulAISetConfig(handle, AI_CFG_CHAN_IEPE_MODE, ch, iepe);
|
||||||
|
if (err != ERR_NO_ERROR) {
|
||||||
|
showErr(err);
|
||||||
|
throw runtime_error("Fatal: could not set IEPE mode");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
DT9837A(const DT9837A &) = delete;
|
DT9837A(const DT9837A &) = delete;
|
||||||
|
|
||||||
@ -163,12 +163,12 @@ public:
|
|||||||
if (hasinput) {
|
if (hasinput) {
|
||||||
assert(!inbuffer);
|
assert(!inbuffer);
|
||||||
inbuffer =
|
inbuffer =
|
||||||
new double[neninchannels() * nFramesPerBlock * 2]; // Watch the 2!
|
new double[neninchannels() * nFramesPerBlock * 2]; // Watch the 2!
|
||||||
}
|
}
|
||||||
if (hasoutput) {
|
if (hasoutput) {
|
||||||
assert(!outbuffer);
|
assert(!outbuffer);
|
||||||
outbuffer =
|
outbuffer =
|
||||||
new double[nenoutchannels() * nFramesPerBlock * 2]; // Watch the 2!
|
new double[nenoutchannels() * nFramesPerBlock * 2]; // Watch the 2!
|
||||||
}
|
}
|
||||||
this->inqueue = inqueue;
|
this->inqueue = inqueue;
|
||||||
this->outqueue = outqueue;
|
this->outqueue = outqueue;
|
||||||
@ -203,6 +203,40 @@ public:
|
|||||||
friend void threadfcn(DT9837A *);
|
friend void threadfcn(DT9837A *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create an empty buffer and fill it with zeros.
|
||||||
|
*
|
||||||
|
* @param size The number of elements in the array
|
||||||
|
*
|
||||||
|
* @return Pointer to the array
|
||||||
|
*/
|
||||||
|
static double* createZeroBuffer(size_t size) {
|
||||||
|
|
||||||
|
double* buf = static_cast<double *>(
|
||||||
|
malloc(sizeof(double) * size));
|
||||||
|
|
||||||
|
for (us sample = 0; sample < size; sample++) {
|
||||||
|
buf[sample] = 0;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Copy samples from one linear array to the next.
|
||||||
|
*
|
||||||
|
* @param[in] from Buffer to copy from
|
||||||
|
* @param[out] to Buffer to copy to
|
||||||
|
* @param startFrom The position to start in the from-buffer
|
||||||
|
* @param startTo The position to start in the to-buffer
|
||||||
|
* @param N The number of samples to copy.
|
||||||
|
*/
|
||||||
|
static inline void copySamples(double* from,double* to,
|
||||||
|
const us startFrom,const us startTo,const us N) {
|
||||||
|
|
||||||
|
for (us sample = 0; sample < N; sample++) {
|
||||||
|
to[startTo + sample] = from[startFrom + sample];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void threadfcn(DT9837A *td) {
|
void threadfcn(DT9837A *td) {
|
||||||
|
|
||||||
std::cerr << "Starting DAQ Thread fcn" << endl;
|
std::cerr << "Starting DAQ Thread fcn" << endl;
|
||||||
@ -271,9 +305,9 @@ void threadfcn(DT9837A *td) {
|
|||||||
|
|
||||||
cerr << "Starting output DAC" << endl;
|
cerr << "Starting output DAC" << endl;
|
||||||
err = ulAOutScan(handle, 0, 0, BIP10VOLTS,
|
err = ulAOutScan(handle, 0, 0, BIP10VOLTS,
|
||||||
/* BIP60VOLTS, */
|
/* BIP60VOLTS, */
|
||||||
2 * td->nFramesPerBlock, // Watch the 2 here!
|
2 * td->nFramesPerBlock, // Watch the 2 here!
|
||||||
&samplerate, scanoptions, outscanflags, outbuffer);
|
&samplerate, scanoptions, outscanflags, outbuffer);
|
||||||
|
|
||||||
if (err != ERR_NO_ERROR) {
|
if (err != ERR_NO_ERROR) {
|
||||||
showErr(err);
|
showErr(err);
|
||||||
@ -315,8 +349,8 @@ void threadfcn(DT9837A *td) {
|
|||||||
|
|
||||||
cerr << "Starting input ADC" << endl;
|
cerr << "Starting input ADC" << endl;
|
||||||
err = ulDaqInScan(handle, indesc, neninchannels,
|
err = ulDaqInScan(handle, indesc, neninchannels,
|
||||||
2 * td->nFramesPerBlock, // Watch the 2 here!
|
2 * td->nFramesPerBlock, // Watch the 2 here!
|
||||||
&samplerate, scanoptions, inscanflags, inbuffer);
|
&samplerate, scanoptions, inscanflags, inbuffer);
|
||||||
if (err != ERR_NO_ERROR) {
|
if (err != ERR_NO_ERROR) {
|
||||||
showErr(err);
|
showErr(err);
|
||||||
goto exit;
|
goto exit;
|
||||||
@ -348,9 +382,9 @@ void threadfcn(DT9837A *td) {
|
|||||||
|
|
||||||
if (outxstat.currentScanCount > outTotalCount + 2 * nFramesPerBlock) {
|
if (outxstat.currentScanCount > outTotalCount + 2 * nFramesPerBlock) {
|
||||||
cerr << "***** WARNING: Missing output sample blocks, DAQ Scan count="
|
cerr << "***** WARNING: Missing output sample blocks, DAQ Scan count="
|
||||||
<< outxstat.currentScanCount
|
<< outxstat.currentScanCount
|
||||||
<< " while loop count = " << outTotalCount
|
<< " while loop count = " << outTotalCount
|
||||||
<< ", probably due to too small buffer size. *****" << endl;
|
<< ", probably due to too small buffer size. *****" << endl;
|
||||||
}
|
}
|
||||||
outTotalCount = outxstat.currentScanCount;
|
outTotalCount = outxstat.currentScanCount;
|
||||||
|
|
||||||
@ -362,22 +396,16 @@ void threadfcn(DT9837A *td) {
|
|||||||
if (!botoutenqueued) {
|
if (!botoutenqueued) {
|
||||||
/* cerr << "Copying output buffer to bottom" << endl; */
|
/* cerr << "Copying output buffer to bottom" << endl; */
|
||||||
double *bufcpy;
|
double *bufcpy;
|
||||||
|
assert(nenoutchannels > 0);
|
||||||
if (!outqueue->empty()) {
|
if (!outqueue->empty()) {
|
||||||
bufcpy = (double *)outqueue->dequeue();
|
bufcpy = (double *)outqueue->dequeue();
|
||||||
} else {
|
} else {
|
||||||
cerr << "******* WARNING: OUTPUTQUEUE UNDERFLOW, FILLING SIGNAL "
|
cerr << "******* WARNING: OUTPUTQUEUE UNDERFLOW, FILLING SIGNAL "
|
||||||
"QUEUE WITH ZEROS ***********"
|
"QUEUE WITH ZEROS ***********"
|
||||||
<< endl;
|
<< endl;
|
||||||
bufcpy = static_cast<double *>(
|
bufcpy = createZeroBuffer(nFramesPerBlock*nenoutchannels);
|
||||||
malloc(sizeof(double) * nFramesPerBlock * nenoutchannels));
|
|
||||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
|
||||||
bufcpy[sample] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(nenoutchannels > 0);
|
|
||||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
|
||||||
outbuffer[buffer_mid_idx_out + sample] = bufcpy[sample];
|
|
||||||
}
|
}
|
||||||
|
copySamples(bufcpy, outbuffer, 0, buffer_mid_idx_out, nFramesPerBlock);
|
||||||
free(bufcpy);
|
free(bufcpy);
|
||||||
botoutenqueued = true;
|
botoutenqueued = true;
|
||||||
}
|
}
|
||||||
@ -386,22 +414,16 @@ void threadfcn(DT9837A *td) {
|
|||||||
if (!topoutenqueued) {
|
if (!topoutenqueued) {
|
||||||
/* cerr << "Copying output buffer to top" << endl; */
|
/* cerr << "Copying output buffer to top" << endl; */
|
||||||
double *bufcpy;
|
double *bufcpy;
|
||||||
|
assert(nenoutchannels > 0);
|
||||||
if (!outqueue->empty()) {
|
if (!outqueue->empty()) {
|
||||||
bufcpy = (double *)outqueue->dequeue();
|
bufcpy = (double *)outqueue->dequeue();
|
||||||
} else {
|
} else {
|
||||||
cerr << "******* WARNING: OUTPUTQUEUE UNDERFLOW, FILLING SIGNAL "
|
cerr << "******* WARNING: OUTPUTQUEUE UNDERFLOW, FILLING SIGNAL "
|
||||||
"QUEUE WITH ZEROS ***********"
|
"QUEUE WITH ZEROS ***********"
|
||||||
<< endl;
|
<< endl;
|
||||||
bufcpy = static_cast<double *>(
|
bufcpy = createZeroBuffer(nFramesPerBlock*nenoutchannels);
|
||||||
malloc(sizeof(double) * nFramesPerBlock * nenoutchannels));
|
|
||||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
|
||||||
bufcpy[sample] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(nenoutchannels > 0);
|
|
||||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
|
||||||
outbuffer[sample] = bufcpy[sample];
|
|
||||||
}
|
}
|
||||||
|
copySamples(bufcpy, outbuffer, 0, 0, nFramesPerBlock);
|
||||||
free(bufcpy);
|
free(bufcpy);
|
||||||
topoutenqueued = true;
|
topoutenqueued = true;
|
||||||
}
|
}
|
||||||
@ -417,10 +439,10 @@ void threadfcn(DT9837A *td) {
|
|||||||
assert(inscanstat == SS_RUNNING);
|
assert(inscanstat == SS_RUNNING);
|
||||||
if (inxstat.currentScanCount > inTotalCount + 2 * nFramesPerBlock) {
|
if (inxstat.currentScanCount > inTotalCount + 2 * nFramesPerBlock) {
|
||||||
cerr << "***** ERROR: Missing input sample blocks, count="
|
cerr << "***** ERROR: Missing input sample blocks, count="
|
||||||
<< inxstat.currentScanCount
|
<< inxstat.currentScanCount
|
||||||
<< ", probably due to too small buffer size. Exiting thread. "
|
<< ", probably due to too small buffer size. Exiting thread. "
|
||||||
"*****"
|
"*****"
|
||||||
<< endl;
|
<< endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
inTotalCount = inxstat.currentScanCount;
|
inTotalCount = inxstat.currentScanCount;
|
||||||
@ -434,11 +456,11 @@ void threadfcn(DT9837A *td) {
|
|||||||
us monitoroffset = monitorOutput ? 1 : 0;
|
us monitoroffset = monitorOutput ? 1 : 0;
|
||||||
assert(neninchannels > 0);
|
assert(neninchannels > 0);
|
||||||
for (us channel = 0; channel < (neninchannels - monitoroffset);
|
for (us channel = 0; channel < (neninchannels - monitoroffset);
|
||||||
channel++) {
|
channel++) {
|
||||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
||||||
bufcpy[(monitoroffset + channel) * nFramesPerBlock + sample] =
|
bufcpy[(monitoroffset + channel) * nFramesPerBlock + sample] =
|
||||||
inbuffer[buffer_mid_idx_in + sample * neninchannels +
|
inbuffer[buffer_mid_idx_in + sample * neninchannels +
|
||||||
channel];
|
channel];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (monitorOutput) {
|
if (monitorOutput) {
|
||||||
@ -447,7 +469,7 @@ void threadfcn(DT9837A *td) {
|
|||||||
us channel = neninchannels - 1;
|
us channel = neninchannels - 1;
|
||||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
||||||
bufcpy[sample] = inbuffer[buffer_mid_idx_in +
|
bufcpy[sample] = inbuffer[buffer_mid_idx_in +
|
||||||
sample * neninchannels + channel];
|
sample * neninchannels + channel];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inqueue->enqueue((void *)bufcpy);
|
inqueue->enqueue((void *)bufcpy);
|
||||||
@ -461,10 +483,10 @@ void threadfcn(DT9837A *td) {
|
|||||||
us monitoroffset = monitorOutput ? 1 : 0;
|
us monitoroffset = monitorOutput ? 1 : 0;
|
||||||
assert(neninchannels > 0);
|
assert(neninchannels > 0);
|
||||||
for (us channel = 0; channel < (neninchannels - monitoroffset);
|
for (us channel = 0; channel < (neninchannels - monitoroffset);
|
||||||
channel++) {
|
channel++) {
|
||||||
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
for (us sample = 0; sample < nFramesPerBlock; sample++) {
|
||||||
bufcpy[(monitoroffset + channel) * nFramesPerBlock + sample] =
|
bufcpy[(monitoroffset + channel) * nFramesPerBlock + sample] =
|
||||||
inbuffer[sample * neninchannels + channel];
|
inbuffer[sample * neninchannels + channel];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (monitorOutput) {
|
if (monitorOutput) {
|
||||||
@ -510,7 +532,7 @@ exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Daq *createUlDaqDevice(const DeviceInfo &devinfo,
|
Daq *createUlDaqDevice(const DeviceInfo &devinfo,
|
||||||
const DaqConfiguration &config) {
|
const DaqConfiguration &config) {
|
||||||
|
|
||||||
DT9837A *daq = NULL;
|
DT9837A *daq = NULL;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user