Update RtAudio backend to overwrite default samplerate to 48 kHz, if available
This commit is contained in:
parent
fbb14f475c
commit
0c0a86dc64
@ -38,35 +38,50 @@ void fillRtAudioDeviceInfo(vector<DeviceInfo> &devinfolist) {
|
||||
// "Our device info struct"
|
||||
DeviceInfo d;
|
||||
switch (api) {
|
||||
case RtAudio::LINUX_ALSA:
|
||||
d.api = rtaudioAlsaApi;
|
||||
break;
|
||||
case RtAudio::LINUX_PULSE:
|
||||
d.api = rtaudioPulseaudioApi;
|
||||
break;
|
||||
case RtAudio::WINDOWS_WASAPI:
|
||||
d.api = rtaudioWasapiApi;
|
||||
break;
|
||||
case RtAudio::WINDOWS_DS:
|
||||
d.api = rtaudioDsApi;
|
||||
break;
|
||||
case RtAudio::WINDOWS_ASIO:
|
||||
d.api = rtaudioAsioApi;
|
||||
break;
|
||||
default:
|
||||
cerr << "Not implemented RtAudio API, skipping." << endl;
|
||||
continue;
|
||||
break;
|
||||
case RtAudio::LINUX_ALSA:
|
||||
d.api = rtaudioAlsaApi;
|
||||
break;
|
||||
case RtAudio::LINUX_PULSE:
|
||||
d.api = rtaudioPulseaudioApi;
|
||||
break;
|
||||
case RtAudio::WINDOWS_WASAPI:
|
||||
d.api = rtaudioWasapiApi;
|
||||
break;
|
||||
case RtAudio::WINDOWS_DS:
|
||||
d.api = rtaudioDsApi;
|
||||
break;
|
||||
case RtAudio::WINDOWS_ASIO:
|
||||
d.api = rtaudioAsioApi;
|
||||
break;
|
||||
default:
|
||||
cerr << "Not implemented RtAudio API, skipping." << endl;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
d.device_name = devinfo.name;
|
||||
d.api_specific_devindex = devno;
|
||||
|
||||
/// We overwrite the default sample rate with the 48 kHz value, which
|
||||
/// is our preffered rate.
|
||||
bool rate_48k_found = false;
|
||||
|
||||
for (us j = 0; j < devinfo.sampleRates.size(); j++) {
|
||||
us rate = devinfo.sampleRates[j];
|
||||
d.availableSampleRates.push_back((double)rate);
|
||||
if (devinfo.preferredSampleRate == rate) {
|
||||
d.prefSampleRateIndex = j;
|
||||
|
||||
us rate_int = devinfo.sampleRates[j];
|
||||
|
||||
d.availableSampleRates.push_back((double)rate_int);
|
||||
|
||||
if(!rate_48k_found) {
|
||||
|
||||
if (devinfo.preferredSampleRate == rate_int) {
|
||||
d.prefSampleRateIndex = j;
|
||||
}
|
||||
|
||||
if(rate_int == 48000) {
|
||||
d.prefSampleRateIndex = j;
|
||||
rate_48k_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,7 +101,7 @@ void fillRtAudioDeviceInfo(vector<DeviceInfo> &devinfolist) {
|
||||
}
|
||||
/* if (formats & RTAUDIO_SINT24) { *1/ */
|
||||
/* d.availableDataTypes.push_back(DataTypeDescriptor::DataType::dtype_int24);
|
||||
*/
|
||||
*/
|
||||
/* } */
|
||||
if (formats & RTAUDIO_SINT32) {
|
||||
d.availableDataTypes.push_back(
|
||||
@ -103,7 +118,7 @@ void fillRtAudioDeviceInfo(vector<DeviceInfo> &devinfolist) {
|
||||
d.prefDataTypeIndex = d.availableDataTypes.size() - 1;
|
||||
|
||||
d.availableFramesPerBlock = {512, 1024, 2048, 4096, 8192};
|
||||
d.prefFramesPerBlockIndex = 1;
|
||||
d.prefFramesPerBlockIndex = 2;
|
||||
|
||||
devinfolist.push_back(d);
|
||||
}
|
||||
@ -111,8 +126,8 @@ void fillRtAudioDeviceInfo(vector<DeviceInfo> &devinfolist) {
|
||||
}
|
||||
|
||||
static int mycallback(void *outputBuffer, void *inputBuffer,
|
||||
unsigned int nFrames, double streamTime,
|
||||
RtAudioStreamStatus status, void *userData);
|
||||
unsigned int nFrames, double streamTime,
|
||||
RtAudioStreamStatus status, void *userData);
|
||||
|
||||
static void myerrorcallback(RtAudioError::Type, const string &errorText);
|
||||
|
||||
@ -129,101 +144,101 @@ class RtAudioDaq : public Daq {
|
||||
|
||||
std::atomic<StreamStatus> _streamStatus{};
|
||||
|
||||
public:
|
||||
public:
|
||||
RtAudioDaq(const DeviceInfo &devinfo, const DaqConfiguration &config)
|
||||
: Daq(devinfo, config),
|
||||
rtaudio(static_cast<RtAudio::Api>(devinfo.api.api_specific_subcode)),
|
||||
nFramesPerBlock(Daq::framesPerBlock()) {
|
||||
: Daq(devinfo, config),
|
||||
rtaudio(static_cast<RtAudio::Api>(devinfo.api.api_specific_subcode)),
|
||||
nFramesPerBlock(Daq::framesPerBlock()) {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
DEBUGTRACE_ENTER;
|
||||
|
||||
// We make sure not to run RtAudio in duplex mode. This seems to be buggy
|
||||
// and untested. Better to use a hardware-type loopback into the system.
|
||||
if (duplexMode()) {
|
||||
throw rte("RtAudio backend cannot run in duplex mode.");
|
||||
}
|
||||
assert(!monitorOutput);
|
||||
|
||||
std::unique_ptr<RtAudio::StreamParameters> inParams, outParams;
|
||||
|
||||
if (neninchannels() > 0) {
|
||||
|
||||
inParams = std::make_unique<RtAudio::StreamParameters>();
|
||||
|
||||
// +1 to get the count.
|
||||
inParams->nChannels = getHighestEnabledInChannel() + 1;
|
||||
if (inParams->nChannels < 1) {
|
||||
throw rte("Invalid input number of channels");
|
||||
// We make sure not to run RtAudio in duplex mode. This seems to be buggy
|
||||
// and untested. Better to use a hardware-type loopback into the system.
|
||||
if (duplexMode()) {
|
||||
throw rte("RtAudio backend cannot run in duplex mode.");
|
||||
}
|
||||
inParams->firstChannel = 0;
|
||||
inParams->deviceId = devinfo.api_specific_devindex;
|
||||
assert(!monitorOutput);
|
||||
|
||||
} else {
|
||||
std::unique_ptr<RtAudio::StreamParameters> inParams, outParams;
|
||||
|
||||
outParams = std::make_unique<RtAudio::StreamParameters>();
|
||||
if (neninchannels() > 0) {
|
||||
|
||||
outParams->nChannels = getHighestEnabledOutChannel() + 1;
|
||||
if (outParams->nChannels < 1) {
|
||||
throw rte("Invalid output number of channels");
|
||||
inParams = std::make_unique<RtAudio::StreamParameters>();
|
||||
|
||||
// +1 to get the count.
|
||||
inParams->nChannels = getHighestEnabledInChannel() + 1;
|
||||
if (inParams->nChannels < 1) {
|
||||
throw rte("Invalid input number of channels");
|
||||
}
|
||||
inParams->firstChannel = 0;
|
||||
inParams->deviceId = devinfo.api_specific_devindex;
|
||||
|
||||
} else {
|
||||
|
||||
outParams = std::make_unique<RtAudio::StreamParameters>();
|
||||
|
||||
outParams->nChannels = getHighestEnabledOutChannel() + 1;
|
||||
if (outParams->nChannels < 1) {
|
||||
throw rte("Invalid output number of channels");
|
||||
}
|
||||
outParams->firstChannel = 0;
|
||||
outParams->deviceId = devinfo.api_specific_devindex;
|
||||
}
|
||||
|
||||
RtAudio::StreamOptions streamoptions;
|
||||
streamoptions.flags = RTAUDIO_HOG_DEVICE | RTAUDIO_NONINTERLEAVED;
|
||||
|
||||
streamoptions.numberOfBuffers = 2;
|
||||
streamoptions.streamName = "LASP RtAudio DAQ stream";
|
||||
streamoptions.priority = 0;
|
||||
|
||||
RtAudioFormat format;
|
||||
using Dtype = DataTypeDescriptor::DataType;
|
||||
const Dtype dtype = dataType();
|
||||
switch (dtype) {
|
||||
case Dtype::dtype_fl32:
|
||||
DEBUGTRACE_PRINT("Datatype float32");
|
||||
format = RTAUDIO_FLOAT32;
|
||||
break;
|
||||
case Dtype::dtype_fl64:
|
||||
DEBUGTRACE_PRINT("Datatype float64");
|
||||
format = RTAUDIO_FLOAT64;
|
||||
break;
|
||||
case Dtype::dtype_int8:
|
||||
DEBUGTRACE_PRINT("Datatype int8");
|
||||
format = RTAUDIO_SINT8;
|
||||
break;
|
||||
case Dtype::dtype_int16:
|
||||
DEBUGTRACE_PRINT("Datatype int16");
|
||||
format = RTAUDIO_SINT16;
|
||||
break;
|
||||
case Dtype::dtype_int32:
|
||||
DEBUGTRACE_PRINT("Datatype int32");
|
||||
format = RTAUDIO_SINT32;
|
||||
break;
|
||||
default:
|
||||
throw rte("Invalid data type specified for DAQ stream.");
|
||||
break;
|
||||
}
|
||||
|
||||
// Copy here, as it is used to return the *actual* number of frames per
|
||||
// block.
|
||||
unsigned int nFramesPerBlock_copy = nFramesPerBlock;
|
||||
|
||||
// Final step: open the stream.
|
||||
rtaudio.openStream(outParams.get(), inParams.get(), format,
|
||||
static_cast<us>(samplerate()), &nFramesPerBlock_copy,
|
||||
mycallback, (void *)this, &streamoptions,
|
||||
&myerrorcallback);
|
||||
|
||||
if (nFramesPerBlock_copy != nFramesPerBlock) {
|
||||
throw rte("Got different number of frames per block back from RtAudio "
|
||||
"backend. Do not know what to do");
|
||||
}
|
||||
outParams->firstChannel = 0;
|
||||
outParams->deviceId = devinfo.api_specific_devindex;
|
||||
}
|
||||
|
||||
RtAudio::StreamOptions streamoptions;
|
||||
streamoptions.flags = RTAUDIO_HOG_DEVICE | RTAUDIO_NONINTERLEAVED;
|
||||
|
||||
streamoptions.numberOfBuffers = 2;
|
||||
streamoptions.streamName = "LASP RtAudio DAQ stream";
|
||||
streamoptions.priority = 0;
|
||||
|
||||
RtAudioFormat format;
|
||||
using Dtype = DataTypeDescriptor::DataType;
|
||||
const Dtype dtype = dataType();
|
||||
switch (dtype) {
|
||||
case Dtype::dtype_fl32:
|
||||
DEBUGTRACE_PRINT("Datatype float32");
|
||||
format = RTAUDIO_FLOAT32;
|
||||
break;
|
||||
case Dtype::dtype_fl64:
|
||||
DEBUGTRACE_PRINT("Datatype float64");
|
||||
format = RTAUDIO_FLOAT64;
|
||||
break;
|
||||
case Dtype::dtype_int8:
|
||||
DEBUGTRACE_PRINT("Datatype int8");
|
||||
format = RTAUDIO_SINT8;
|
||||
break;
|
||||
case Dtype::dtype_int16:
|
||||
DEBUGTRACE_PRINT("Datatype int16");
|
||||
format = RTAUDIO_SINT16;
|
||||
break;
|
||||
case Dtype::dtype_int32:
|
||||
DEBUGTRACE_PRINT("Datatype int32");
|
||||
format = RTAUDIO_SINT32;
|
||||
break;
|
||||
default:
|
||||
throw rte("Invalid data type specified for DAQ stream.");
|
||||
break;
|
||||
}
|
||||
|
||||
// Copy here, as it is used to return the *actual* number of frames per
|
||||
// block.
|
||||
unsigned int nFramesPerBlock_copy = nFramesPerBlock;
|
||||
|
||||
// Final step: open the stream.
|
||||
rtaudio.openStream(outParams.get(), inParams.get(), format,
|
||||
static_cast<us>(samplerate()), &nFramesPerBlock_copy,
|
||||
mycallback, (void *)this, &streamoptions,
|
||||
&myerrorcallback);
|
||||
|
||||
if (nFramesPerBlock_copy != nFramesPerBlock) {
|
||||
throw rte("Got different number of frames per block back from RtAudio "
|
||||
"backend. Do not know what to do");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void start(InDaqCallback inCallback,
|
||||
OutDaqCallback outCallback) override final {
|
||||
OutDaqCallback outCallback) override final {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
|
||||
@ -236,7 +251,7 @@ public:
|
||||
// Logical XOR
|
||||
if (inCallback && outCallback) {
|
||||
throw rte("Either input or output stream possible for RtAudio. "
|
||||
"Stream duplex mode not provided.");
|
||||
"Stream duplex mode not provided.");
|
||||
}
|
||||
|
||||
if (neninchannels() > 0) {
|
||||
@ -279,7 +294,7 @@ public:
|
||||
}
|
||||
|
||||
int streamCallback(void *outputBuffer, void *inputBuffer,
|
||||
unsigned int nFrames, RtAudioStreamStatus status) {
|
||||
unsigned int nFrames, RtAudioStreamStatus status) {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
|
||||
@ -296,16 +311,16 @@ public:
|
||||
};
|
||||
|
||||
switch (status) {
|
||||
case RTAUDIO_INPUT_OVERFLOW:
|
||||
stopWithError(se::inputXRun);
|
||||
return 1;
|
||||
break;
|
||||
case RTAUDIO_OUTPUT_UNDERFLOW:
|
||||
stopWithError(se::outputXRun);
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case RTAUDIO_INPUT_OVERFLOW:
|
||||
stopWithError(se::inputXRun);
|
||||
return 1;
|
||||
break;
|
||||
case RTAUDIO_OUTPUT_UNDERFLOW:
|
||||
stopWithError(se::outputXRun);
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const auto &dtype_descr = dtypeDescr();
|
||||
@ -316,7 +331,7 @@ public:
|
||||
us sw = dtype_descr.sw;
|
||||
if (nFrames != nFramesPerBlock) {
|
||||
cerr << "RtAudio backend error: nFrames does not match block size!"
|
||||
<< endl;
|
||||
<< endl;
|
||||
stopWithError(se::logicError);
|
||||
return 1;
|
||||
}
|
||||
@ -332,7 +347,7 @@ public:
|
||||
for (us ch = ch_min; ch <= ch_max; ch++) {
|
||||
if (inchannel_config.at(ch).enabled) {
|
||||
byte_t *ptr =
|
||||
static_cast<byte_t *>(inputBuffer) + sw * i * nFramesPerBlock;
|
||||
static_cast<byte_t *>(inputBuffer) + sw * i * nFramesPerBlock;
|
||||
DEBUGTRACE_PRINT((us)ptr);
|
||||
ptrs.push_back(ptr);
|
||||
}
|
||||
@ -362,7 +377,7 @@ public:
|
||||
if (outchannel_config.at(ch).enabled) {
|
||||
|
||||
ptrs.push_back(static_cast<byte_t *>(outputBuffer) +
|
||||
sw * i * nFramesPerBlock);
|
||||
sw * i * nFramesPerBlock);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@ -390,7 +405,7 @@ public:
|
||||
};
|
||||
|
||||
std::unique_ptr<Daq> createRtAudioDevice(const DeviceInfo &devinfo,
|
||||
const DaqConfiguration &config) {
|
||||
const DaqConfiguration &config) {
|
||||
return std::make_unique<RtAudioDaq>(devinfo, config);
|
||||
}
|
||||
|
||||
@ -398,7 +413,7 @@ void myerrorcallback(RtAudioError::Type, const string &errorText) {
|
||||
cerr << "RtAudio backend stream error: " << errorText << endl;
|
||||
}
|
||||
int mycallback(void *outputBuffer, void *inputBuffer, unsigned int nFrames,
|
||||
double streamTime, RtAudioStreamStatus status, void *userData) {
|
||||
double streamTime, RtAudioStreamStatus status, void *userData) {
|
||||
|
||||
return static_cast<RtAudioDaq *>(userData)->streamCallback(
|
||||
outputBuffer, inputBuffer, nFrames, status);
|
||||
|
Loading…
Reference in New Issue
Block a user