Portaudio backend seems to be working. No extensive checks performed yet.
This commit is contained in:
parent
77b1848bb4
commit
64a268e277
@ -337,9 +337,9 @@ public:
|
||||
const auto &dtype_descr = dtypeDescr();
|
||||
const auto dtype = dataType();
|
||||
|
||||
us neninchannels = this->neninchannels();
|
||||
us nenoutchannels = this->nenoutchannels();
|
||||
us sw = dtype_descr.sw;
|
||||
const us neninchannels = this->neninchannels();
|
||||
const us nenoutchannels = this->nenoutchannels();
|
||||
const us sw = dtype_descr.sw;
|
||||
if (nFrames != nFramesPerBlock) {
|
||||
cerr << "RtAudio backend error: nFrames does not match block size!"
|
||||
<< endl;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#define DEBUGTRACE_ENABLED
|
||||
/* #define DEBUGTRACE_ENABLED */
|
||||
#include "debugtrace.hpp"
|
||||
#include "lasp_config.h"
|
||||
|
||||
@ -123,6 +123,10 @@ static int rawPaCallback(const void *inputBuffer, void *outputBuffer,
|
||||
class PortAudioDaq : public Daq {
|
||||
bool _shouldPaTerminate = false;
|
||||
PaStream *_stream = nullptr;
|
||||
std::atomic<StreamStatus::StreamError> _streamError =
|
||||
StreamStatus::StreamError::noError;
|
||||
InDaqCallback _incallback;
|
||||
OutDaqCallback _outcallback;
|
||||
|
||||
public:
|
||||
PortAudioDaq(const OurPaDeviceInfo &devinfo_gen,
|
||||
@ -211,11 +215,12 @@ PortAudioDaq::PortAudioDaq(const OurPaDeviceInfo &devinfo_gen,
|
||||
|
||||
using Dtype = DataTypeDescriptor::DataType;
|
||||
const Dtype dtype = dataType();
|
||||
PaSampleFormat format;
|
||||
// Sample format is bit flag
|
||||
PaSampleFormat format = paNonInterleaved;
|
||||
switch (dtype) {
|
||||
case Dtype::dtype_fl32:
|
||||
DEBUGTRACE_PRINT("Datatype float32");
|
||||
format = paFloat32;
|
||||
format |= paFloat32;
|
||||
break;
|
||||
case Dtype::dtype_fl64:
|
||||
DEBUGTRACE_PRINT("Datatype float64");
|
||||
@ -223,15 +228,15 @@ PortAudioDaq::PortAudioDaq(const OurPaDeviceInfo &devinfo_gen,
|
||||
break;
|
||||
case Dtype::dtype_int8:
|
||||
DEBUGTRACE_PRINT("Datatype int8");
|
||||
format = paInt8;
|
||||
format |= paInt8;
|
||||
break;
|
||||
case Dtype::dtype_int16:
|
||||
DEBUGTRACE_PRINT("Datatype int16");
|
||||
format = paInt16;
|
||||
format |= paInt16;
|
||||
break;
|
||||
case Dtype::dtype_int32:
|
||||
DEBUGTRACE_PRINT("Datatype int32");
|
||||
format = paInt32;
|
||||
format |= paInt32;
|
||||
break;
|
||||
default:
|
||||
throw rte("Invalid data type specified for DAQ stream.");
|
||||
@ -250,7 +255,7 @@ PortAudioDaq::PortAudioDaq(const OurPaDeviceInfo &devinfo_gen,
|
||||
.hostApiSpecificStreamInfo = nullptr}));
|
||||
}
|
||||
if (nenoutchannels() > 0) {
|
||||
instreamParams = std::make_unique<PaStreamParameters>(
|
||||
outstreamParams = std::make_unique<PaStreamParameters>(
|
||||
PaStreamParameters({.device = devindex,
|
||||
.channelCount = (int)nenoutchannels(),
|
||||
.sampleFormat = format,
|
||||
@ -279,6 +284,30 @@ void PortAudioDaq::start(InDaqCallback inCallback, OutDaqCallback outCallback) {
|
||||
if (Pa_IsStreamActive(_stream)) {
|
||||
throw rte("Stream is already running");
|
||||
}
|
||||
|
||||
// Logical XOR
|
||||
if (inCallback && outCallback) {
|
||||
throw rte("Either input or output stream possible for RtAudio. "
|
||||
"Stream duplex mode not provided.");
|
||||
}
|
||||
|
||||
if (neninchannels() > 0) {
|
||||
if (!inCallback) {
|
||||
throw rte(
|
||||
|
||||
"Input callback given, but stream does not provide input data");
|
||||
}
|
||||
|
||||
_incallback = inCallback;
|
||||
}
|
||||
if (nenoutchannels() > 0) {
|
||||
if (!outCallback) {
|
||||
throw rte(
|
||||
"Output callback given, but stream does not provide output data");
|
||||
}
|
||||
_outcallback = outCallback;
|
||||
}
|
||||
|
||||
PaError err = Pa_StartStream(_stream);
|
||||
throwIfError(err);
|
||||
}
|
||||
@ -293,6 +322,9 @@ void PortAudioDaq::stop() {
|
||||
}
|
||||
Daq::StreamStatus PortAudioDaq::getStreamStatus() const {
|
||||
Daq::StreamStatus status;
|
||||
// Copy over atomic flag.
|
||||
status.errorType = _streamError;
|
||||
// Check if stream is still running.
|
||||
if (_stream) {
|
||||
if (Pa_IsStreamActive(_stream)) {
|
||||
status.isRunning = true;
|
||||
@ -329,6 +361,84 @@ int PortAudioDaq::memberPaCallback(const void *inputBuffer, void *outputBuffer,
|
||||
PaStreamCallbackFlags statusFlags) {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
typedef Daq::StreamStatus::StreamError se;
|
||||
if (statusFlags & paPrimingOutput) {
|
||||
// Initial output buffers generated. So nothing with input yet
|
||||
return paContinue;
|
||||
}
|
||||
if ((statusFlags & paInputUnderflow) || (statusFlags & paInputOverflow)) {
|
||||
_streamError = se::inputXRun;
|
||||
return paAbort;
|
||||
}
|
||||
if ((statusFlags & paOutputUnderflow) || (statusFlags & paOutputOverflow)) {
|
||||
_streamError = se::outputXRun;
|
||||
return paAbort;
|
||||
}
|
||||
if (framesPerBuffer != framesPerBlock()) {
|
||||
cerr << "Logic error: expected a block size of: " << framesPerBlock()
|
||||
<< endl;
|
||||
_streamError = se::logicError;
|
||||
return paAbort;
|
||||
}
|
||||
|
||||
const us neninchannels = this->neninchannels();
|
||||
const us nenoutchannels = this->nenoutchannels();
|
||||
const auto &dtype_descr = dtypeDescr();
|
||||
const auto dtype = dataType();
|
||||
const us sw = dtype_descr.sw;
|
||||
if (inputBuffer) {
|
||||
assert(_incallback);
|
||||
std::vector<byte_t *> ptrs;
|
||||
ptrs.reserve(neninchannels);
|
||||
|
||||
const us ch_min = getLowestEnabledInChannel();
|
||||
const us ch_max = getHighestEnabledInChannel();
|
||||
assert(ch_min < ninchannels);
|
||||
assert(ch_max < ninchannels);
|
||||
|
||||
/// Only pass on the pointers of the channels we want. inputBuffer is
|
||||
/// noninterleaved, as specified in PortAudioDaq constructor.
|
||||
for (us ch = ch_min; ch <= ch_max; ch++) {
|
||||
if (inchannel_config.at(ch).enabled) {
|
||||
byte_t *ch_ptr =
|
||||
reinterpret_cast<byte_t **>(const_cast<void *>(inputBuffer))[ch];
|
||||
ptrs.push_back(ch_ptr);
|
||||
}
|
||||
}
|
||||
DaqData d{framesPerBuffer, neninchannels, dtype};
|
||||
d.copyInFromRaw(ptrs);
|
||||
|
||||
_incallback(d);
|
||||
}
|
||||
|
||||
if (outputBuffer) {
|
||||
assert(_outcallback);
|
||||
std::vector<byte_t *> ptrs;
|
||||
ptrs.reserve(nenoutchannels);
|
||||
|
||||
/* outCallback */
|
||||
|
||||
const us ch_min = getLowestEnabledOutChannel();
|
||||
const us ch_max = getHighestEnabledOutChannel();
|
||||
assert(ch_min < noutchannels);
|
||||
assert(ch_max < noutchannels);
|
||||
/// Only pass on the pointers of the channels we want
|
||||
for (us ch = ch_min; ch <= ch_max; ch++) {
|
||||
if (outchannel_config.at(ch).enabled) {
|
||||
byte_t *ch_ptr = reinterpret_cast<byte_t **>(outputBuffer)[ch];
|
||||
ptrs.push_back(ch_ptr);
|
||||
}
|
||||
}
|
||||
DaqData d{framesPerBuffer, nenoutchannels, dtype};
|
||||
|
||||
_outcallback(d);
|
||||
// Copy over the buffer
|
||||
us j = 0;
|
||||
for (auto ptr : ptrs) {
|
||||
d.copyToRaw(j, ptr);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
return paContinue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user