mirror of
https://github.com/SatDump/SatDump
synced 2026-08-13 17:47:30 -04:00
Start adding live back
This commit is contained in:
parent
ffb3cf3101
commit
cd22ff265d
9 changed files with 237 additions and 16 deletions
|
|
@ -24,6 +24,10 @@ void ProcessingModule::setOutputType(ModuleDataType type)
|
|||
output_data_type = type;
|
||||
}
|
||||
|
||||
void ProcessingModule::init()
|
||||
{
|
||||
}
|
||||
|
||||
void ProcessingModule::drawUI()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <atomic>
|
||||
#include "imgui/imgui_flags.h"
|
||||
#include "dll_export.h"
|
||||
#include "modules/buffer.h"
|
||||
|
||||
#define WRITE_IMAGE(image, path) \
|
||||
image.save_png(std::string(path).c_str()); \
|
||||
|
|
@ -15,9 +16,9 @@
|
|||
|
||||
enum ModuleDataType
|
||||
{
|
||||
DATA_STREAM, // Generic data, for which a circular buffer will be used
|
||||
DATA_STREAM, // Generic data, for which a circular buffer will be used
|
||||
DATA_DSP_STREAM, // DSP Data using the specialized buffer and complex floats
|
||||
DATA_FILE, // Just generic data from a file
|
||||
DATA_FILE, // Just generic data from a file
|
||||
};
|
||||
|
||||
class ProcessingModule
|
||||
|
|
@ -26,7 +27,7 @@ protected:
|
|||
const std::string d_input_file;
|
||||
const std::string d_output_file_hint;
|
||||
std::vector<std::string> d_output_files;
|
||||
const std::map<std::string, std::string> d_parameters;
|
||||
std::map<std::string, std::string> d_parameters;
|
||||
ModuleDataType input_data_type, output_data_type;
|
||||
|
||||
public:
|
||||
|
|
@ -35,6 +36,7 @@ public:
|
|||
virtual std::vector<ModuleDataType> getOutputTypes() { return {DATA_FILE}; }
|
||||
void setInputType(ModuleDataType type);
|
||||
void setOutputType(ModuleDataType type);
|
||||
virtual void init();
|
||||
virtual void process() = 0;
|
||||
virtual void drawUI() = 0;
|
||||
std::vector<std::string> getOutputs();
|
||||
|
|
@ -42,6 +44,8 @@ public:
|
|||
public:
|
||||
//std::shared_ptr<satdump::Pipe> input_fifo;
|
||||
//std::shared_ptr<satdump::Pipe> output_fifo;
|
||||
std::shared_ptr<dsp::stream<std::complex<float>>> input_stream;
|
||||
std::shared_ptr<dsp::stream<std::complex<float>>> output_stream;
|
||||
std::atomic<bool> input_active;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -21,18 +21,22 @@ QPSKDemodModule::QPSKDemodModule(std::string input_file, std::string output_file
|
|||
d_loop_bw(std::stof(parameters["costas_bw"])),
|
||||
d_buffer_size(std::stoi(parameters["buffer_size"])),
|
||||
d_dc_block(parameters.count("dc_block") > 0 ? std::stoi(parameters["dc_block"]) : 0)
|
||||
{
|
||||
// Buffers
|
||||
sym_buffer = new int8_t[d_buffer_size * 2];
|
||||
}
|
||||
|
||||
void QPSKDemodModule::init()
|
||||
{
|
||||
// Init DSP blocks
|
||||
file_source = std::make_shared<dsp::FileSourceBlock>(d_input_file, dsp::BasebandTypeFromString(parameters["baseband_format"]), d_buffer_size);
|
||||
if (input_data_type == DATA_FILE)
|
||||
file_source = std::make_shared<dsp::FileSourceBlock>(d_input_file, dsp::BasebandTypeFromString(d_parameters["baseband_format"]), d_buffer_size);
|
||||
if (d_dc_block)
|
||||
dcb = std::make_shared<dsp::DCBlockerBlock>(file_source->output_stream, 1024, true);
|
||||
agc = std::make_shared<dsp::AGCBlock>(d_dc_block ? dcb->output_stream : file_source->output_stream, d_agc_rate, 1.0f, 1.0f, 65536);
|
||||
dcb = std::make_shared<dsp::DCBlockerBlock>(input_data_type == DATA_DSP_STREAM ? input_stream : file_source->output_stream, 1024, true);
|
||||
agc = std::make_shared<dsp::AGCBlock>(d_dc_block ? dcb->output_stream : (input_data_type == DATA_DSP_STREAM ? input_stream : file_source->output_stream), d_agc_rate, 1.0f, 1.0f, 65536);
|
||||
rrc = std::make_shared<dsp::CCFIRBlock>(agc->output_stream, 1, libdsp::firgen::root_raised_cosine(1, d_samplerate, d_symbolrate, d_rrc_alpha, d_rrc_taps));
|
||||
pll = std::make_shared<dsp::CostasLoopBlock>(rrc->output_stream, d_loop_bw, 4);
|
||||
rec = std::make_shared<dsp::CCMMClockRecoveryBlock>(pll->output_stream, (float)d_samplerate / (float)d_symbolrate, pow(8.7e-3, 2) / 4.0, 0.5f, 8.7e-3, 0.005f);
|
||||
|
||||
// Buffers
|
||||
sym_buffer = new int8_t[d_buffer_size * 2];
|
||||
}
|
||||
|
||||
std::vector<ModuleDataType> QPSKDemodModule::getInputTypes()
|
||||
|
|
@ -57,9 +61,6 @@ void QPSKDemodModule::process()
|
|||
else
|
||||
filesize = 0;
|
||||
|
||||
//if (input_data_type == DATA_FILE)
|
||||
// data_in = std::ifstream(d_input_file, std::ios::binary);
|
||||
|
||||
data_out = std::ofstream(d_output_file_hint + ".soft", std::ios::binary);
|
||||
d_output_files.push_back(d_output_file_hint + ".soft");
|
||||
|
||||
|
|
@ -70,7 +71,8 @@ void QPSKDemodModule::process()
|
|||
time_t lastTime = 0;
|
||||
|
||||
// Start
|
||||
file_source->start();
|
||||
if (input_data_type == DATA_FILE)
|
||||
file_source->start();
|
||||
if (d_dc_block)
|
||||
dcb->start();
|
||||
agc->start();
|
||||
|
|
@ -79,7 +81,7 @@ void QPSKDemodModule::process()
|
|||
rec->start();
|
||||
|
||||
int dat_size = 0;
|
||||
while (/*input_data_type == DATA_STREAM ? input_active.load() : */ !file_source->eof())
|
||||
while (input_data_type == DATA_FILE ? !file_source->eof() : input_active.load())
|
||||
{
|
||||
dat_size = rec->output_stream->read();
|
||||
|
||||
|
|
@ -96,7 +98,8 @@ void QPSKDemodModule::process()
|
|||
|
||||
data_out.write((char *)sym_buffer, dat_size * 2);
|
||||
|
||||
progress = file_source->getPosition();
|
||||
if (input_data_type == DATA_FILE)
|
||||
progress = file_source->getPosition();
|
||||
if (time(NULL) % 10 == 0 && lastTime != time(NULL))
|
||||
{
|
||||
lastTime = time(NULL);
|
||||
|
|
@ -107,7 +110,8 @@ void QPSKDemodModule::process()
|
|||
logger->info("Demodulation finished");
|
||||
|
||||
// Stop
|
||||
file_source->stop();
|
||||
if (input_data_type == DATA_FILE)
|
||||
file_source->stop();
|
||||
if (d_dc_block)
|
||||
dcb->stop();
|
||||
agc->stop();
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ protected:
|
|||
public:
|
||||
QPSKDemodModule(std::string input_file, std::string output_file_hint, std::map<std::string, std::string> parameters);
|
||||
~QPSKDemodModule();
|
||||
void init();
|
||||
void process();
|
||||
void drawUI();
|
||||
std::vector<ModuleDataType> getInputTypes();
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ void Pipeline::run(std::string input_file,
|
|||
module->setInputType(DATA_FILE);
|
||||
module->setOutputType(DATA_FILE);
|
||||
|
||||
module->init();
|
||||
|
||||
if (ui)
|
||||
{
|
||||
uiCallListMutex->lock();
|
||||
|
|
|
|||
194
src-ui/live.cpp
Normal file
194
src-ui/live.cpp
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
#include "live.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "global.h"
|
||||
#include "pipeline.h"
|
||||
#include <cstring>
|
||||
#include "logger.h"
|
||||
#include "portable-file-dialogs.h"
|
||||
#include "processing.h"
|
||||
#include <filesystem>
|
||||
|
||||
#ifdef BUILD_LIVE
|
||||
|
||||
int device_id = 0;
|
||||
|
||||
void renderLiveProcessing()
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
std::string names;
|
||||
|
||||
std::map<int, std::string> id_table;
|
||||
|
||||
for (int i = 0, y = 0; i < pipelines.size(); i++)
|
||||
{
|
||||
if (pipelines[i].live)
|
||||
{
|
||||
names += pipelines[i].readable_name + '\0';
|
||||
id_table.insert({y++, pipelines[i].name});
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Text("Pipeline : ");
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Combo("##pipeline", &pipeline_id, names.c_str()))
|
||||
{
|
||||
downlink_pipeline = id_table[pipeline_id];
|
||||
std::vector<Pipeline>::iterator it = std::find_if(pipelines.begin(),
|
||||
pipelines.end(),
|
||||
[](const Pipeline &e) {
|
||||
return e.name == downlink_pipeline;
|
||||
});
|
||||
std::memcpy(samplerate, std::to_string(it->default_samplerate).c_str(), std::to_string(it->default_samplerate).length());
|
||||
frequency = it->frequencies[frequency_id];
|
||||
}
|
||||
// ImGui::EndCombo();
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
ImGui::Text("Output dir : ");
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Select Output"))
|
||||
{
|
||||
logger->debug("Opening file dialog");
|
||||
auto result = pfd::select_folder("Open output directory", ".");
|
||||
while (result.ready(1000))
|
||||
{
|
||||
}
|
||||
|
||||
if (result.result().size() > 0)
|
||||
output_file = result.result();
|
||||
|
||||
logger->debug("Dir " + output_file);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(output_file.c_str());
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
ImGui::Text("Device : ");
|
||||
ImGui::SameLine();
|
||||
{
|
||||
std::string names = ""; // = "baseband\0";
|
||||
//std::vector<Pipeline>::iterator it = std::find_if(pipelines.begin(),
|
||||
// pipelines.end(),
|
||||
/// [](const Pipeline &e) {
|
||||
// return e.name == downlink_pipeline;
|
||||
// });
|
||||
|
||||
//if (it != pipelines.end())
|
||||
// for (int i = 0; i < it->frequencies.size(); i++)
|
||||
// {
|
||||
// names += std::to_string(it->frequencies[i]) + " Mhz" + '\0';
|
||||
// }
|
||||
|
||||
if (ImGui::Combo("##device", &device_id, names.c_str()))
|
||||
{
|
||||
//frequency = it->frequencies[frequency_id];
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Text("Frequency : ");
|
||||
ImGui::SameLine();
|
||||
{
|
||||
std::string names; // = "baseband\0";
|
||||
std::vector<Pipeline>::iterator it = std::find_if(pipelines.begin(),
|
||||
pipelines.end(),
|
||||
[](const Pipeline &e) {
|
||||
return e.name == downlink_pipeline;
|
||||
});
|
||||
|
||||
if (it != pipelines.end())
|
||||
for (int i = 0; i < it->frequencies.size(); i++)
|
||||
{
|
||||
names += std::to_string(it->frequencies[i]) + " Mhz" + '\0';
|
||||
}
|
||||
|
||||
if (ImGui::Combo("##frequency", &frequency_id, names.c_str()))
|
||||
{
|
||||
frequency = it->frequencies[frequency_id];
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Checkbox("DC Block", &dc_block);
|
||||
|
||||
ImGui::Text("Samplerate (Hz / SPS)");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##samplerate", samplerate, 100);
|
||||
|
||||
if (ImGui::Button("Start"))
|
||||
{
|
||||
logger->debug("Starting livedemod...");
|
||||
|
||||
if (output_file == "")
|
||||
{
|
||||
sprintf(error_message, "Please select an output file!");
|
||||
}
|
||||
else if (downlink_pipeline == "")
|
||||
{
|
||||
sprintf(error_message, "Please select a pipeline!");
|
||||
}
|
||||
else if (frequency <= 0)
|
||||
{
|
||||
sprintf(error_message, "Please select a frequency!");
|
||||
}
|
||||
else if (std::stoi(samplerate) <= 0)
|
||||
{
|
||||
sprintf(error_message, "Please select a samplerate!");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!std::filesystem::exists(output_file))
|
||||
std::filesystem::create_directory(output_file);
|
||||
|
||||
logger->info(downlink_pipeline);
|
||||
|
||||
std::vector<Pipeline>::iterator it = std::find_if(pipelines.begin(),
|
||||
pipelines.end(),
|
||||
[](const Pipeline &e) {
|
||||
return e.name == downlink_pipeline;
|
||||
});
|
||||
|
||||
if (it != pipelines.end())
|
||||
{
|
||||
|
||||
parameters.emplace("samplerate", std::string(samplerate));
|
||||
|
||||
parameters.emplace("baseband_format", "f32");
|
||||
|
||||
parameters.emplace("dc_block", dc_block ? "1" : "0");
|
||||
|
||||
std::map<std::string, std::string> final_parameters = it->steps[1].modules[0].parameters;
|
||||
for (const std::pair<std::string, std::string> ¶m : parameters)
|
||||
if (final_parameters.count(param.first) > 0)
|
||||
final_parameters[param.first] = param.second;
|
||||
else
|
||||
final_parameters.emplace(param.first, param.second);
|
||||
|
||||
logger->debug("Parameters :");
|
||||
for (const std::pair<std::string, std::string> ¶m : final_parameters)
|
||||
logger->debug(" - " + param.first + " : " + param.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->critical("Pipeline " + downlink_pipeline + " does not exist!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::TextColored(ImColor::HSV(0 / 360.0, 1, 1, 1.0), error_message);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
#endif
|
||||
6
src-ui/live.h
Normal file
6
src-ui/live.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
//#define BUILD_LIVE
|
||||
|
||||
#ifdef BUILD_LIVE
|
||||
void renderLiveProcessing();
|
||||
#endif
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
#include "init.h"
|
||||
#include "processing.h"
|
||||
#include "offline.h"
|
||||
#include "live.h"
|
||||
|
||||
static void glfw_error_callback(int error, const char *description)
|
||||
{
|
||||
|
|
@ -163,7 +164,11 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
if (ImGui::BeginTabItem("Live processing"))
|
||||
{
|
||||
#ifdef BUILD_LIVE
|
||||
renderLiveProcessing();
|
||||
#else
|
||||
ImGui::Text("Live support is currently being rewritten, and does not work on Windows yet. If you really need it, please stick to an older version.");
|
||||
#endif
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Credits"))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include "offline.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "global.h"
|
||||
#include "pipeline.h"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue