展示优化

This commit is contained in:
2026-08-03 11:22:23 +08:00
parent b8c1360175
commit ed601608b2
3 changed files with 132 additions and 43 deletions
+30 -1
View File
@@ -1,2 +1,31 @@
#include "BackEnd.h"
#include <QMetaObject>
Back_End::~Back_End() {
stop_mock_thread();
}
void Back_End::stop_mock_thread() {
++mock_generation;
QTimer* timer = mock_timer;
mock_timer = nullptr;
if (timer) {
if (timer->thread() == QThread::currentThread()) {
timer->stop();
delete timer;
}
else if (mock_thread && mock_thread->isRunning()) {
QMetaObject::invokeMethod(timer, [timer]() {
timer->stop();
delete timer;
}, Qt::BlockingQueuedConnection);
}
else {
delete timer;
}
}
if (!mock_thread)
return;
mock_thread->quit();
mock_thread->wait();
delete mock_thread;
mock_thread = nullptr;
}
+2 -17
View File
@@ -25,28 +25,13 @@ public:
QString get_screenshot_save_dir_path();
QString get_screenshot_save_file_name();
QString get_audio_file_location();
void stop_mock_thread() {
++mock_generation;
if (mock_timer) {
mock_timer->stop();
mock_timer->disconnect(this);
mock_timer->deleteLater();
mock_timer = nullptr;
}
if (mock_thread) {
mock_thread->quit();
mock_thread->wait();
mock_thread = nullptr;
}
}
void stop_mock_thread();
Back_End(const Back_End&) = delete;
Back_End& operator=(const Back_End&) = delete;
void call_back_data_func(int channel, void *pData, int i_length);
protected:
Back_End();
~Back_End() override {
stop_mock_thread();
}
~Back_End() override;
QTimer* mock_timer{};
std::uint64_t mock_generation{};
QThread* mock_thread{};
+100 -25
View File
@@ -8,9 +8,12 @@
#include "SweepFrequencyWidget.h"
#include <algorithm>
#include <cmath>
#include <memory>
#include <memory_resource>
#include <mutex>
#include <QByteArray>
#include <QDebug>
#include <QMetaObject>
#include <QPointer>
#include <utility>
#include <vector>
@@ -99,26 +102,59 @@ void push_radio_data(Radio_Widget* rw, Trace_Mode trace_mode) {
}
rw->progress_bar2->setValue(make_random_value({1, 5}));
}
void push_radio_data_perf(Radio_Widget* rw, Trace_Mode trace_mode) {
struct Mock_Performance_Frame {
std::pmr::vector<double> spectrum;
double spectrum_middle_power{};
renderive::Time_Of_Day waterfall_time;
std::pmr::vector<double> waterfall;
renderive::Time_Of_Day trace_time;
double trace_value{};
std::pmr::vector<double> audio;
double progress_value{};
};
struct Mock_Performance_Batch {
std::vector<Mock_Performance_Frame> frames;
};
struct Mock_Delivery_State {
std::mutex mutex;
std::shared_ptr<Mock_Performance_Batch> latest;
bool delivery_posted{};
};
std::shared_ptr<Mock_Performance_Batch> make_performance_batch(const Mock_Config& config) {
auto batch = std::make_shared<Mock_Performance_Batch>();
batch->frames.reserve(static_cast<std::size_t>(config.batch_count));
for (int i = 0; i < config.batch_count; ++i) {
auto spectrum = make_random_data({40, 120}, 1024, renderive::Memory_Domain::Spectrum);
double middle_power = spectrum.empty() ? 80.0 : spectrum[spectrum.size() / 2];
auto waterfall_time = current_render_time();
auto waterfall = make_random_data({0, 160}, 1024, renderive::Memory_Domain::Waterfall);
auto trace_time = current_render_time();
double trace_value = make_trace_value({-6000, 6000}, config.trace_mode);
auto audio = make_random_data({-6000, 6000}, 512, renderive::Memory_Domain::Spectrum);
batch->frames.push_back(Mock_Performance_Frame{
std::move(spectrum),
middle_power,
waterfall_time,
std::move(waterfall),
trace_time,
trace_value,
std::move(audio),
make_random_value({1, 5})
});
}
return batch;
}
void apply_performance_batch(Radio_Widget* rw, Mock_Performance_Batch& batch) {
if (!rw || !rw->spectrogram_line || !rw->water_fall || !rw->time_power || !rw->audio_spectrogram_plot || !rw->progress_bar1 || !rw->progress_bar2)
return;
{
renderive::Range nr = {40, 120};
auto data = make_random_data(nr, 1024, renderive::Memory_Domain::Spectrum);
double middle_power = data.empty() ? nr.center() : data[data.size() / 2];
rw->spectrogram_line->update_samples(std::move(data));
rw->progress_bar1->setValue(middle_power);
for (auto& frame : batch.frames) {
rw->spectrogram_line->update_samples(std::move(frame.spectrum));
rw->progress_bar1->setValue(frame.spectrum_middle_power);
rw->water_fall->append_row(frame.waterfall_time, std::move(frame.waterfall));
rw->time_power->append_sample(frame.trace_time, frame.trace_value);
rw->audio_spectrogram_plot->update_samples(std::move(frame.audio));
rw->progress_bar2->setValue(frame.progress_value);
}
{
rw->water_fall->append_row(current_render_time(), make_random_data({0, 160}, 1024, renderive::Memory_Domain::Waterfall));
}
{
rw->time_power->append_sample(current_render_time(), make_trace_value({-6000, 6000}, trace_mode));
}
{
rw->audio_spectrogram_plot->update_samples(make_random_data({-6000, 6000}, 512, renderive::Memory_Domain::Spectrum));
}
rw->progress_bar2->setValue(make_random_value({1, 5}));
}
}
void Back_End::play(const QString& fileName) {
@@ -194,16 +230,55 @@ Back_End::Back_End() {
QPointer<Radio_Widget> rw = Main_Widget::instance()->radio_widget;
if (!rw)
return;
mock_timer = new QTimer(this);
if (!config.performance) {
mock_timer = new QTimer(this);
mock_timer->setTimerType(Qt::PreciseTimer);
QObject::connect(mock_timer, &QTimer::timeout, this, [config, rw]() {
for (int i = 0; i < config.batch_count; ++i) {
if (!rw)
return;
push_radio_data(rw.data(), config.trace_mode);
}
});
mock_timer->start(config.interval_ms);
return;
}
auto delivery_state = std::make_shared<Mock_Delivery_State>();
mock_thread = new QThread(this);
mock_timer = new QTimer;
mock_timer->setTimerType(Qt::PreciseTimer);
QObject::connect(mock_timer, &QTimer::timeout, this, [config, rw]() {
for (int i = 0; i < config.batch_count; ++i) {
if (!rw)
return;
config.performance ? push_radio_data_perf(rw.data(), config.trace_mode) : push_radio_data(rw.data(), config.trace_mode);
}
mock_timer->setInterval(config.interval_ms);
mock_timer->moveToThread(mock_thread);
QTimer* timer = mock_timer;
QObject::connect(mock_thread, &QThread::started, timer, [timer]() {
timer->start();
});
mock_timer->start(config.interval_ms);
QObject::connect(timer, &QTimer::timeout, timer, [this, config, rw, delivery_state, start_generation]() {
auto batch = make_performance_batch(config);
bool post_delivery = false;
{
std::lock_guard<std::mutex> lock(delivery_state->mutex);
delivery_state->latest = std::move(batch);
if (!delivery_state->delivery_posted) {
delivery_state->delivery_posted = true;
post_delivery = true;
}
}
if (!post_delivery)
return;
QMetaObject::invokeMethod(this, [this, rw, delivery_state, start_generation]() {
std::shared_ptr<Mock_Performance_Batch> latest;
{
std::lock_guard<std::mutex> lock(delivery_state->mutex);
latest = std::move(delivery_state->latest);
delivery_state->delivery_posted = false;
}
if (start_generation != mock_generation || !rw || !latest)
return;
apply_performance_batch(rw.data(), *latest);
}, Qt::QueuedConnection);
});
mock_thread->start();
});
}
#endif