/* * Copyright (c) 2020-2021 Vasile Vilvoiu * * specgram is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef _RENDERER_HPP_ #define _RENDERER_HPP_ #include "configuration.hpp" #include #include #include /* Orientation */ enum class Orientation { k90CCW, kNormal, k90CW, k180 }; /** * Spectrogram rendering class */ class Renderer { private: const Configuration configuration_; /* configuration is cached as it contains multiple settings regarding spacing and sizing */ const std::size_t fft_count_; /* number of windows to render */ const std::unique_ptr color_map_; /* color map used for rendering */ sf::Font font_; sf::RenderTexture canvas_; sf::Texture fft_area_texture_; /* actual spectrogram area */ std::size_t width_; std::size_t height_; sf::Transform legend_transform_; sf::Transform fft_live_transform_; sf::Transform fft_area_transform_; /** * First value specifies the position of the tick in the domain [0..1]. * Second value is the text of the tick. */ using AxisTick = std::tuple; std::list frequency_ticks_; std::list live_ticks_; /** * Build an array of ticks with linear spacing. * @param v_min Lowest value on the axis. * @param v_max Highest value on the axis. * @param v_unit Unit of the axis. * @param num_ticks Number of ticks to generate. * @return Array of ticks. */ [[maybe_unused]] /* need for this method disappeared when fixing #9, might be useful in the future */ static std::list GetLinearTicks(double v_min, double v_max, const std::string& v_unit, unsigned int num_ticks); /** * Build an array of nicely spaced ticks. * @param v_min Lowest value on the axis. * @param v_max Highest value on the axis. * @param v_unit Unit of the axis. * @param length_px Length of the scale, in pixels (used for spacing estimation). * @param min_tick_length_px Minimum tick spacing. * @param rotated If true then vertical. Otherwise horizontal. * @return Array of ticks. * * NOTE: This method attempts to find some nice values for the ticks that * also have sufficient spacing for the text to fit properly. */ std::list GetNiceTicks(double v_min, double v_max, const std::string& v_unit, unsigned int length_px, unsigned int min_tick_length_px, bool rotated); /** * Render an axis upon a texture * @param texture Texture to render to. * @param t Transform to use. * @param lhs True if has left-hand side text. * @param orientation One of Orientation. * @param length Length in pixels. * @param ticks Ticks. */ void RenderAxis(sf::RenderTexture& texture, const sf::Transform& t, bool lhs, Orientation orientation, double length, const std::list& ticks); public: Renderer() = delete; Renderer(const Configuration& conf, const ColorMap& cmap, const ValueMap& vmap, std::size_t fft_count); /** * Render the spectrogram area. * @param memory RGBA memory of the colorized spectrogram. */ void RenderFFTArea(const std::vector& memory); /** * Render the spectrogram area. * @param history List of RGBA colorized windows. */ void RenderFFTArea(const std::list>& history); std::vector RenderLiveFFT(const RealWindow& window); /** * @return The rendered canvas texture. */ sf::Texture GetCanvas(); /* size getters */ auto GetWidth() const { return width_; } auto GetHeight() const { return height_; } }; #endif