Finished RtAudio sink

This commit is contained in:
Ryzerth 2021-02-22 04:04:49 +01:00
parent 49cf3af769
commit 72bd3e9cc1

View File

@ -7,6 +7,8 @@
#include <dsp/processing.h> #include <dsp/processing.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <RtAudio.h> #include <RtAudio.h>
#include <config.h>
#include <options.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str()) #define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -18,6 +20,8 @@ SDRPP_MOD_INFO {
/* Max instances */ 1 /* Max instances */ 1
}; };
ConfigManager config;
class AudioSink : SinkManager::Sink { class AudioSink : SinkManager::Sink {
public: public:
AudioSink(SinkManager::Stream* stream, std::string streamName) { AudioSink(SinkManager::Stream* stream, std::string streamName) {
@ -27,9 +31,16 @@ public:
monoPacker.init(&s2m.out, 512); monoPacker.init(&s2m.out, 512);
stereoPacker.init(_stream->sinkOut, 512); stereoPacker.init(_stream->sinkOut, 512);
stream->setSampleRate(48000); bool created = false;
std::string device = "";
RtAudio::StreamParameters parameters; config.aquire();
if (!config.conf.contains(_streamName)) {
created = true;
config.conf[_streamName]["device"] = "";
config.conf[_streamName]["devices"] = json({});
}
device = config.conf[_streamName]["device"];
config.release(created);
int count = audio.getDeviceCount(); int count = audio.getDeviceCount();
RtAudio::DeviceInfo info; RtAudio::DeviceInfo info;
@ -37,12 +48,14 @@ public:
info = audio.getDeviceInfo(i); info = audio.getDeviceInfo(i);
if (!info.probed) { continue; } if (!info.probed) { continue; }
if (info.outputChannels == 0) { continue; } if (info.outputChannels == 0) { continue; }
if (info.isDefaultOutput) { devId = devList.size(); } if (info.isDefaultOutput) { defaultDevId = devList.size(); }
devList.push_back(info); devList.push_back(info);
deviceIds.push_back(i); deviceIds.push_back(i);
txtDevList += info.name; txtDevList += info.name;
txtDevList += '\0'; txtDevList += '\0';
} }
selectByName(device);
} }
~AudioSink() { ~AudioSink() {
@ -65,30 +78,83 @@ public:
running = false; running = false;
} }
void selectFirst() {
selectById(defaultDevId);
}
void selectByName(std::string name) {
for (int i = 0; i < devList.size(); i++) {
if (devList[i].name == name) {
selectById(i);
return;
}
}
selectFirst();
}
void selectById(int id) {
devId = id;
bool created = false;
config.aquire();
if (!config.conf[_streamName]["devices"].contains(devList[id].name)) {
created = true;
config.conf[_streamName]["devices"][devList[id].name] = devList[id].preferredSampleRate;
}
sampleRate = config.conf[_streamName]["devices"][devList[id].name];
config.release(created);
sampleRates = devList[id].sampleRates;
sampleRatesTxt = "";
char buf[256];
bool found = false;
unsigned int defaultId = 0;
unsigned int defaultSr = devList[id].preferredSampleRate;
for (int i = 0; i < sampleRates.size(); i++) {
if (sampleRates[i] == sampleRate) {
found = true;
srId = i;
}
if (sampleRates[i] == defaultSr) {
defaultId = i;
}
sprintf(buf, "%d", sampleRates[i]);
sampleRatesTxt += buf;
sampleRatesTxt += '\0';
}
if (!found) {
sampleRate = defaultSr;
srId = defaultId;
}
_stream->setSampleRate(sampleRate);
if (running) { doStop(); }
if (running) { doStart(); }
}
void menuHandler() { void menuHandler() {
float menuWidth = ImGui::GetContentRegionAvailWidth(); float menuWidth = ImGui::GetContentRegionAvailWidth();
ImGui::SetNextItemWidth(menuWidth); ImGui::SetNextItemWidth(menuWidth);
if (ImGui::Combo(("##_rtaudio_sink_dev_"+_streamName).c_str(), &devId, txtDevList.c_str())) { if (ImGui::Combo(("##_rtaudio_sink_dev_"+_streamName).c_str(), &devId, txtDevList.c_str())) {
// TODO: Load SR from config selectById(devId);
config.aquire();
config.conf[_streamName]["device"] = devList[devId].name;
config.release(true);
}
ImGui::SetNextItemWidth(menuWidth);
if (ImGui::Combo(("##_rtaudio_sink_sr_"+_streamName).c_str(), &srId, sampleRatesTxt.c_str())) {
sampleRate = sampleRates[srId];
_stream->setSampleRate(sampleRate);
if (running) { if (running) {
doStop(); doStop();
doStart(); doStart();
} }
// TODO: Save to config config.aquire();
config.conf[_streamName]["devices"][devList[devId].name] = sampleRate;
config.release(true);
} }
// AudioDevice_t* dev = devices[devListId];
// ImGui::SetNextItemWidth(menuWidth);
// if (ImGui::Combo(("##_rtaudio_sink_sr_"+_streamName).c_str(), &dev->srId, dev->txtSampleRates.c_str())) {
// _stream->setSampleRate(dev->sampleRates[dev->srId]);
// if (running) {
// doStop();
// doStart();
// }
// // TODO: Save to config
// }
} }
private: private:
@ -96,7 +162,6 @@ private:
RtAudio::StreamParameters parameters; RtAudio::StreamParameters parameters;
parameters.deviceId = deviceIds[devId]; parameters.deviceId = deviceIds[devId];
parameters.nChannels = 2; parameters.nChannels = 2;
unsigned int sampleRate = 48000;
unsigned int bufferFrames = sampleRate / 60; unsigned int bufferFrames = sampleRate / 60;
RtAudio::StreamOptions opts; RtAudio::StreamOptions opts;
opts.flags = RTAUDIO_MINIMIZE_LATENCY; opts.flags = RTAUDIO_MINIMIZE_LATENCY;
@ -149,20 +214,16 @@ private:
int devId = 0; int devId = 0;
bool running = false; bool running = false;
const double POSSIBLE_SAMP_RATE[6] = { unsigned int defaultDevId = 0;
48000.0f,
44100.0f,
24000.0f,
22050.0f,
12000.0f,
11025.0f
};
std::vector<RtAudio::DeviceInfo> devList; std::vector<RtAudio::DeviceInfo> devList;
std::vector<unsigned int> deviceIds; std::vector<unsigned int> deviceIds;
std::string txtDevList; std::string txtDevList;
std::vector<unsigned int> sampleRates;
std::string sampleRatesTxt;
unsigned int sampleRate = 48000;
RtAudio audio; RtAudio audio;
}; };
@ -205,8 +266,10 @@ private:
}; };
MOD_EXPORT void _INIT_() { MOD_EXPORT void _INIT_() {
// Nothing here json def = json({});
// TODO: Do instancing here (in source modules as well) to prevent multiple loads config.setPath(options::opts.root + "/audio_sink_config.json");
config.load(def);
config.enableAutoSave();
} }
MOD_EXPORT void* _CREATE_INSTANCE_(std::string name) { MOD_EXPORT void* _CREATE_INSTANCE_(std::string name) {
@ -215,7 +278,8 @@ MOD_EXPORT void* _CREATE_INSTANCE_(std::string name) {
} }
MOD_EXPORT void _DELETE_INSTANCE_() { MOD_EXPORT void _DELETE_INSTANCE_() {
config.disableAutoSave();
config.save();
} }
MOD_EXPORT void _END_() { MOD_EXPORT void _END_() {