mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-02-02 21:04:45 +01:00
fix
This commit is contained in:
parent
19e516f206
commit
618d4ac4cc
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,4 +4,5 @@ build/
|
|||||||
*.dll
|
*.dll
|
||||||
*.exe
|
*.exe
|
||||||
*.zip
|
*.zip
|
||||||
|
*.wav
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
@ -22,10 +22,9 @@ public:
|
|||||||
AudioSink(SinkManager::Stream* stream, std::string streamName) {
|
AudioSink(SinkManager::Stream* stream, std::string streamName) {
|
||||||
_stream = stream;
|
_stream = stream;
|
||||||
_streamName = streamName;
|
_streamName = streamName;
|
||||||
audioStream = _stream->bindStream();
|
s2m.init(_stream->sinkOut);
|
||||||
s2m.init(audioStream);
|
|
||||||
monoRB.init(&s2m.out);
|
monoRB.init(&s2m.out);
|
||||||
stereoRB.init(audioStream);
|
stereoRB.init(_stream->sinkOut);
|
||||||
|
|
||||||
// Initialize PortAudio
|
// Initialize PortAudio
|
||||||
Pa_Initialize();
|
Pa_Initialize();
|
||||||
@ -68,7 +67,11 @@ public:
|
|||||||
defaultDev = devListId;
|
defaultDev = devListId;
|
||||||
}
|
}
|
||||||
dev.srId = 0;
|
dev.srId = 0;
|
||||||
devices.push_back(dev);
|
|
||||||
|
AudioDevice_t* _dev = new AudioDevice_t;
|
||||||
|
*_dev = dev;
|
||||||
|
devices.push_back(_dev);
|
||||||
|
|
||||||
deviceNames.push_back(deviceInfo->name);
|
deviceNames.push_back(deviceInfo->name);
|
||||||
txtDevList += deviceInfo->name;
|
txtDevList += deviceInfo->name;
|
||||||
txtDevList += '\0';
|
txtDevList += '\0';
|
||||||
@ -78,7 +81,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
~AudioSink() {
|
~AudioSink() {
|
||||||
|
for (auto const& dev : devices) {
|
||||||
|
delete dev;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
@ -98,6 +103,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void menuHandler() {
|
void menuHandler() {
|
||||||
|
float menuWidth = ImGui::GetContentRegionAvailWidth();
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(menuWidth);
|
||||||
if (ImGui::Combo(("##_audio_sink_dev_"+_streamName).c_str(), &devListId, txtDevList.c_str())) {
|
if (ImGui::Combo(("##_audio_sink_dev_"+_streamName).c_str(), &devListId, txtDevList.c_str())) {
|
||||||
// TODO: Load SR from config
|
// TODO: Load SR from config
|
||||||
if (running) {
|
if (running) {
|
||||||
@ -107,9 +115,11 @@ public:
|
|||||||
// TODO: Save to config
|
// TODO: Save to config
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioDevice_t dev = devices[devListId];
|
AudioDevice_t* dev = devices[devListId];
|
||||||
|
|
||||||
if (ImGui::Combo(("##_audio_sink_sr_"+_streamName).c_str(), &dev.srId, txtDevList.c_str())) {
|
ImGui::SetNextItemWidth(menuWidth);
|
||||||
|
if (ImGui::Combo(("##_audio_sink_sr_"+_streamName).c_str(), &dev->srId, dev->txtSampleRates.c_str())) {
|
||||||
|
_stream->setSampleRate(dev->sampleRates[dev->srId]);
|
||||||
if (running) {
|
if (running) {
|
||||||
doStop();
|
doStop();
|
||||||
doStart();
|
doStart();
|
||||||
@ -121,25 +131,27 @@ public:
|
|||||||
private:
|
private:
|
||||||
void doStart() {
|
void doStart() {
|
||||||
const PaDeviceInfo *deviceInfo;
|
const PaDeviceInfo *deviceInfo;
|
||||||
AudioDevice_t dev = devices[devListId];
|
AudioDevice_t* dev = devices[devListId];
|
||||||
PaStreamParameters outputParams;
|
PaStreamParameters outputParams;
|
||||||
deviceInfo = Pa_GetDeviceInfo(dev.index);
|
deviceInfo = Pa_GetDeviceInfo(dev->index);
|
||||||
outputParams.channelCount = 2;
|
outputParams.channelCount = 2;
|
||||||
outputParams.sampleFormat = paFloat32;
|
outputParams.sampleFormat = paFloat32;
|
||||||
outputParams.hostApiSpecificStreamInfo = NULL;
|
outputParams.hostApiSpecificStreamInfo = NULL;
|
||||||
outputParams.device = dev.index;
|
outputParams.device = dev->index;
|
||||||
outputParams.suggestedLatency = Pa_GetDeviceInfo(outputParams.device)->defaultLowOutputLatency;
|
outputParams.suggestedLatency = Pa_GetDeviceInfo(outputParams.device)->defaultLowOutputLatency;
|
||||||
PaError err;
|
PaError err;
|
||||||
|
|
||||||
float sampleRate = dev.sampleRates[dev.srId];
|
float sampleRate = dev->sampleRates[dev->srId];
|
||||||
int bufferSize = sampleRate / 60.0f;
|
int bufferSize = sampleRate / 60.0f;
|
||||||
|
|
||||||
if (dev.channels == 2) {
|
if (dev->channels == 2) {
|
||||||
stereoRB.data.setMaxLatency(bufferSize * 2);
|
stereoRB.data.setMaxLatency(bufferSize * 2);
|
||||||
|
stereoRB.start();
|
||||||
err = Pa_OpenStream(&stream, NULL, &outputParams, sampleRate, bufferSize, 0, _stereo_cb, this);
|
err = Pa_OpenStream(&stream, NULL, &outputParams, sampleRate, bufferSize, 0, _stereo_cb, this);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
monoRB.data.setMaxLatency(bufferSize * 2);
|
monoRB.data.setMaxLatency(bufferSize * 2);
|
||||||
|
monoRB.start();
|
||||||
err = Pa_OpenStream(&stream, NULL, &outputParams, sampleRate, bufferSize, 0, _mono_cb, this);
|
err = Pa_OpenStream(&stream, NULL, &outputParams, sampleRate, bufferSize, 0, _mono_cb, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,6 +170,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void doStop() {
|
void doStop() {
|
||||||
|
monoRB.stop();
|
||||||
|
stereoRB.stop();
|
||||||
monoRB.data.stopReader();
|
monoRB.data.stopReader();
|
||||||
stereoRB.data.stopReader();
|
stereoRB.data.stopReader();
|
||||||
Pa_StopStream(stream);
|
Pa_StopStream(stream);
|
||||||
@ -181,7 +195,6 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
SinkManager::Stream* _stream;
|
SinkManager::Stream* _stream;
|
||||||
dsp::stream<dsp::stereo_t>* audioStream;
|
|
||||||
dsp::StereoToMono s2m;
|
dsp::StereoToMono s2m;
|
||||||
dsp::RingBufferSink<float> monoRB;
|
dsp::RingBufferSink<float> monoRB;
|
||||||
dsp::RingBufferSink<dsp::stereo_t> stereoRB;
|
dsp::RingBufferSink<dsp::stereo_t> stereoRB;
|
||||||
@ -204,7 +217,7 @@ private:
|
|||||||
11025.0f
|
11025.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<AudioDevice_t> devices;
|
std::vector<AudioDevice_t*> devices;
|
||||||
std::vector<std::string> deviceNames;
|
std::vector<std::string> deviceNames;
|
||||||
std::string txtDevList;
|
std::string txtDevList;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <dsp/block.h>
|
#include <dsp/block.h>
|
||||||
#include <fftw3.h>
|
#include <fftw3.h>
|
||||||
|
#include <volk/volk.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
@ -127,4 +128,85 @@ namespace dsp {
|
|||||||
stream<float>* _in;
|
stream<float>* _in;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class Volume : public generic_block<Volume<T>> {
|
||||||
|
public:
|
||||||
|
Volume() {}
|
||||||
|
|
||||||
|
Volume(stream<T>* in, float volume) { init(in, volume); }
|
||||||
|
|
||||||
|
~Volume() { generic_block<Volume<T>>::stop(); }
|
||||||
|
|
||||||
|
void init(stream<T>* in, float volume) {
|
||||||
|
_in = in;
|
||||||
|
_volume = volume;
|
||||||
|
generic_block<Volume<T>>::registerInput(_in);
|
||||||
|
generic_block<Volume<T>>::registerOutput(&out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setInputSize(stream<T>* in) {
|
||||||
|
std::lock_guard<std::mutex> lck(generic_block<Volume<T>>::ctrlMtx);
|
||||||
|
generic_block<Volume<T>>::tempStop();
|
||||||
|
generic_block<Volume<T>>::unregisterInput(_in);
|
||||||
|
_in = in;
|
||||||
|
generic_block<Volume<T>>::registerInput(_in);
|
||||||
|
generic_block<Volume<T>>::tempStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setVolume(float volume) {
|
||||||
|
_volume = volume;
|
||||||
|
level = powf(_volume, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
float getVolume() {
|
||||||
|
return _volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMuted(bool muted) {
|
||||||
|
_muted = muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getMuted() {
|
||||||
|
return _muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
int run() {
|
||||||
|
count = _in->read();
|
||||||
|
if (count < 0) { return -1; }
|
||||||
|
|
||||||
|
if (out.aquire() < 0) { return -1; }
|
||||||
|
|
||||||
|
if (_muted) {
|
||||||
|
if constexpr (std::is_same_v<T, stereo_t>) {
|
||||||
|
memset(out.data, 0, sizeof(stereo_t) * count);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memset(out.data, 0, sizeof(float) * count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if constexpr (std::is_same_v<T, stereo_t>) {
|
||||||
|
volk_32f_s32f_multiply_32f((float*)out.data, (float*)_in->data, level, count * 2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
volk_32f_s32f_multiply_32f((float*)out.data, (float*)_in->data, level, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_in->flush();
|
||||||
|
out.write(count);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream<T> out;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int count;
|
||||||
|
float level = 1.0f;
|
||||||
|
float _volume = 1.0f;
|
||||||
|
bool _muted = false;
|
||||||
|
stream<T>* _in;
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
@ -9,6 +9,7 @@ public:
|
|||||||
~Event() {}
|
~Event() {}
|
||||||
|
|
||||||
struct EventHandler {
|
struct EventHandler {
|
||||||
|
EventHandler() {}
|
||||||
EventHandler(void (*handler)(T, void*), void* ctx) {
|
EventHandler(void (*handler)(T, void*), void* ctx) {
|
||||||
this->handler = handler;
|
this->handler = handler;
|
||||||
this->ctx = ctx;
|
this->ctx = ctx;
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include <watcher.h>
|
#include <watcher.h>
|
||||||
#include <module.h>
|
#include <module.h>
|
||||||
#include <signal_path/vfo_manager.h>
|
#include <signal_path/vfo_manager.h>
|
||||||
#include <signal_path/audio.h>
|
|
||||||
#include <gui/style.h>
|
#include <gui/style.h>
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <signal_path/signal_path.h>
|
#include <signal_path/signal_path.h>
|
||||||
@ -27,7 +26,6 @@
|
|||||||
#include <gui/menus/display.h>
|
#include <gui/menus/display.h>
|
||||||
#include <gui/menus/bandplan.h>
|
#include <gui/menus/bandplan.h>
|
||||||
#include <gui/menus/sink.h>
|
#include <gui/menus/sink.h>
|
||||||
#include <gui/menus/audio.h>
|
|
||||||
#include <gui/menus/scripting.h>
|
#include <gui/menus/scripting.h>
|
||||||
#include <gui/dialogs/credits.h>
|
#include <gui/dialogs/credits.h>
|
||||||
#include <signal_path/source.h>
|
#include <signal_path/source.h>
|
||||||
@ -68,8 +66,6 @@ void fftHandler(dsp::complex_t* samples, int count, void* ctx) {
|
|||||||
|
|
||||||
watcher<uint64_t> freq((uint64_t)90500000);
|
watcher<uint64_t> freq((uint64_t)90500000);
|
||||||
watcher<double> vfoFreq(92000000.0);
|
watcher<double> vfoFreq(92000000.0);
|
||||||
float dummyVolume = 1.0;
|
|
||||||
float* volume = &dummyVolume;
|
|
||||||
float fftMin = -70.0;
|
float fftMin = -70.0;
|
||||||
float fftMax = 0.0;
|
float fftMax = 0.0;
|
||||||
watcher<double> offset(0.0, true);
|
watcher<double> offset(0.0, true);
|
||||||
@ -97,7 +93,6 @@ void windowInit() {
|
|||||||
|
|
||||||
gui::menu.registerEntry("Source", sourecmenu::draw, NULL);
|
gui::menu.registerEntry("Source", sourecmenu::draw, NULL);
|
||||||
gui::menu.registerEntry("Sinks", sinkmenu::draw, NULL);
|
gui::menu.registerEntry("Sinks", sinkmenu::draw, NULL);
|
||||||
gui::menu.registerEntry("Audio", audiomenu::draw, NULL);
|
|
||||||
gui::menu.registerEntry("Scripting", scriptingmenu::draw, NULL);
|
gui::menu.registerEntry("Scripting", scriptingmenu::draw, NULL);
|
||||||
gui::menu.registerEntry("Band Plan", bandplanmenu::draw, NULL);
|
gui::menu.registerEntry("Band Plan", bandplanmenu::draw, NULL);
|
||||||
gui::menu.registerEntry("Display", displaymenu::draw, NULL);
|
gui::menu.registerEntry("Display", displaymenu::draw, NULL);
|
||||||
@ -120,7 +115,6 @@ void windowInit() {
|
|||||||
|
|
||||||
sourecmenu::init();
|
sourecmenu::init();
|
||||||
sinkmenu::init();
|
sinkmenu::init();
|
||||||
audiomenu::init();
|
|
||||||
scriptingmenu::init();
|
scriptingmenu::init();
|
||||||
bandplanmenu::init();
|
bandplanmenu::init();
|
||||||
displaymenu::init();
|
displaymenu::init();
|
||||||
@ -271,10 +265,6 @@ void drawWindow() {
|
|||||||
gui::waterfall.selectedVFOChanged = false;
|
gui::waterfall.selectedVFOChanged = false;
|
||||||
gui::freqSelect.setFrequency(vfo->generalOffset + gui::waterfall.getCenterFrequency());
|
gui::freqSelect.setFrequency(vfo->generalOffset + gui::waterfall.getCenterFrequency());
|
||||||
gui::freqSelect.frequencyChanged = false;
|
gui::freqSelect.frequencyChanged = false;
|
||||||
audioStreamName = audio::getNameFromVFO(gui::waterfall.selectedVFO);
|
|
||||||
if (audioStreamName != "") {
|
|
||||||
volume = &audio::streams[audioStreamName]->volume;
|
|
||||||
}
|
|
||||||
core::configManager.aquire();
|
core::configManager.aquire();
|
||||||
core::configManager.conf["frequency"] = gui::freqSelect.frequency;
|
core::configManager.conf["frequency"] = gui::freqSelect.frequency;
|
||||||
core::configManager.release(true);
|
core::configManager.release(true);
|
||||||
@ -339,19 +329,7 @@ void drawWindow() {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 8);
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 8);
|
||||||
ImGui::SetNextItemWidth(200);
|
sigpath::sinkManager.showVolumeSlider(gui::waterfall.selectedVFO, "##_sdrpp_main_volume_", 200);
|
||||||
if (ImGui::SliderFloat("##_2_", volume, 0.0, 1.0, "")) {
|
|
||||||
if (audioStreamName != "") {
|
|
||||||
core::configManager.aquire();
|
|
||||||
if (!core::configManager.conf["audio"].contains(audioStreamName)) {
|
|
||||||
//saveAudioConfig(audioStreamName);
|
|
||||||
// TODO: FIX THIS SHIT
|
|
||||||
}
|
|
||||||
audio::streams[audioStreamName]->audio->setVolume(*volume);
|
|
||||||
core::configManager.conf["audio"][audioStreamName]["volume"] = *volume;
|
|
||||||
core::configManager.release(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
@ -1,138 +0,0 @@
|
|||||||
#include <gui/menus/audio.h>
|
|
||||||
#include <gui/bandplan.h>
|
|
||||||
#include <gui/gui.h>
|
|
||||||
#include <core.h>
|
|
||||||
#include <signal_path/audio.h>
|
|
||||||
|
|
||||||
namespace audiomenu {
|
|
||||||
// Note: Those are supposed to be the ones from the volume slider
|
|
||||||
std::string audioStreamName;
|
|
||||||
float* volume;
|
|
||||||
|
|
||||||
void loadAudioConfig(std::string name) {
|
|
||||||
json audioSettings = core::configManager.conf["audio"][name];
|
|
||||||
std::string devName = audioSettings["device"];
|
|
||||||
auto _devIt = std::find(audio::streams[name]->audio->deviceNames.begin(), audio::streams[name]->audio->deviceNames.end(), devName);
|
|
||||||
|
|
||||||
// If audio device doesn't exist anymore
|
|
||||||
if (_devIt == audio::streams[name]->audio->deviceNames.end()) {
|
|
||||||
audio::streams[name]->audio->setToDefault();
|
|
||||||
int deviceId = audio::streams[name]->audio->getDeviceId();
|
|
||||||
audio::setAudioDevice(name, deviceId, audio::streams[name]->audio->devices[deviceId].sampleRates[0]);
|
|
||||||
audio::streams[name]->sampleRateId = 0;
|
|
||||||
audio::streams[name]->volume = audioSettings["volume"];
|
|
||||||
audio::streams[name]->audio->setVolume(audio::streams[name]->volume);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int deviceId = std::distance(audio::streams[name]->audio->deviceNames.begin(), _devIt);
|
|
||||||
float sr = audioSettings["sampleRate"];
|
|
||||||
auto _srIt = std::find(audio::streams[name]->audio->devices[deviceId].sampleRates.begin(), audio::streams[name]->audio->devices[deviceId].sampleRates.end(), sr);
|
|
||||||
|
|
||||||
// If sample rate doesn't exist anymore
|
|
||||||
if (_srIt == audio::streams[name]->audio->devices[deviceId].sampleRates.end()) {
|
|
||||||
audio::streams[name]->sampleRateId = 0;
|
|
||||||
audio::setAudioDevice(name, deviceId, audio::streams[name]->audio->devices[deviceId].sampleRates[0]);
|
|
||||||
audio::streams[name]->volume = audioSettings["volume"];
|
|
||||||
audio::streams[name]->audio->setVolume(audio::streams[name]->volume);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int samplerateId = std::distance(audio::streams[name]->audio->devices[deviceId].sampleRates.begin(), _srIt);
|
|
||||||
audio::streams[name]->sampleRateId = samplerateId;
|
|
||||||
audio::setAudioDevice(name, deviceId, audio::streams[name]->audio->devices[deviceId].sampleRates[samplerateId]);
|
|
||||||
audio::streams[name]->deviceId = deviceId;
|
|
||||||
audio::streams[name]->volume = audioSettings["volume"];
|
|
||||||
audio::streams[name]->audio->setVolume(audio::streams[name]->volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
void saveAudioConfig(std::string name) {
|
|
||||||
core::configManager.conf["audio"][name]["device"] = audio::streams[name]->audio->deviceNames[audio::streams[name]->deviceId];
|
|
||||||
core::configManager.conf["audio"][name]["volume"] = audio::streams[name]->volume;
|
|
||||||
core::configManager.conf["audio"][name]["sampleRate"] = audio::streams[name]->sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init() {
|
|
||||||
for (auto [name, stream] : audio::streams) {
|
|
||||||
if (core::configManager.conf["audio"].contains(name)) {
|
|
||||||
bool running = audio::streams[name]->running;
|
|
||||||
audio::stopStream(name);
|
|
||||||
loadAudioConfig(name);
|
|
||||||
if (running) {
|
|
||||||
audio::startStream(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
audioStreamName = audio::getNameFromVFO(gui::waterfall.selectedVFO);
|
|
||||||
if (audioStreamName != "") {
|
|
||||||
volume = &audio::streams[audioStreamName]->volume;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(void* ctx) {
|
|
||||||
float menuColumnWidth = ImGui::GetContentRegionAvailWidth();
|
|
||||||
int count = 0;
|
|
||||||
int maxCount = audio::streams.size();
|
|
||||||
for (auto const& [name, stream] : audio::streams) {
|
|
||||||
int deviceId;
|
|
||||||
float vol = 1.0f;
|
|
||||||
deviceId = stream->audio->getDeviceId();
|
|
||||||
|
|
||||||
ImGui::SetCursorPosX((menuColumnWidth / 2.0f) - (ImGui::CalcTextSize(name.c_str()).x / 2.0f));
|
|
||||||
ImGui::Text("%s", name.c_str());
|
|
||||||
|
|
||||||
ImGui::PushItemWidth(menuColumnWidth);
|
|
||||||
bool running = stream->running;
|
|
||||||
if (ImGui::Combo(("##_audio_dev_0_"+ name).c_str(), &stream->deviceId, stream->audio->devTxtList.c_str())) {
|
|
||||||
audio::stopStream(name);
|
|
||||||
audio::setAudioDevice(name, stream->deviceId, stream->audio->devices[deviceId].sampleRates[0]);
|
|
||||||
if (running) {
|
|
||||||
audio::startStream(name);
|
|
||||||
}
|
|
||||||
stream->sampleRateId = 0;
|
|
||||||
|
|
||||||
// Create config if it doesn't exist
|
|
||||||
core::configManager.aquire();
|
|
||||||
if (!core::configManager.conf["audio"].contains(name)) {
|
|
||||||
saveAudioConfig(name);
|
|
||||||
}
|
|
||||||
core::configManager.conf["audio"][name]["device"] = stream->audio->deviceNames[stream->deviceId];
|
|
||||||
core::configManager.conf["audio"][name]["sampleRate"] = stream->audio->devices[stream->deviceId].sampleRates[0];
|
|
||||||
core::configManager.release(true);
|
|
||||||
}
|
|
||||||
if (ImGui::Combo(("##_audio_sr_0_" + name).c_str(), &stream->sampleRateId, stream->audio->devices[deviceId].txtSampleRates.c_str())) {
|
|
||||||
audio::stopStream(name);
|
|
||||||
audio::setSampleRate(name, stream->audio->devices[deviceId].sampleRates[stream->sampleRateId]);
|
|
||||||
if (running) {
|
|
||||||
audio::startStream(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create config if it doesn't exist
|
|
||||||
core::configManager.aquire();
|
|
||||||
if (!core::configManager.conf["audio"].contains(name)) {
|
|
||||||
saveAudioConfig(name);
|
|
||||||
}
|
|
||||||
core::configManager.conf["audio"][name]["sampleRate"] = stream->audio->devices[deviceId].sampleRates[stream->sampleRateId];
|
|
||||||
core::configManager.release(true);
|
|
||||||
}
|
|
||||||
if (ImGui::SliderFloat(("##_audio_vol_0_" + name).c_str(), &stream->volume, 0.0f, 1.0f, "")) {
|
|
||||||
stream->audio->setVolume(stream->volume);
|
|
||||||
|
|
||||||
// Create config if it doesn't exist
|
|
||||||
core::configManager.aquire();
|
|
||||||
if (!core::configManager.conf["audio"].contains(name)) {
|
|
||||||
saveAudioConfig(name);
|
|
||||||
}
|
|
||||||
core::configManager.conf["audio"][name]["volume"] = stream->volume;
|
|
||||||
core::configManager.release(true);
|
|
||||||
}
|
|
||||||
ImGui::PopItemWidth();
|
|
||||||
count++;
|
|
||||||
if (count < maxCount) {
|
|
||||||
ImGui::Spacing();
|
|
||||||
ImGui::Separator();
|
|
||||||
}
|
|
||||||
ImGui::Spacing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,6 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace audiomenu {
|
|
||||||
void init();
|
|
||||||
void draw(void* ctx);
|
|
||||||
};
|
|
@ -1,9 +1,12 @@
|
|||||||
#include <gui/menus/sink.h>
|
#include <gui/menus/sink.h>
|
||||||
#include <signal_path/signal_path.h>
|
#include <signal_path/signal_path.h>
|
||||||
|
#include <core.h>
|
||||||
|
|
||||||
namespace sinkmenu {
|
namespace sinkmenu {
|
||||||
void init() {
|
void init() {
|
||||||
|
core::configManager.aquire();
|
||||||
|
sigpath::sinkManager.loadSinksFromConfig();
|
||||||
|
core::configManager.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(void* ctx) {
|
void draw(void* ctx) {
|
||||||
|
@ -9,12 +9,21 @@ namespace sourecmenu {
|
|||||||
double freqOffset = 0.0;
|
double freqOffset = 0.0;
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
// Select default
|
core::configManager.aquire();
|
||||||
// TODO: Replace by setting
|
std::string name = core::configManager.conf["source"];
|
||||||
if (sigpath::sourceManager.sourceNames.size() > 0) {
|
auto it = std::find(sigpath::sourceManager.sourceNames.begin(), sigpath::sourceManager.sourceNames.end(), name);
|
||||||
|
if (it != sigpath::sourceManager.sourceNames.end()) {
|
||||||
|
sigpath::sourceManager.selectSource(name);
|
||||||
|
sourceId = std::distance(sigpath::sourceManager.sourceNames.begin(), it);
|
||||||
|
}
|
||||||
|
else if (sigpath::sourceManager.sourceNames.size() > 0) {
|
||||||
sigpath::sourceManager.selectSource(sigpath::sourceManager.sourceNames[0]);
|
sigpath::sourceManager.selectSource(sigpath::sourceManager.sourceNames[0]);
|
||||||
}
|
}
|
||||||
sigpath::sourceManager.setTuningOffset(0);
|
else {
|
||||||
|
spdlog::warn("No source available...");
|
||||||
|
}
|
||||||
|
sigpath::sourceManager.setTuningOffset(core::configManager.conf["offset"]);
|
||||||
|
core::configManager.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(void* ctx) {
|
void draw(void* ctx) {
|
||||||
@ -28,12 +37,18 @@ namespace sourecmenu {
|
|||||||
ImGui::SetNextItemWidth(itemWidth);
|
ImGui::SetNextItemWidth(itemWidth);
|
||||||
if (ImGui::Combo("##source", &sourceId, items.c_str())) {
|
if (ImGui::Combo("##source", &sourceId, items.c_str())) {
|
||||||
sigpath::sourceManager.selectSource(sigpath::sourceManager.sourceNames[sourceId]);
|
sigpath::sourceManager.selectSource(sigpath::sourceManager.sourceNames[sourceId]);
|
||||||
|
core::configManager.aquire();
|
||||||
|
core::configManager.conf["source"] = sigpath::sourceManager.sourceNames[sourceId];
|
||||||
|
core::configManager.release(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
sigpath::sourceManager.showSelectedMenu();
|
sigpath::sourceManager.showSelectedMenu();
|
||||||
ImGui::SetNextItemWidth(itemWidth - ImGui::CalcTextSize("Offset (Hz)").x - 10);
|
ImGui::SetNextItemWidth(itemWidth - ImGui::CalcTextSize("Offset (Hz)").x - 10);
|
||||||
if (ImGui::InputDouble("Offset (Hz)##freq_offset", &freqOffset, 1.0, 100.0)) {
|
if (ImGui::InputDouble("Offset (Hz)##freq_offset", &freqOffset, 1.0, 100.0)) {
|
||||||
sigpath::sourceManager.setTuningOffset(freqOffset);
|
sigpath::sourceManager.setTuningOffset(freqOffset);
|
||||||
|
core::configManager.aquire();
|
||||||
|
core::configManager.conf["offset"] = freqOffset;
|
||||||
|
core::configManager.release(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,311 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <thread>
|
|
||||||
#include <dsp/stream.h>
|
|
||||||
#include <dsp/types.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <portaudio.h>
|
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
#include <dsp/sink.h>
|
|
||||||
|
|
||||||
namespace io {
|
|
||||||
class AudioSink {
|
|
||||||
public:
|
|
||||||
enum {
|
|
||||||
MONO,
|
|
||||||
STEREO,
|
|
||||||
_TYPE_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AudioDevice_t {
|
|
||||||
std::string name;
|
|
||||||
int index;
|
|
||||||
int channels;
|
|
||||||
std::vector<double> sampleRates;
|
|
||||||
std::string txtSampleRates;
|
|
||||||
};
|
|
||||||
|
|
||||||
AudioSink() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioSink(int bufferSize) { init(bufferSize); }
|
|
||||||
|
|
||||||
void init(int bufferSize) {
|
|
||||||
_bufferSize = bufferSize;
|
|
||||||
monoBuffer = new float[_bufferSize];
|
|
||||||
stereoBuffer = new dsp::stereo_t[_bufferSize];
|
|
||||||
_volume = 1.0f;
|
|
||||||
|
|
||||||
monoSink.init(&monoDummy);
|
|
||||||
stereoSink.init(&stereoDummy);
|
|
||||||
|
|
||||||
Pa_Initialize();
|
|
||||||
|
|
||||||
devTxtList = "";
|
|
||||||
int devCount = Pa_GetDeviceCount();
|
|
||||||
devIndex = Pa_GetDefaultOutputDevice();
|
|
||||||
const PaDeviceInfo *deviceInfo;
|
|
||||||
PaStreamParameters outputParams;
|
|
||||||
outputParams.sampleFormat = paFloat32;
|
|
||||||
outputParams.hostApiSpecificStreamInfo = NULL;
|
|
||||||
for(int i = 0; i < devCount; i++) {
|
|
||||||
deviceInfo = Pa_GetDeviceInfo(i);
|
|
||||||
if (deviceInfo->maxOutputChannels < 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
AudioDevice_t dev;
|
|
||||||
dev.name = deviceInfo->name;
|
|
||||||
dev.index = i;
|
|
||||||
dev.channels = std::min<int>(deviceInfo->maxOutputChannels, 2);
|
|
||||||
dev.sampleRates.clear();
|
|
||||||
dev.txtSampleRates = "";
|
|
||||||
for (int j = 0; j < 6; j++) {
|
|
||||||
outputParams.channelCount = dev.channels;
|
|
||||||
outputParams.device = dev.index;
|
|
||||||
outputParams.suggestedLatency = deviceInfo->defaultLowOutputLatency;
|
|
||||||
PaError err = Pa_IsFormatSupported(NULL, &outputParams, POSSIBLE_SAMP_RATE[j]);
|
|
||||||
if (err != paFormatIsSupported) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
dev.sampleRates.push_back(POSSIBLE_SAMP_RATE[j]);
|
|
||||||
dev.txtSampleRates += std::to_string((int)POSSIBLE_SAMP_RATE[j]);
|
|
||||||
dev.txtSampleRates += '\0';
|
|
||||||
}
|
|
||||||
if (dev.sampleRates.size() == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (i == devIndex) {
|
|
||||||
devListIndex = devices.size();
|
|
||||||
defaultDev = devListIndex;
|
|
||||||
}
|
|
||||||
devices.push_back(dev);
|
|
||||||
deviceNames.push_back(deviceInfo->name);
|
|
||||||
devTxtList += deviceInfo->name;
|
|
||||||
devTxtList += '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMonoInput(dsp::stream<float>* input) {
|
|
||||||
monoSink.setInput(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStereoInput(dsp::stream<dsp::stereo_t>* input) {
|
|
||||||
stereoSink.setInput(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setVolume(float volume) {
|
|
||||||
_volume = volume;
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() {
|
|
||||||
if (running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const PaDeviceInfo *deviceInfo;
|
|
||||||
AudioDevice_t dev = devices[devListIndex];
|
|
||||||
PaStreamParameters outputParams;
|
|
||||||
deviceInfo = Pa_GetDeviceInfo(dev.index);
|
|
||||||
outputParams.channelCount = 2;
|
|
||||||
outputParams.sampleFormat = paFloat32;
|
|
||||||
outputParams.hostApiSpecificStreamInfo = NULL;
|
|
||||||
outputParams.device = dev.index;
|
|
||||||
outputParams.suggestedLatency = Pa_GetDeviceInfo(outputParams.device)->defaultLowOutputLatency;
|
|
||||||
PaError err;
|
|
||||||
if (streamType == MONO) {
|
|
||||||
err = Pa_OpenStream(&stream, NULL, &outputParams, _sampleRate, _bufferSize, 0,
|
|
||||||
(dev.channels == 2) ? _mono_to_stereo_callback : _mono_to_mono_callback, this);
|
|
||||||
monoSink.start();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
err = Pa_OpenStream(&stream, NULL, &outputParams, _sampleRate, _bufferSize, 0,
|
|
||||||
(dev.channels == 2) ? _stereo_to_stereo_callback : _stereo_to_mono_callback, this);
|
|
||||||
stereoSink.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err != 0) {
|
|
||||||
spdlog::error("Error while opening audio stream: ({0}) => {1}", err, Pa_GetErrorText(err));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
err = Pa_StartStream(stream);
|
|
||||||
if (err != 0) {
|
|
||||||
spdlog::error("Error while starting audio stream: ({0}) => {1}", err, Pa_GetErrorText(err));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
spdlog::info("Audio device open.");
|
|
||||||
running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stop() {
|
|
||||||
if (!running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (streamType == MONO) {
|
|
||||||
monoSink.stop();
|
|
||||||
monoSink.data.stopReader();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stereoSink.stop();
|
|
||||||
stereoSink.data.stopReader();
|
|
||||||
}
|
|
||||||
Pa_StopStream(stream);
|
|
||||||
Pa_CloseStream(stream);
|
|
||||||
if (streamType == MONO) {
|
|
||||||
monoSink.data.clearReadStop();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stereoSink.data.clearReadStop();
|
|
||||||
}
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBlockSize(int blockSize) {
|
|
||||||
if (running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_bufferSize = blockSize;
|
|
||||||
delete[] monoBuffer;
|
|
||||||
delete[] stereoBuffer;
|
|
||||||
monoBuffer = new float[_bufferSize];
|
|
||||||
stereoBuffer = new dsp::stereo_t[_bufferSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSampleRate(float sampleRate) {
|
|
||||||
_sampleRate = sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDevice(int id) {
|
|
||||||
if (devListIndex == id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
devListIndex = id;
|
|
||||||
devIndex = devices[id].index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setToDefault() {
|
|
||||||
setDevice(defaultDev);
|
|
||||||
}
|
|
||||||
|
|
||||||
int getDeviceId() {
|
|
||||||
return devListIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStreamType(int type) {
|
|
||||||
streamType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string devTxtList;
|
|
||||||
std::vector<AudioDevice_t> devices;
|
|
||||||
std::vector<std::string> deviceNames;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static int _mono_to_mono_callback(const void *input,
|
|
||||||
void *output,
|
|
||||||
unsigned long frameCount,
|
|
||||||
const PaStreamCallbackTimeInfo* timeInfo,
|
|
||||||
PaStreamCallbackFlags statusFlags, void *userData ) {
|
|
||||||
AudioSink* _this = (AudioSink*)userData;
|
|
||||||
float* outbuf = (float*)output;
|
|
||||||
if (_this->monoSink.data.read(_this->monoBuffer, frameCount) < 0) {
|
|
||||||
memset(outbuf, 0, sizeof(float) * frameCount);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float vol = powf(_this->_volume, 2);
|
|
||||||
for (int i = 0; i < frameCount; i++) {
|
|
||||||
outbuf[i] = _this->monoBuffer[i] * vol;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _stereo_to_stereo_callback(const void *input,
|
|
||||||
void *output,
|
|
||||||
unsigned long frameCount,
|
|
||||||
const PaStreamCallbackTimeInfo* timeInfo,
|
|
||||||
PaStreamCallbackFlags statusFlags, void *userData ) {
|
|
||||||
AudioSink* _this = (AudioSink*)userData;
|
|
||||||
dsp::stereo_t* outbuf = (dsp::stereo_t*)output;
|
|
||||||
if (_this->stereoSink.data.read(_this->stereoBuffer, frameCount) < 0) {
|
|
||||||
memset(outbuf, 0, sizeof(dsp::stereo_t) * frameCount);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: Calculate the power in the UI instead of here
|
|
||||||
|
|
||||||
float vol = powf(_this->_volume, 2);
|
|
||||||
for (int i = 0; i < frameCount; i++) {
|
|
||||||
outbuf[i].l = _this->stereoBuffer[i].l * vol;
|
|
||||||
outbuf[i].r = _this->stereoBuffer[i].r * vol;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _mono_to_stereo_callback(const void *input,
|
|
||||||
void *output,
|
|
||||||
unsigned long frameCount,
|
|
||||||
const PaStreamCallbackTimeInfo* timeInfo,
|
|
||||||
PaStreamCallbackFlags statusFlags, void *userData ) {
|
|
||||||
AudioSink* _this = (AudioSink*)userData;
|
|
||||||
dsp::stereo_t* outbuf = (dsp::stereo_t*)output;
|
|
||||||
if (_this->monoSink.data.read(_this->monoBuffer, frameCount) < 0) {
|
|
||||||
memset(outbuf, 0, sizeof(dsp::stereo_t) * frameCount);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float vol = powf(_this->_volume, 2);
|
|
||||||
for (int i = 0; i < frameCount; i++) {
|
|
||||||
outbuf[i].l = _this->monoBuffer[i] * vol;
|
|
||||||
outbuf[i].r = _this->monoBuffer[i] * vol;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _stereo_to_mono_callback(const void *input,
|
|
||||||
void *output,
|
|
||||||
unsigned long frameCount,
|
|
||||||
const PaStreamCallbackTimeInfo* timeInfo,
|
|
||||||
PaStreamCallbackFlags statusFlags, void *userData ) {
|
|
||||||
AudioSink* _this = (AudioSink*)userData;
|
|
||||||
float* outbuf = (float*)output;
|
|
||||||
if (_this->stereoSink.data.read(_this->stereoBuffer, frameCount) < 0) {
|
|
||||||
memset(outbuf, 0, sizeof(float) * frameCount);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: Calculate the power in the UI instead of here
|
|
||||||
|
|
||||||
float vol = powf(_this->_volume, 2);
|
|
||||||
for (int i = 0; i < frameCount; i++) {
|
|
||||||
outbuf[i] = ((_this->stereoBuffer[i].l + _this->stereoBuffer[i].r) / 2.0f) * vol;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double POSSIBLE_SAMP_RATE[6] = {
|
|
||||||
48000.0f,
|
|
||||||
44100.0f,
|
|
||||||
24000.0f,
|
|
||||||
22050.0f,
|
|
||||||
12000.0f,
|
|
||||||
11025.0f
|
|
||||||
};
|
|
||||||
|
|
||||||
int streamType;
|
|
||||||
int devIndex;
|
|
||||||
int devListIndex;
|
|
||||||
int defaultDev;
|
|
||||||
double _sampleRate;
|
|
||||||
int _bufferSize;
|
|
||||||
dsp::stream<float> monoDummy;
|
|
||||||
dsp::stream<dsp::stereo_t> stereoDummy;
|
|
||||||
dsp::RingBufferSink<float> monoSink;
|
|
||||||
dsp::RingBufferSink<dsp::stereo_t> stereoSink;
|
|
||||||
float* monoBuffer;
|
|
||||||
dsp::stereo_t* stereoBuffer;
|
|
||||||
float _volume = 1.0f;
|
|
||||||
PaStream *stream;
|
|
||||||
bool running = false;
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,314 +0,0 @@
|
|||||||
#include <signal_path/audio.h>
|
|
||||||
|
|
||||||
namespace audio {
|
|
||||||
std::map<std::string, AudioStream_t*> streams;
|
|
||||||
|
|
||||||
double registerMonoStream(dsp::stream<float>* stream, std::string name, std::string vfoName, int (*sampleRateChangeHandler)(void* ctx, double sampleRate), void* ctx) {
|
|
||||||
AudioStream_t* astr = new AudioStream_t;
|
|
||||||
astr->type = STREAM_TYPE_MONO;
|
|
||||||
astr->ctx = ctx;
|
|
||||||
astr->audio = new io::AudioSink;
|
|
||||||
astr->audio->init(1);
|
|
||||||
astr->deviceId = astr->audio->getDeviceId();
|
|
||||||
double sampleRate = astr->audio->devices[astr->deviceId].sampleRates[0];
|
|
||||||
int blockSize = sampleRate / 200.0; // default block size
|
|
||||||
astr->monoAudioStream = new dsp::stream<float>;
|
|
||||||
astr->audio->setBlockSize(blockSize);
|
|
||||||
astr->audio->setStreamType(io::AudioSink::MONO);
|
|
||||||
astr->audio->setMonoInput(astr->monoAudioStream);
|
|
||||||
astr->audio->setSampleRate(sampleRate);
|
|
||||||
astr->blockSize = blockSize;
|
|
||||||
astr->sampleRate = sampleRate;
|
|
||||||
astr->monoStream = stream;
|
|
||||||
astr->sampleRateChangeHandler = sampleRateChangeHandler;
|
|
||||||
astr->monoDynSplit = new dsp::Splitter<float>(stream);
|
|
||||||
astr->monoDynSplit->bindStream(astr->monoAudioStream);
|
|
||||||
astr->running = false;
|
|
||||||
astr->volume = 1.0f;
|
|
||||||
astr->sampleRateId = 0;
|
|
||||||
astr->vfoName = vfoName;
|
|
||||||
streams[name] = astr;
|
|
||||||
return sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
double registerStereoStream(dsp::stream<dsp::stereo_t>* stream, std::string name, std::string vfoName, int (*sampleRateChangeHandler)(void* ctx, double sampleRate), void* ctx) {
|
|
||||||
AudioStream_t* astr = new AudioStream_t;
|
|
||||||
astr->type = STREAM_TYPE_STEREO;
|
|
||||||
astr->ctx = ctx;
|
|
||||||
astr->audio = new io::AudioSink;
|
|
||||||
astr->audio->init(1);
|
|
||||||
double sampleRate = astr->audio->devices[astr->audio->getDeviceId()].sampleRates[0];
|
|
||||||
int blockSize = sampleRate / 200.0; // default block size
|
|
||||||
astr->stereoAudioStream = new dsp::stream<dsp::stereo_t>;
|
|
||||||
astr->audio->setBlockSize(blockSize);
|
|
||||||
astr->audio->setStreamType(io::AudioSink::STEREO);
|
|
||||||
astr->audio->setStereoInput(astr->stereoAudioStream);
|
|
||||||
astr->audio->setSampleRate(sampleRate);
|
|
||||||
astr->blockSize = blockSize;
|
|
||||||
astr->sampleRate = sampleRate;
|
|
||||||
astr->stereoStream = stream;
|
|
||||||
astr->sampleRateChangeHandler = sampleRateChangeHandler;
|
|
||||||
astr->stereoDynSplit = new dsp::Splitter<dsp::stereo_t>(stream);
|
|
||||||
astr->stereoDynSplit->bindStream(astr->stereoAudioStream);
|
|
||||||
astr->running = false;
|
|
||||||
streams[name] = astr;
|
|
||||||
astr->vfoName = vfoName;
|
|
||||||
return sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startStream(std::string name) {
|
|
||||||
AudioStream_t* astr = streams[name];
|
|
||||||
if (astr->running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (astr->type == STREAM_TYPE_MONO) {
|
|
||||||
astr->monoDynSplit->start();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
astr->stereoDynSplit->start();
|
|
||||||
}
|
|
||||||
astr->audio->start();
|
|
||||||
astr->running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopStream(std::string name) {
|
|
||||||
AudioStream_t* astr = streams[name];
|
|
||||||
if (!astr->running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (astr->type == STREAM_TYPE_MONO) {
|
|
||||||
astr->monoDynSplit->stop();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
astr->stereoDynSplit->stop();
|
|
||||||
}
|
|
||||||
astr->audio->stop();
|
|
||||||
astr->running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeStream(std::string name) {
|
|
||||||
AudioStream_t* astr = streams[name];
|
|
||||||
stopStream(name);
|
|
||||||
for (int i = 0; i < astr->boundStreams.size(); i++) {
|
|
||||||
astr->boundStreams[i].streamRemovedHandler(astr->ctx);
|
|
||||||
}
|
|
||||||
delete astr->monoDynSplit;
|
|
||||||
}
|
|
||||||
|
|
||||||
dsp::stream<float>* bindToStreamMono(std::string name, void (*streamRemovedHandler)(void* ctx), void (*sampleRateChangeHandler)(void* ctx, double sampleRate, int blockSize), void* ctx) {
|
|
||||||
AudioStream_t* astr = streams[name];
|
|
||||||
BoundStream_t bstr;
|
|
||||||
bstr.type = STREAM_TYPE_MONO;
|
|
||||||
bstr.ctx = ctx;
|
|
||||||
bstr.streamRemovedHandler = streamRemovedHandler;
|
|
||||||
bstr.sampleRateChangeHandler = sampleRateChangeHandler;
|
|
||||||
if (astr->type == STREAM_TYPE_MONO) {
|
|
||||||
bstr.monoStream = new dsp::stream<float>;
|
|
||||||
astr->monoDynSplit->stop();
|
|
||||||
astr->monoDynSplit->bindStream(bstr.monoStream);
|
|
||||||
if (astr->running) {
|
|
||||||
astr->monoDynSplit->start();
|
|
||||||
}
|
|
||||||
astr->boundStreams.push_back(bstr);
|
|
||||||
return bstr.monoStream;
|
|
||||||
}
|
|
||||||
bstr.stereoStream = new dsp::stream<dsp::stereo_t>;
|
|
||||||
bstr.s2m = new dsp::StereoToMono(bstr.stereoStream);
|
|
||||||
bstr.monoStream = &bstr.s2m->out;
|
|
||||||
astr->stereoDynSplit->stop();
|
|
||||||
astr->stereoDynSplit->bindStream(bstr.stereoStream);
|
|
||||||
if (astr->running) {
|
|
||||||
astr->stereoDynSplit->start();
|
|
||||||
}
|
|
||||||
bstr.s2m->start();
|
|
||||||
astr->boundStreams.push_back(bstr);
|
|
||||||
return bstr.monoStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
dsp::stream<dsp::stereo_t>* bindToStreamStereo(std::string name, void (*streamRemovedHandler)(void* ctx), void (*sampleRateChangeHandler)(void* ctx, double sampleRate, int blockSize), void* ctx) {
|
|
||||||
AudioStream_t* astr = streams[name];
|
|
||||||
BoundStream_t bstr;
|
|
||||||
bstr.type = STREAM_TYPE_STEREO;
|
|
||||||
bstr.ctx = ctx;
|
|
||||||
bstr.streamRemovedHandler = streamRemovedHandler;
|
|
||||||
bstr.sampleRateChangeHandler = sampleRateChangeHandler;
|
|
||||||
if (astr->type == STREAM_TYPE_STEREO) {
|
|
||||||
bstr.stereoStream = new dsp::stream<dsp::stereo_t>;
|
|
||||||
astr->stereoDynSplit->stop();
|
|
||||||
astr->stereoDynSplit->bindStream(bstr.stereoStream);
|
|
||||||
if (astr->running) {
|
|
||||||
astr->stereoDynSplit->start();
|
|
||||||
}
|
|
||||||
astr->boundStreams.push_back(bstr);
|
|
||||||
return bstr.stereoStream;
|
|
||||||
}
|
|
||||||
bstr.monoStream = new dsp::stream<float>;
|
|
||||||
bstr.m2s = new dsp::MonoToStereo(bstr.monoStream);
|
|
||||||
bstr.stereoStream = &bstr.m2s->out;
|
|
||||||
astr->monoDynSplit->stop();
|
|
||||||
astr->monoDynSplit->bindStream(bstr.monoStream);
|
|
||||||
if (astr->running) {
|
|
||||||
astr->monoDynSplit->start();
|
|
||||||
}
|
|
||||||
bstr.m2s->start();
|
|
||||||
astr->boundStreams.push_back(bstr);
|
|
||||||
return bstr.stereoStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBlockSize(std::string name, int blockSize) {
|
|
||||||
// NOTE: THIS SHOULD NOT BE NEEDED ANYMORE
|
|
||||||
|
|
||||||
// AudioStream_t* astr = streams[name];
|
|
||||||
// if (astr->running) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (astr->type == STREAM_TYPE_MONO) {
|
|
||||||
// astr->monoDynSplit->setBlockSize(blockSize);
|
|
||||||
// for (int i = 0; i < astr->boundStreams.size(); i++) {
|
|
||||||
// BoundStream_t bstr = astr->boundStreams[i];
|
|
||||||
// bstr.monoStream->setMaxLatency(blockSize * 2);
|
|
||||||
// if (bstr.type == STREAM_TYPE_STEREO) {
|
|
||||||
// bstr.m2s->stop();
|
|
||||||
// bstr.m2s->setBlockSize(blockSize);
|
|
||||||
// bstr.m2s->start();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// astr->blockSize = blockSize;
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// astr->monoDynSplit->setBlockSize(blockSize);
|
|
||||||
// for (int i = 0; i < astr->boundStreams.size(); i++) {
|
|
||||||
// BoundStream_t bstr = astr->boundStreams[i];
|
|
||||||
// bstr.stereoStream->setMaxLatency(blockSize * 2);
|
|
||||||
// if (bstr.type == STREAM_TYPE_MONO) {
|
|
||||||
// bstr.s2m->stop();
|
|
||||||
// bstr.s2m->setBlockSize(blockSize);
|
|
||||||
// bstr.s2m->start();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// astr->blockSize = blockSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unbindFromStreamMono(std::string name, dsp::stream<float>* stream) {
|
|
||||||
AudioStream_t* astr = streams[name];
|
|
||||||
for (int i = 0; i < astr->boundStreams.size(); i++) {
|
|
||||||
BoundStream_t bstr = astr->boundStreams[i];
|
|
||||||
if (bstr.monoStream != stream) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (astr->type == STREAM_TYPE_STEREO) {
|
|
||||||
astr->stereoDynSplit->stop();
|
|
||||||
astr->stereoDynSplit->unbindStream(bstr.stereoStream);
|
|
||||||
if (astr->running) {
|
|
||||||
astr->stereoDynSplit->start();
|
|
||||||
}
|
|
||||||
bstr.s2m->stop();
|
|
||||||
delete bstr.s2m;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
astr->monoDynSplit->stop();
|
|
||||||
astr->monoDynSplit->unbindStream(bstr.monoStream);
|
|
||||||
if (astr->running) {
|
|
||||||
astr->monoDynSplit->start();
|
|
||||||
}
|
|
||||||
delete stream;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void unbindFromStreamStereo(std::string name, dsp::stream<dsp::stereo_t>* stream) {
|
|
||||||
AudioStream_t* astr = streams[name];
|
|
||||||
for (int i = 0; i < astr->boundStreams.size(); i++) {
|
|
||||||
BoundStream_t bstr = astr->boundStreams[i];
|
|
||||||
if (bstr.stereoStream != stream) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (astr->type == STREAM_TYPE_MONO) {
|
|
||||||
astr->monoDynSplit->stop();
|
|
||||||
astr->monoDynSplit->unbindStream(bstr.monoStream);
|
|
||||||
if (astr->running) {
|
|
||||||
astr->monoDynSplit->start();
|
|
||||||
}
|
|
||||||
bstr.m2s->stop();
|
|
||||||
delete bstr.m2s;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
astr->stereoDynSplit->stop();
|
|
||||||
astr->stereoDynSplit->unbindStream(bstr.stereoStream);
|
|
||||||
if (astr->running) {
|
|
||||||
astr->stereoDynSplit->start();
|
|
||||||
}
|
|
||||||
delete stream;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getNameFromVFO(std::string vfoName) {
|
|
||||||
for (auto const& [name, stream] : streams) {
|
|
||||||
if (stream->vfoName == vfoName) {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSampleRate(std::string name, double sampleRate) {
|
|
||||||
AudioStream_t* astr = streams[name];
|
|
||||||
if (astr->running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: All the blocksize stuff needs removal
|
|
||||||
|
|
||||||
int blockSize = astr->sampleRateChangeHandler(astr->ctx, sampleRate);
|
|
||||||
astr->audio->setSampleRate(sampleRate);
|
|
||||||
//astr->audio->setBlockSize(blockSize);
|
|
||||||
if (astr->type == STREAM_TYPE_MONO) {
|
|
||||||
//astr->monoDynSplit->setBlockSize(blockSize);
|
|
||||||
for (int i = 0; i < astr->boundStreams.size(); i++) {
|
|
||||||
BoundStream_t bstr = astr->boundStreams[i];
|
|
||||||
if (bstr.type == STREAM_TYPE_STEREO) {
|
|
||||||
bstr.m2s->stop();
|
|
||||||
//bstr.m2s->setBlockSize(blockSize);
|
|
||||||
bstr.sampleRateChangeHandler(bstr.ctx, sampleRate, blockSize);
|
|
||||||
bstr.m2s->start();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bstr.sampleRateChangeHandler(bstr.ctx, sampleRate, blockSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//astr->stereoDynSplit->setBlockSize(blockSize);
|
|
||||||
for (int i = 0; i < astr->boundStreams.size(); i++) {
|
|
||||||
BoundStream_t bstr = astr->boundStreams[i];
|
|
||||||
if (bstr.type == STREAM_TYPE_MONO) {
|
|
||||||
bstr.s2m->stop();
|
|
||||||
//bstr.s2m->setBlockSize(blockSize);
|
|
||||||
bstr.sampleRateChangeHandler(bstr.ctx, sampleRate, blockSize);
|
|
||||||
bstr.s2m->start();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bstr.sampleRateChangeHandler(bstr.ctx, sampleRate, blockSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAudioDevice(std::string name, int deviceId, double sampleRate) {
|
|
||||||
AudioStream_t* astr = streams[name];
|
|
||||||
if (astr->running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
astr->deviceId = deviceId;
|
|
||||||
astr->audio->setDevice(deviceId);
|
|
||||||
setSampleRate(name, sampleRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> getStreamNameList() {
|
|
||||||
std::vector<std::string> list;
|
|
||||||
for (auto [name, stream] : streams) {
|
|
||||||
list.push_back(name);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <dsp/stream.h>
|
|
||||||
#include <dsp/routing.h>
|
|
||||||
#include <dsp/audio.h>
|
|
||||||
#include <io/audio.h>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace audio {
|
|
||||||
enum {
|
|
||||||
STREAM_TYPE_MONO,
|
|
||||||
STREAM_TYPE_STEREO,
|
|
||||||
_STREAM_TYPE_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: Create a manager class and an instance class
|
|
||||||
|
|
||||||
struct BoundStream_t {
|
|
||||||
dsp::stream<float>* monoStream;
|
|
||||||
dsp::stream<dsp::stereo_t>* stereoStream;
|
|
||||||
dsp::StereoToMono* s2m;
|
|
||||||
dsp::MonoToStereo* m2s;
|
|
||||||
void (*streamRemovedHandler)(void* ctx);
|
|
||||||
void (*sampleRateChangeHandler)(void* ctx, double sampleRate, int blockSize);
|
|
||||||
void* ctx;
|
|
||||||
int type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AudioStream_t {
|
|
||||||
io::AudioSink* audio;
|
|
||||||
dsp::stream<float>* monoAudioStream;
|
|
||||||
dsp::stream<dsp::stereo_t>* stereoAudioStream;
|
|
||||||
std::vector<BoundStream_t> boundStreams;
|
|
||||||
dsp::stream<float>* monoStream;
|
|
||||||
dsp::Splitter<float>* monoDynSplit;
|
|
||||||
dsp::stream<dsp::stereo_t>* stereoStream;
|
|
||||||
dsp::Splitter<dsp::stereo_t>* stereoDynSplit;
|
|
||||||
int (*sampleRateChangeHandler)(void* ctx, double sampleRate);
|
|
||||||
double sampleRate;
|
|
||||||
int blockSize;
|
|
||||||
int type;
|
|
||||||
bool running = false;
|
|
||||||
float volume;
|
|
||||||
int sampleRateId;
|
|
||||||
int deviceId;
|
|
||||||
void* ctx;
|
|
||||||
std::string vfoName;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern std::map<std::string, AudioStream_t*> streams;
|
|
||||||
|
|
||||||
double registerMonoStream(dsp::stream<float>* stream, std::string name, std::string vfoName, int (*sampleRateChangeHandler)(void* ctx, double sampleRate), void* ctx);
|
|
||||||
double registerStereoStream(dsp::stream<dsp::stereo_t>* stream, std::string name, std::string vfoName, int (*sampleRateChangeHandler)(void* ctx, double sampleRate), void* ctx);
|
|
||||||
void startStream(std::string name);
|
|
||||||
void stopStream(std::string name);
|
|
||||||
void removeStream(std::string name);
|
|
||||||
dsp::stream<float>* bindToStreamMono(std::string name, void (*streamRemovedHandler)(void* ctx), void (*sampleRateChangeHandler)(void* ctx, double sampleRate, int blockSize), void* ctx);
|
|
||||||
dsp::stream<dsp::stereo_t>* bindToStreamStereo(std::string name, void (*streamRemovedHandler)(void* ctx), void (*sampleRateChangeHandler)(void* ctx, double sampleRate, int blockSize), void* ctx);
|
|
||||||
void setBlockSize(std::string name, int blockSize);
|
|
||||||
void unbindFromStreamMono(std::string name, dsp::stream<float>* stream);
|
|
||||||
void unbindFromStreamStereo(std::string name, dsp::stream<dsp::stereo_t>* stream);
|
|
||||||
std::string getNameFromVFO(std::string vfoName);
|
|
||||||
void setSampleRate(std::string name, double sampleRate);
|
|
||||||
void setAudioDevice(std::string name, int deviceId, double sampleRate);
|
|
||||||
std::vector<std::string> getStreamNameList();
|
|
||||||
};
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
|||||||
#include <signal_path/sink.h>
|
#include <signal_path/sink.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <imgui/imgui.h>
|
#include <imgui/imgui.h>
|
||||||
|
#include <gui/style.h>
|
||||||
|
#include <gui/icons.h>
|
||||||
#include <core.h>
|
#include <core.h>
|
||||||
|
|
||||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||||
@ -12,16 +14,26 @@ SinkManager::SinkManager() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SinkManager::Stream::Stream(dsp::stream<dsp::stereo_t>* in, const Event<float>::EventHandler& srChangeHandler, float sampleRate) {
|
SinkManager::Stream::Stream(dsp::stream<dsp::stereo_t>* in, const Event<float>::EventHandler& srChangeHandler, float sampleRate) {
|
||||||
|
init(in, srChangeHandler, sampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SinkManager::Stream::init(dsp::stream<dsp::stereo_t>* in, const Event<float>::EventHandler& srChangeHandler, float sampleRate) {
|
||||||
_in = in;
|
_in = in;
|
||||||
srChange.bindHandler(srChangeHandler);
|
srChange.bindHandler(srChangeHandler);
|
||||||
_sampleRate = sampleRate;
|
_sampleRate = sampleRate;
|
||||||
splitter.init(_in);
|
splitter.init(_in);
|
||||||
|
splitter.bindStream(&volumeInput);
|
||||||
|
volumeAjust.init(&volumeInput, 1.0f);
|
||||||
|
sinkOut = &volumeAjust.out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SinkManager::Stream::start() {
|
void SinkManager::Stream::start() {
|
||||||
if (running) {
|
if (running) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
splitter.start();
|
||||||
|
volumeAjust.start();
|
||||||
sink->start();
|
sink->start();
|
||||||
running = true;
|
running = true;
|
||||||
}
|
}
|
||||||
@ -30,10 +42,25 @@ void SinkManager::Stream::stop() {
|
|||||||
if (!running) {
|
if (!running) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
splitter.stop();
|
||||||
|
volumeAjust.stop();
|
||||||
sink->stop();
|
sink->stop();
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SinkManager::Stream::setVolume(float volume) {
|
||||||
|
guiVolume = volume;
|
||||||
|
volumeAjust.setVolume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
float SinkManager::Stream::getVolume() {
|
||||||
|
return guiVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SinkManager::Stream::getSampleRate() {
|
||||||
|
return _sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
void SinkManager::Stream::setInput(dsp::stream<dsp::stereo_t>* in) {
|
void SinkManager::Stream::setInput(dsp::stream<dsp::stereo_t>* in) {
|
||||||
std::lock_guard<std::mutex> lck(ctrlMtx);
|
std::lock_guard<std::mutex> lck(ctrlMtx);
|
||||||
_in = in;
|
_in = in;
|
||||||
@ -71,20 +98,15 @@ void SinkManager::registerStream(std::string name, SinkManager::Stream* stream)
|
|||||||
spdlog::error("Cannot register stream '{0}', this name is already taken", name);
|
spdlog::error("Cannot register stream '{0}', this name is already taken", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
core::configManager.aquire();
|
|
||||||
std::string providerName = core::configManager.conf["defaultSink"];
|
|
||||||
core::configManager.release();
|
|
||||||
|
|
||||||
SinkManager::SinkProvider provider;
|
SinkManager::SinkProvider provider;
|
||||||
if (providers.find(providerName) == providers.end()) {
|
|
||||||
// TODO: get default
|
provider = providers["None"];
|
||||||
}
|
|
||||||
else {
|
|
||||||
provider = providers[providerName];
|
|
||||||
}
|
|
||||||
|
|
||||||
stream->sink = provider.create(stream, name, provider.ctx);
|
stream->sink = provider.create(stream, name, provider.ctx);
|
||||||
|
|
||||||
|
streams[name] = stream;
|
||||||
|
streamNames.push_back(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SinkManager::unregisterStream(std::string name) {
|
void SinkManager::unregisterStream(std::string name) {
|
||||||
@ -92,6 +114,7 @@ void SinkManager::unregisterStream(std::string name) {
|
|||||||
spdlog::error("Cannot unregister stream '{0}', this stream doesn't exist", name);
|
spdlog::error("Cannot unregister stream '{0}', this stream doesn't exist", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
spdlog::error("unregisterStream NOT IMPLEMENTED!!!!!!!");
|
||||||
SinkManager::Stream* stream = streams[name];
|
SinkManager::Stream* stream = streams[name];
|
||||||
delete stream->sink;
|
delete stream->sink;
|
||||||
delete stream;
|
delete stream;
|
||||||
@ -113,6 +136,14 @@ void SinkManager::stopStream(std::string name) {
|
|||||||
streams[name]->stop();
|
streams[name]->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float SinkManager::getStreamSampleRate(std::string name) {
|
||||||
|
if (streams.find(name) == streams.end()) {
|
||||||
|
spdlog::error("Cannot get sample rate of stream '{0}', this stream doesn't exist", name);
|
||||||
|
return -1.0f;
|
||||||
|
}
|
||||||
|
return streams[name]->getSampleRate();
|
||||||
|
}
|
||||||
|
|
||||||
dsp::stream<dsp::stereo_t>* SinkManager::bindStream(std::string name) {
|
dsp::stream<dsp::stereo_t>* SinkManager::bindStream(std::string name) {
|
||||||
if (streams.find(name) == streams.end()) {
|
if (streams.find(name) == streams.end()) {
|
||||||
spdlog::error("Cannot bind to stream '{0}'. Stream doesn't exist", name);
|
spdlog::error("Cannot bind to stream '{0}'. Stream doesn't exist", name);
|
||||||
@ -130,7 +161,93 @@ void SinkManager::unbindStream(std::string name, dsp::stream<dsp::stereo_t>* str
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SinkManager::setStreamSink(std::string name, std::string providerName) {
|
void SinkManager::setStreamSink(std::string name, std::string providerName) {
|
||||||
|
spdlog::warn("setStreamSink is NOT implemented!!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SinkManager::showVolumeSlider(std::string name, std::string prefix, float width) {
|
||||||
|
// TODO: Replace map with some hashmap for it to be faster
|
||||||
|
float height = ImGui::GetTextLineHeightWithSpacing() + 2;
|
||||||
|
|
||||||
|
if (streams.find(name) == streams.end()) {
|
||||||
|
float dummy = 0.0f;
|
||||||
|
style::beginDisabled();
|
||||||
|
ImGui::SetNextItemWidth(width - height);
|
||||||
|
ImGui::SliderFloat((prefix + name).c_str(), &dummy, 0.0f, 1.0f, "");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::PushID(ImGui::GetID(("sdrpp_dummy_mute_btn_" + name).c_str()));
|
||||||
|
ImGui::ImageButton(icons::STOP, ImVec2(height, height), ImVec2(0, 0), ImVec2(1, 1), 0);
|
||||||
|
ImGui::PopID();
|
||||||
|
style::endDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
SinkManager::Stream* stream = streams[name];
|
||||||
|
ImGui::SetNextItemWidth(width - height - 10);
|
||||||
|
if (ImGui::SliderFloat((prefix + name).c_str(), &stream->guiVolume, 0.0f, 1.0f, "")) {
|
||||||
|
stream->setVolume(stream->guiVolume);
|
||||||
|
core::configManager.aquire();
|
||||||
|
saveStreamConfig(name);
|
||||||
|
core::configManager.release(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (stream->volumeAjust.getMuted()) {
|
||||||
|
ImGui::PushID(ImGui::GetID(("sdrpp_unmute_btn_" + name).c_str()));
|
||||||
|
if (ImGui::ImageButton(icons::PLAY, ImVec2(height, height), ImVec2(0, 0), ImVec2(1, 1), 0)) {
|
||||||
|
stream->volumeAjust.setMuted(false);
|
||||||
|
core::configManager.aquire();
|
||||||
|
saveStreamConfig(name);
|
||||||
|
core::configManager.release(true);
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ImGui::PushID(ImGui::GetID(("sdrpp_mute_btn_" + name).c_str()));
|
||||||
|
if (ImGui::ImageButton(icons::STOP, ImVec2(height, height), ImVec2(0, 0), ImVec2(1, 1), 0)) {
|
||||||
|
stream->volumeAjust.setMuted(true);
|
||||||
|
core::configManager.aquire();
|
||||||
|
saveStreamConfig(name);
|
||||||
|
core::configManager.release(true);
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SinkManager::loadStreamConfig(std::string name) {
|
||||||
|
json conf = core::configManager.conf["streams"][name];
|
||||||
|
SinkManager::Stream* stream = streams[name];
|
||||||
|
std::string provName = conf["sink"];
|
||||||
|
if (providers.find(provName) == providers.end()) {
|
||||||
|
provName = providerNames[0];
|
||||||
|
}
|
||||||
|
if (stream->running) {
|
||||||
|
stream->sink->stop();
|
||||||
|
}
|
||||||
|
delete stream->sink;
|
||||||
|
SinkManager::SinkProvider prov = providers[provName];
|
||||||
|
stream->providerId = std::distance(providerNames.begin(), std::find(providerNames.begin(), providerNames.end(), provName));
|
||||||
|
stream->sink = prov.create(stream, name, prov.ctx);
|
||||||
|
if (stream->running) {
|
||||||
|
stream->sink->start();
|
||||||
|
}
|
||||||
|
stream->setVolume(conf["volume"]);
|
||||||
|
stream->volumeAjust.setMuted(conf["muted"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SinkManager::saveStreamConfig(std::string name) {
|
||||||
|
SinkManager::Stream* stream = streams[name];
|
||||||
|
json conf;
|
||||||
|
conf["sink"] = providerNames[stream->providerId];
|
||||||
|
conf["volume"] = stream->getVolume();
|
||||||
|
conf["muted"] = stream->volumeAjust.getMuted();
|
||||||
|
core::configManager.conf["streams"][name] = conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: aquire and release config before running this
|
||||||
|
void SinkManager::loadSinksFromConfig() {
|
||||||
|
for (auto const& [name, stream] : streams) {
|
||||||
|
if (!core::configManager.conf["streams"].contains(name)) { continue; }
|
||||||
|
loadStreamConfig(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SinkManager::showMenu() {
|
void SinkManager::showMenu() {
|
||||||
@ -139,7 +256,7 @@ void SinkManager::showMenu() {
|
|||||||
int maxCount = streams.size();
|
int maxCount = streams.size();
|
||||||
|
|
||||||
std::string provStr = "";
|
std::string provStr = "";
|
||||||
for (auto const& [name, provider] : providers) {
|
for (auto const& name : providerNames) {
|
||||||
provStr += name;
|
provStr += name;
|
||||||
provStr += '\0';
|
provStr += '\0';
|
||||||
}
|
}
|
||||||
@ -148,6 +265,7 @@ void SinkManager::showMenu() {
|
|||||||
ImGui::SetCursorPosX((menuWidth / 2.0f) - (ImGui::CalcTextSize(name.c_str()).x / 2.0f));
|
ImGui::SetCursorPosX((menuWidth / 2.0f) - (ImGui::CalcTextSize(name.c_str()).x / 2.0f));
|
||||||
ImGui::Text("%s", name.c_str());
|
ImGui::Text("%s", name.c_str());
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(menuWidth);
|
||||||
if (ImGui::Combo(CONCAT("##_sdrpp_sink_select_", name), &stream->providerId, provStr.c_str())) {
|
if (ImGui::Combo(CONCAT("##_sdrpp_sink_select_", name), &stream->providerId, provStr.c_str())) {
|
||||||
if (stream->running) {
|
if (stream->running) {
|
||||||
stream->sink->stop();
|
stream->sink->stop();
|
||||||
@ -158,11 +276,15 @@ void SinkManager::showMenu() {
|
|||||||
if (stream->running) {
|
if (stream->running) {
|
||||||
stream->sink->start();
|
stream->sink->start();
|
||||||
}
|
}
|
||||||
|
core::configManager.aquire();
|
||||||
|
saveStreamConfig(name);
|
||||||
|
core::configManager.release(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->sink->menuHandler();
|
stream->sink->menuHandler();
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
showVolumeSlider(name, "##_sdrpp_sink_menu_vol_", menuWidth);
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
if (count < maxCount) {
|
if (count < maxCount) {
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
@ -170,4 +292,8 @@ void SinkManager::showMenu() {
|
|||||||
}
|
}
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> SinkManager::getStreamNames() {
|
||||||
|
return streamNames;
|
||||||
}
|
}
|
@ -4,6 +4,7 @@
|
|||||||
#include <dsp/stream.h>
|
#include <dsp/stream.h>
|
||||||
#include <dsp/types.h>
|
#include <dsp/types.h>
|
||||||
#include <dsp/routing.h>
|
#include <dsp/routing.h>
|
||||||
|
#include <dsp/processing.h>
|
||||||
#include <dsp/sink.h>
|
#include <dsp/sink.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <event.h>
|
#include <event.h>
|
||||||
@ -22,11 +23,20 @@ public:
|
|||||||
|
|
||||||
class Stream {
|
class Stream {
|
||||||
public:
|
public:
|
||||||
|
Stream() {}
|
||||||
Stream(dsp::stream<dsp::stereo_t>* in, const Event<float>::EventHandler& srChangeHandler, float sampleRate);
|
Stream(dsp::stream<dsp::stereo_t>* in, const Event<float>::EventHandler& srChangeHandler, float sampleRate);
|
||||||
|
|
||||||
|
void init(dsp::stream<dsp::stereo_t>* in, const Event<float>::EventHandler& srChangeHandler, float sampleRate);
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
void setVolume(float volume);
|
||||||
|
float getVolume();
|
||||||
|
|
||||||
|
void setSampleRate(float sampleRate);
|
||||||
|
float getSampleRate();
|
||||||
|
|
||||||
void setInput(dsp::stream<dsp::stereo_t>* in);
|
void setInput(dsp::stream<dsp::stereo_t>* in);
|
||||||
|
|
||||||
dsp::stream<dsp::stereo_t>* bindStream();
|
dsp::stream<dsp::stereo_t>* bindStream();
|
||||||
@ -35,18 +45,22 @@ public:
|
|||||||
friend SinkManager;
|
friend SinkManager;
|
||||||
friend SinkManager::Sink;
|
friend SinkManager::Sink;
|
||||||
|
|
||||||
|
dsp::stream<dsp::stereo_t>* sinkOut;
|
||||||
|
|
||||||
Event<float> srChange;
|
Event<float> srChange;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setSampleRate(float sampleRate);
|
|
||||||
|
|
||||||
dsp::stream<dsp::stereo_t>* _in;
|
dsp::stream<dsp::stereo_t>* _in;
|
||||||
dsp::Splitter<dsp::stereo_t> splitter;
|
dsp::Splitter<dsp::stereo_t> splitter;
|
||||||
SinkManager::Sink* sink;
|
SinkManager::Sink* sink;
|
||||||
|
dsp::stream<dsp::stereo_t> volumeInput;
|
||||||
|
dsp::Volume<dsp::stereo_t> volumeAjust;
|
||||||
std::mutex ctrlMtx;
|
std::mutex ctrlMtx;
|
||||||
float _sampleRate;
|
float _sampleRate;
|
||||||
int providerId = 0;
|
int providerId = 0;
|
||||||
bool running = false;
|
bool running = false;
|
||||||
|
|
||||||
|
float guiVolume = 1.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SinkProvider {
|
struct SinkProvider {
|
||||||
@ -56,13 +70,21 @@ public:
|
|||||||
|
|
||||||
class NullSink : SinkManager::Sink {
|
class NullSink : SinkManager::Sink {
|
||||||
public:
|
public:
|
||||||
void start() {}
|
NullSink(SinkManager::Stream* stream) {
|
||||||
void stop() {}
|
ns.init(stream->sinkOut);
|
||||||
|
}
|
||||||
|
void start() { ns.start(); }
|
||||||
|
void stop() { ns.stop(); }
|
||||||
void menuHandler() {}
|
void menuHandler() {}
|
||||||
|
|
||||||
static SinkManager::Sink* create(SinkManager::Stream* stream, std::string streamName, void* ctx) {
|
static SinkManager::Sink* create(SinkManager::Stream* stream, std::string streamName, void* ctx) {
|
||||||
return new SinkManager::NullSink;
|
stream->srChange.emit(48000);
|
||||||
|
return new SinkManager::NullSink(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
dsp::NullSink<dsp::stereo_t> ns;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void registerSinkProvider(std::string name, SinkProvider provider);
|
void registerSinkProvider(std::string name, SinkProvider provider);
|
||||||
@ -73,16 +95,27 @@ public:
|
|||||||
void startStream(std::string name);
|
void startStream(std::string name);
|
||||||
void stopStream(std::string name);
|
void stopStream(std::string name);
|
||||||
|
|
||||||
|
float getStreamSampleRate(std::string name);
|
||||||
|
|
||||||
void setStreamSink(std::string name, std::string providerName);
|
void setStreamSink(std::string name, std::string providerName);
|
||||||
|
|
||||||
|
void showVolumeSlider(std::string name, std::string prefix, float width);
|
||||||
|
|
||||||
dsp::stream<dsp::stereo_t>* bindStream(std::string name);
|
dsp::stream<dsp::stereo_t>* bindStream(std::string name);
|
||||||
void unbindStream(std::string name, dsp::stream<dsp::stereo_t>* stream);
|
void unbindStream(std::string name, dsp::stream<dsp::stereo_t>* stream);
|
||||||
|
|
||||||
|
void loadSinksFromConfig();
|
||||||
void showMenu();
|
void showMenu();
|
||||||
|
|
||||||
|
std::vector<std::string> getStreamNames();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void loadStreamConfig(std::string name);
|
||||||
|
void saveStreamConfig(std::string name);
|
||||||
|
|
||||||
std::map<std::string, SinkProvider> providers;
|
std::map<std::string, SinkProvider> providers;
|
||||||
std::map<std::string, Stream*> streams;
|
std::map<std::string, Stream*> streams;
|
||||||
std::vector<std::string> providerNames;
|
std::vector<std::string> providerNames;
|
||||||
|
std::vector<std::string> streamNames;
|
||||||
|
|
||||||
};
|
};
|
@ -23,7 +23,7 @@ public:
|
|||||||
bandWidth = 200000;
|
bandWidth = 200000;
|
||||||
bandWidthMin = 100000;
|
bandWidthMin = 100000;
|
||||||
bandWidthMax = 200000;
|
bandWidthMax = 200000;
|
||||||
sigPath.init(name, 200000, 1000);
|
sigPath.init(name);
|
||||||
sigPath.start();
|
sigPath.start();
|
||||||
sigPath.setDemodulator(SigPath::DEMOD_FM, bandWidth);
|
sigPath.setDemodulator(SigPath::DEMOD_FM, bandWidth);
|
||||||
sigPath.vfo->setSnapInterval(100000.0);
|
sigPath.vfo->setSnapInterval(100000.0);
|
||||||
|
@ -1,33 +1,28 @@
|
|||||||
#include <path.h>
|
#include <path.h>
|
||||||
#include <signal_path/audio.h>
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
SigPath::SigPath() {
|
SigPath::SigPath() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SigPath::sampleRateChangeHandler(void* ctx, double sampleRate) {
|
void SigPath::sampleRateChangeHandler(float _sampleRate, void* ctx) {
|
||||||
SigPath* _this = (SigPath*)ctx;
|
SigPath* _this = (SigPath*)ctx;
|
||||||
_this->outputSampleRate = sampleRate;
|
_this->outputSampleRate = _sampleRate;
|
||||||
_this->audioResamp.stop();
|
_this->audioResamp.stop();
|
||||||
_this->deemp.stop();
|
_this->deemp.stop();
|
||||||
float bw = std::min<float>(_this->bandwidth, sampleRate / 2.0f);
|
float bw = std::min<float>(_this->bandwidth, _sampleRate / 2.0f);
|
||||||
|
|
||||||
|
|
||||||
_this->audioResamp.setOutSampleRate(sampleRate);
|
_this->audioResamp.setOutSampleRate(_sampleRate);
|
||||||
_this->audioWin.setSampleRate(_this->sampleRate * _this->audioResamp.getInterpolation());
|
_this->audioWin.setSampleRate(_this->demodOutputSamplerate * _this->audioResamp.getInterpolation());
|
||||||
_this->audioResamp.updateWindow(&_this->audioWin);
|
_this->audioResamp.updateWindow(&_this->audioWin);
|
||||||
|
|
||||||
_this->deemp.setSampleRate(sampleRate);
|
_this->deemp.setSampleRate(_sampleRate);
|
||||||
_this->audioResamp.start();
|
_this->audioResamp.start();
|
||||||
_this->deemp.start();
|
_this->deemp.start();
|
||||||
// Note: returning a block size should not be needed anymore
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SigPath::init(std::string vfoName, uint64_t sampleRate, int blockSize) {
|
void SigPath::init(std::string vfoName) {
|
||||||
this->sampleRate = sampleRate;
|
|
||||||
this->blockSize = blockSize;
|
|
||||||
this->vfoName = vfoName;
|
this->vfoName = vfoName;
|
||||||
|
|
||||||
vfo = sigpath::vfoManager.createVFO(vfoName, ImGui::WaterfallVFO::REF_CENTER, 0, 200000, 200000, 1000);
|
vfo = sigpath::vfoManager.createVFO(vfoName, ImGui::WaterfallVFO::REF_CENTER, 0, 200000, 200000, 1000);
|
||||||
@ -36,6 +31,7 @@ void SigPath::init(std::string vfoName, uint64_t sampleRate, int blockSize) {
|
|||||||
_deemp = DEEMP_50US;
|
_deemp = DEEMP_50US;
|
||||||
bandwidth = 200000;
|
bandwidth = 200000;
|
||||||
demodOutputSamplerate = 200000;
|
demodOutputSamplerate = 200000;
|
||||||
|
outputSampleRate = 48000;
|
||||||
|
|
||||||
// TODO: Set default VFO options
|
// TODO: Set default VFO options
|
||||||
// TODO: ajust deemphasis for different output sample rates
|
// TODO: ajust deemphasis for different output sample rates
|
||||||
@ -53,16 +49,16 @@ void SigPath::init(std::string vfoName, uint64_t sampleRate, int blockSize) {
|
|||||||
audioResamp.updateWindow(&audioWin);
|
audioResamp.updateWindow(&audioWin);
|
||||||
|
|
||||||
deemp.init(&audioResamp.out, 48000, 50e-6);
|
deemp.init(&audioResamp.out, 48000, 50e-6);
|
||||||
|
|
||||||
outputSampleRate = audio::registerMonoStream(&deemp.out, vfoName, vfoName, sampleRateChangeHandler, this);
|
|
||||||
|
|
||||||
setDemodulator(_demod, bandwidth);
|
m2s.setInput(&deemp.out);
|
||||||
}
|
|
||||||
|
|
||||||
void SigPath::setSampleRate(float sampleRate) {
|
Event<float>::EventHandler evHandler;
|
||||||
this->sampleRate = sampleRate;
|
evHandler.handler = sampleRateChangeHandler;
|
||||||
|
evHandler.ctx = this;
|
||||||
|
stream.init(&m2s.out, evHandler, outputSampleRate);
|
||||||
|
|
||||||
|
sigpath::sinkManager.registerStream(vfoName, &stream);
|
||||||
|
|
||||||
// Reset the demodulator and audio systems
|
|
||||||
setDemodulator(_demod, bandwidth);
|
setDemodulator(_demod, bandwidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,10 +211,6 @@ void SigPath::setDemodulator(int demId, float bandWidth) {
|
|||||||
deemp.start();
|
deemp.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SigPath::updateBlockSize() {
|
|
||||||
setDemodulator(_demod, bandwidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SigPath::setDeemphasis(int deemph) {
|
void SigPath::setDeemphasis(int deemph) {
|
||||||
_deemp = deemph;
|
_deemp = deemph;
|
||||||
deemp.stop();
|
deemp.stop();
|
||||||
@ -290,6 +282,6 @@ void SigPath::start() {
|
|||||||
demod.start();
|
demod.start();
|
||||||
audioResamp.start();
|
audioResamp.start();
|
||||||
deemp.start();
|
deemp.start();
|
||||||
//ns.start();
|
m2s.start();
|
||||||
audio::startStream(vfoName);
|
stream.start();
|
||||||
}
|
}
|
@ -4,19 +4,16 @@
|
|||||||
#include <dsp/filter.h>
|
#include <dsp/filter.h>
|
||||||
#include <dsp/window.h>
|
#include <dsp/window.h>
|
||||||
#include <dsp/audio.h>
|
#include <dsp/audio.h>
|
||||||
#include <io/audio.h>
|
|
||||||
#include <module.h>
|
#include <module.h>
|
||||||
#include <signal_path/signal_path.h>
|
#include <signal_path/signal_path.h>
|
||||||
#include <dsp/processing.h>
|
#include <dsp/processing.h>
|
||||||
|
#include <signal_path/sink.h>
|
||||||
|
|
||||||
class SigPath {
|
class SigPath {
|
||||||
public:
|
public:
|
||||||
SigPath();
|
SigPath();
|
||||||
void init(std::string vfoName, uint64_t sampleRate, int blockSize);
|
void init(std::string vfoName);
|
||||||
void start();
|
void start();
|
||||||
void setSampleRate(float sampleRate);
|
|
||||||
void setVFOFrequency(uint64_t frequency);
|
|
||||||
void updateBlockSize();
|
|
||||||
void setDemodulator(int demod, float bandWidth);
|
void setDemodulator(int demod, float bandWidth);
|
||||||
void setDeemphasis(int deemph);
|
void setDeemphasis(int deemph);
|
||||||
void setBandwidth(float bandWidth);
|
void setBandwidth(float bandWidth);
|
||||||
@ -44,7 +41,7 @@ public:
|
|||||||
VFOManager::VFO* vfo;
|
VFOManager::VFO* vfo;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int sampleRateChangeHandler(void* ctx, double sampleRate);
|
static void sampleRateChangeHandler(float _sampleRate, void* ctx);
|
||||||
|
|
||||||
dsp::stream<dsp::complex_t> input;
|
dsp::stream<dsp::complex_t> input;
|
||||||
|
|
||||||
@ -57,17 +54,17 @@ private:
|
|||||||
dsp::AGC agc;
|
dsp::AGC agc;
|
||||||
|
|
||||||
// Audio output
|
// Audio output
|
||||||
dsp::MonoToStereo m2s;
|
|
||||||
dsp::filter_window::BlackmanWindow audioWin;
|
dsp::filter_window::BlackmanWindow audioWin;
|
||||||
dsp::PolyphaseResampler<float> audioResamp;
|
dsp::PolyphaseResampler<float> audioResamp;
|
||||||
|
dsp::MonoToStereo m2s;
|
||||||
|
SinkManager::Stream stream;
|
||||||
|
|
||||||
std::string vfoName;
|
std::string vfoName;
|
||||||
|
|
||||||
float sampleRate;
|
// TODO: FIx all this sample rate BS (multiple names for same thing)
|
||||||
float bandwidth;
|
float bandwidth;
|
||||||
float demodOutputSamplerate;
|
float demodOutputSamplerate;
|
||||||
float outputSampleRate;
|
float outputSampleRate;
|
||||||
int blockSize;
|
|
||||||
int _demod;
|
int _demod;
|
||||||
int _deemp;
|
int _deemp;
|
||||||
float audioBw;
|
float audioBw;
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <dsp/stream.h>
|
#include <dsp/stream.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <signal_path/audio.h>
|
|
||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
#include <signal_path/signal_path.h>
|
#include <signal_path/signal_path.h>
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -51,7 +50,7 @@ private:
|
|||||||
RecorderModule* _this = (RecorderModule*)ctx;
|
RecorderModule* _this = (RecorderModule*)ctx;
|
||||||
float menuColumnWidth = ImGui::GetContentRegionAvailWidth();
|
float menuColumnWidth = ImGui::GetContentRegionAvailWidth();
|
||||||
|
|
||||||
std::vector<std::string> streamNames = audio::getStreamNameList();
|
std::vector<std::string> streamNames = sigpath::sinkManager.getStreamNames();
|
||||||
std::string nameList;
|
std::string nameList;
|
||||||
for (std::string name : streamNames) {
|
for (std::string name : streamNames) {
|
||||||
nameList += name;
|
nameList += name;
|
||||||
@ -147,9 +146,9 @@ private:
|
|||||||
if (!_this->recording) {
|
if (!_this->recording) {
|
||||||
if (ImGui::Button("Record", ImVec2(menuColumnWidth, 0))) {
|
if (ImGui::Button("Record", ImVec2(menuColumnWidth, 0))) {
|
||||||
_this->samplesWritten = 0;
|
_this->samplesWritten = 0;
|
||||||
_this->sampleRate = 48000;
|
_this->sampleRate = sigpath::sinkManager.getStreamSampleRate(_this->selectedStreamName);
|
||||||
_this->writer = new WavWriter(ROOT_DIR "/recordings/" + genFileName("audio_"), 16, 2, 48000);
|
_this->writer = new WavWriter(ROOT_DIR "/recordings/" + genFileName("audio_"), 16, 2, _this->sampleRate);
|
||||||
_this->audioStream = audio::bindToStreamStereo(_this->selectedStreamName, streamRemovedHandler, sampleRateChanged, _this);
|
_this->audioStream = sigpath::sinkManager.bindStream(_this->selectedStreamName);
|
||||||
_this->workerThread = std::thread(_audioWriteWorker, _this);
|
_this->workerThread = std::thread(_audioWriteWorker, _this);
|
||||||
_this->recording = true;
|
_this->recording = true;
|
||||||
_this->startTime = time(0);
|
_this->startTime = time(0);
|
||||||
@ -161,7 +160,7 @@ private:
|
|||||||
_this->audioStream->stopReader();
|
_this->audioStream->stopReader();
|
||||||
_this->workerThread.join();
|
_this->workerThread.join();
|
||||||
_this->audioStream->clearReadStop();
|
_this->audioStream->clearReadStop();
|
||||||
audio::unbindFromStreamStereo(_this->selectedStreamName, _this->audioStream);
|
sigpath::sinkManager.unbindStream(_this->selectedStreamName, _this->audioStream);
|
||||||
_this->writer->close();
|
_this->writer->close();
|
||||||
delete _this->writer;
|
delete _this->writer;
|
||||||
_this->recording = false;
|
_this->recording = false;
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
},
|
},
|
||||||
"bandPlan": "General",
|
"bandPlan": "General",
|
||||||
"bandPlanEnabled": true,
|
"bandPlanEnabled": true,
|
||||||
"defaultSink": "Audio",
|
|
||||||
"fftHeight": 296,
|
"fftHeight": 296,
|
||||||
"frequency": 99000000,
|
"frequency": 99000000,
|
||||||
"max": 0.0,
|
"max": 0.0,
|
||||||
@ -35,9 +34,17 @@
|
|||||||
],
|
],
|
||||||
"menuWidth": 300,
|
"menuWidth": 300,
|
||||||
"min": -70.5882339477539,
|
"min": -70.5882339477539,
|
||||||
|
"offset": 0.0,
|
||||||
"showWaterfall": true,
|
"showWaterfall": true,
|
||||||
"source": "",
|
"source": "PlutoSDR",
|
||||||
"sourceSettings": {},
|
"sourceSettings": {},
|
||||||
|
"streams": {
|
||||||
|
"Radio": {
|
||||||
|
"muted": false,
|
||||||
|
"sink": "Audio",
|
||||||
|
"volume": 0.65625
|
||||||
|
}
|
||||||
|
},
|
||||||
"windowSize": {
|
"windowSize": {
|
||||||
"h": 720,
|
"h": 720,
|
||||||
"w": 1280
|
"w": 1280
|
||||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user