summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasile Vilvoiu <vasi@vilvoiu.ro>2021-07-16 21:00:28 +0300
committerVasile Vilvoiu <vasi@vilvoiu.ro>2021-07-16 21:00:28 +0300
commit68e6ebe24cb476997b2ddfc21a5b13fb6f332fa7 (patch)
tree646db708a2db1b61904003c81a05b01358cdb4cc
parentb13609afcdf66d781db70fb75f6869a052a49079 (diff)
Render texture onto window on each iteration.
Keep colormap in renderer so we don't pass the colormapped windows like animals. Pre-render empty window. Fixes #15.
-rw-r--r--src/color-map.cpp5
-rw-r--r--src/color-map.hpp7
-rw-r--r--src/live.cpp20
-rw-r--r--src/live.hpp2
-rw-r--r--src/renderer.cpp16
-rw-r--r--src/renderer.hpp3
-rw-r--r--src/specgram.cpp21
7 files changed, 44 insertions, 30 deletions
diff --git a/src/color-map.cpp b/src/color-map.cpp
index a47d98c..d1d199a 100644
--- a/src/color-map.cpp
+++ b/src/color-map.cpp
@@ -124,6 +124,11 @@ InterpolationColorMap::Map(const RealWindow& input) const
return output;
}
+std::unique_ptr<ColorMap> InterpolationColorMap::Copy() const
+{
+ return std::make_unique<InterpolationColorMap>(colors_, values_);
+}
+
TwoColorMap::TwoColorMap(const sf::Color& c1, const sf::Color& c2)
: InterpolationColorMap({ c1, c2 }, { 0.0f, 1.0f })
{
diff --git a/src/color-map.hpp b/src/color-map.hpp
index 4c89275..139edaf 100644
--- a/src/color-map.hpp
+++ b/src/color-map.hpp
@@ -44,6 +44,8 @@ public:
virtual std::vector<uint8_t> Map(const RealWindow& input) const = 0;
std::vector<uint8_t> Gradient(std::size_t width) const;
+
+ virtual std::unique_ptr<ColorMap> Copy() const = 0;
};
class InterpolationColorMap : public ColorMap {
@@ -53,13 +55,12 @@ private:
std::vector<uint8_t> GetColor(double value) const;
-protected:
- InterpolationColorMap(const std::vector<sf::Color>& colors, const std::vector<double>& vals);
-
public:
+ InterpolationColorMap(const std::vector<sf::Color>& colors, const std::vector<double>& vals);
InterpolationColorMap() = delete;
std::vector<uint8_t> Map(const std::vector<double>& input) const override;
+ std::unique_ptr<ColorMap> Copy() const override;
};
class TwoColorMap : public InterpolationColorMap {
diff --git a/src/live.cpp b/src/live.cpp
index f1ae3d6..641eb7d 100644
--- a/src/live.cpp
+++ b/src/live.cpp
@@ -23,11 +23,17 @@ LiveOutput::LiveOutput(const Configuration& conf, const ColorMap& cmap, const Va
/* FFT area raw memory used to update the area texture */
this->fft_area_.resize(conf.GetWidth() * conf.GetCount() * 4); /* RGBA pixel array */
+
+ /* render the live FFT area with a DC signal of zero */
+ Render(); /* I don't have a good idea why this is needed, but I guess it has something to do with double buffering */
+ this->renderer_.RenderFFTArea(this->fft_area_);
+ this->renderer_.RenderLiveFFT(RealWindow(conf.GetWidth()));
}
-void
-LiveOutput::AddWindow(const std::vector<uint8_t>& window, const RealWindow& win_values)
+std::vector<uint8_t>
+LiveOutput::AddWindow(const RealWindow& win_values)
{
+ auto window = this->renderer_.RenderLiveFFT(win_values);
std::size_t wlen_bytes = this->configuration_.GetWidth() * 4;
if (window.size() != wlen_bytes) {
throw std::runtime_error("input window size differs from live window size");
@@ -43,12 +49,9 @@ LiveOutput::AddWindow(const std::vector<uint8_t>& window, const RealWindow& win_
reinterpret_cast<const void *>(window.data()),
wlen_bytes);
- /* update renderer */
+ /* update renderer texture */
this->renderer_.RenderFFTArea(this->fft_area_);
- this->renderer_.RenderLiveFFT(win_values, window);
-
- /* draw window */
- this->Render();
+ return window;
}
bool
@@ -65,6 +68,7 @@ LiveOutput::HandleEvents()
void
LiveOutput::Render()
{
+ /* draw renderer output to window */
sf::Texture canvas_texture = this->renderer_.GetCanvas();
sf::Sprite canvas_sprite(canvas_texture);
if (this->configuration_.IsHorizontal()) {
@@ -74,4 +78,4 @@ LiveOutput::Render()
this->window_.draw(canvas_sprite);
this->window_.display();
-} \ No newline at end of file
+}
diff --git a/src/live.hpp b/src/live.hpp
index 5f6eb86..d7baa61 100644
--- a/src/live.hpp
+++ b/src/live.hpp
@@ -32,7 +32,7 @@ public:
LiveOutput(const Configuration& conf, const ColorMap& cmap, const ValueMap& vmap);
- void AddWindow(const std::vector<uint8_t>& window, const RealWindow& win_values);
+ std::vector<uint8_t> AddWindow(const RealWindow& win_values);
bool HandleEvents();
void Render();
};
diff --git a/src/renderer.cpp b/src/renderer.cpp
index 05fea43..e482bb0 100644
--- a/src/renderer.cpp
+++ b/src/renderer.cpp
@@ -38,8 +38,11 @@ ValueToShortString(double value, int prec, const std::string& unit)
}
Renderer::Renderer(const Configuration& conf, const ColorMap& cmap, const ValueMap& vmap, std::size_t fft_count)
- : configuration_(conf), fft_count_(fft_count)
+ : configuration_(conf), fft_count_(fft_count), color_map_(cmap.Copy())
{
+ if (color_map_ == nullptr) {
+ throw std::runtime_error("failed to copy color map");
+ }
if (fft_count == 0) {
throw std::runtime_error("positive number of FFT windows required by rendere");
}
@@ -436,18 +439,18 @@ Renderer::RenderFFTArea(const std::list<std::vector<uint8_t>>& history)
return this->RenderFFTArea(memory);
}
-void
-Renderer::RenderLiveFFT(const RealWindow& window, const std::vector<uint8_t>& colors)
+std::vector<uint8_t>
+Renderer::RenderLiveFFT(const RealWindow& window)
{
if (window.size() != this->configuration_.GetWidth()) {
throw std::runtime_error("incorrect window size to be rendered");
}
-
if (!this->configuration_.HasLiveWindow()) {
- /* noop */
- return;
+ throw std::runtime_error("asked to render live window for non-live configuration");
}
+ std::vector<uint8_t> colors = this->color_map_->Map(window);
+
/* FFT live box (so we overwrite old one */
sf::RectangleShape fft_live_box(sf::Vector2f(this->configuration_.GetWidth(),
this->configuration_.GetLiveFFTHeight() + 1.0f));
@@ -488,6 +491,7 @@ Renderer::RenderLiveFFT(const RealWindow& window, const std::vector<uint8_t>& co
this->canvas_.draw(reinterpret_cast<sf::Vertex *>(vertices.data()), vertices.size(),
sf::LineStrip, this->fft_live_transform_);
+ return colors;
}
sf::Texture
diff --git a/src/renderer.hpp b/src/renderer.hpp
index a473a2a..01ce397 100644
--- a/src/renderer.hpp
+++ b/src/renderer.hpp
@@ -30,6 +30,7 @@ class Renderer {
private:
const Configuration configuration_;
const std::size_t fft_count_;
+ const std::unique_ptr<const ColorMap> color_map_;
sf::Font font_;
@@ -63,7 +64,7 @@ public:
/* render commands */
void RenderFFTArea(const std::vector<uint8_t>& memory);
void RenderFFTArea(const std::list<std::vector<uint8_t>>& history);
- void RenderLiveFFT(const RealWindow& window, const std::vector<uint8_t>& colors);
+ std::vector<uint8_t> RenderLiveFFT(const RealWindow& window);
/* canvas builder */
sf::Texture GetCanvas();
diff --git a/src/specgram.cpp b/src/specgram.cpp
index cb646fc..d70126f 100644
--- a/src/specgram.cpp
+++ b/src/specgram.cpp
@@ -165,6 +165,7 @@ main(int argc, char** argv)
std::unique_ptr<LiveOutput> live = nullptr;
if (conf.IsLive()) {
live = std::make_unique<LiveOutput>(conf, *color_map, *value_map);
+ live->Render(); /* render empty window */
}
/* create input parser */
@@ -218,7 +219,7 @@ main(int argc, char** argv)
/* main loop */
while (main_loop_running && !reader->ReachedEOF()) {
- /* check for window events (if necessary) */
+ /* check for window events (if necessary) and redraw */
if (live != nullptr) {
if (!live->HandleEvents()) {
/* exited by closing window */
@@ -226,6 +227,7 @@ main(int argc, char** argv)
/* uninstall signal so that reader thread can exit successfully */
std::signal(SIGINT, nullptr);
}
+ live->Render();
}
/* check for a complete block */
@@ -282,7 +284,7 @@ main(int argc, char** argv)
assert(window_sum.size() == normalized_magnitude.size());
assert(conf.GetAverageCount() > 0);
for (std::size_t i = 0; i < window_sum.size(); i++) {
- window_sum[i] += normalized_magnitude[i] / conf.GetAverageCount();
+ window_sum[i] += normalized_magnitude[i] / (double)conf.GetAverageCount();
}
window_sum_count++;
@@ -291,17 +293,14 @@ main(int argc, char** argv)
continue;
}
- /* colorize FFT */
- auto colorized = color_map->Map(window_sum);
-
/* add to live */
if (live != nullptr) {
- live->AddWindow(colorized, window_sum);
- }
-
- /* add to history */
- if (have_output) {
- history.push_back(colorized);
+ auto colorized = live->AddWindow(window_sum);
+ if (have_output) {
+ history.push_back(colorized);
+ }
+ } else if (have_output) {
+ history.push_back(color_map->Map(window_sum));
}
/* reset */