From 0c0a86dc647931ec28be72755390cec4dda1ab42 Mon Sep 17 00:00:00 2001 From: "J.A. de Jong - Redu-Sone B.V., ASCEE V.O.F" Date: Fri, 11 Nov 2022 12:35:52 +0100 Subject: [PATCH] Update RtAudio backend to overwrite default samplerate to 48 kHz, if available --- src/lasp/device/lasp_rtaudiodaq.cpp | 271 +++++++++++++++------------- 1 file changed, 143 insertions(+), 128 deletions(-) diff --git a/src/lasp/device/lasp_rtaudiodaq.cpp b/src/lasp/device/lasp_rtaudiodaq.cpp index 411ecda..f57a828 100644 --- a/src/lasp/device/lasp_rtaudiodaq.cpp +++ b/src/lasp/device/lasp_rtaudiodaq.cpp @@ -38,35 +38,50 @@ void fillRtAudioDeviceInfo(vector &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 &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 &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 &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{}; -public: + public: RtAudioDaq(const DeviceInfo &devinfo, const DaqConfiguration &config) - : Daq(devinfo, config), - rtaudio(static_cast(devinfo.api.api_specific_subcode)), - nFramesPerBlock(Daq::framesPerBlock()) { + : Daq(devinfo, config), + rtaudio(static_cast(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 inParams, outParams; - - if (neninchannels() > 0) { - - inParams = std::make_unique(); - - // +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 inParams, outParams; - outParams = std::make_unique(); + if (neninchannels() > 0) { - outParams->nChannels = getHighestEnabledOutChannel() + 1; - if (outParams->nChannels < 1) { - throw rte("Invalid output number of channels"); + inParams = std::make_unique(); + + // +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(); + + 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(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(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(inputBuffer) + sw * i * nFramesPerBlock; + static_cast(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(outputBuffer) + - sw * i * nFramesPerBlock); + sw * i * nFramesPerBlock); } i++; } @@ -390,7 +405,7 @@ public: }; std::unique_ptr createRtAudioDevice(const DeviceInfo &devinfo, - const DaqConfiguration &config) { + const DaqConfiguration &config) { return std::make_unique(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(userData)->streamCallback( outputBuffer, inputBuffer, nFrames, status);