Skip to content

Commit

Permalink
Added header file comments for classes and methods.
Browse files Browse the repository at this point in the history
Renamed all factory methods to ::Build().
  • Loading branch information
rimio committed Jul 21, 2021
1 parent a7c430f commit ee8a157
Show file tree
Hide file tree
Showing 18 changed files with 526 additions and 151 deletions.
4 changes: 1 addition & 3 deletions src/color-map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
#include <cassert>

std::unique_ptr<ColorMap>
ColorMap::FromType(ColorMapType type,
const sf::Color& bg_color,
const sf::Color& custom_color)
ColorMap::Build(ColorMapType type, const sf::Color& bg_color, const sf::Color& custom_color)
{
/* colormaps are not allowed to be translucent */
sf::Color opaque_bg_color(bg_color.r, bg_color.g, bg_color.b, 255);
Expand Down
65 changes: 61 additions & 4 deletions src/color-map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,54 @@ enum class ColorMapType {
kCustom
};

/**
* Base color map class.
*
* This maps values in the domain [0..1] to 32bit RGBA colors, based on
* various color schemes.
*/
class ColorMap {
protected:
ColorMap() = default;

public:
ColorMap(const ColorMap&) = default;

static std::unique_ptr<ColorMap> FromType(ColorMapType type,
const sf::Color& bg_color,
const sf::Color& custom_color);

/**
* Factory method for colormaps.
* @param type One of ColorMapType.
* @param bg_color Background color (where applicable).
* @param custom_color Custom color (where applicable).
* @return A new ColorMap object.
*/
static std::unique_ptr<ColorMap> Build(ColorMapType type,
const sf::Color& bg_color,
const sf::Color& custom_color);

/**
* Map a window of real values to RGBA colours.
* @param input Array of floating point values in the domain [0..1].
* @return Array of bytes, 4 for each input value, RGBA format.
*/
virtual std::vector<uint8_t> Map(const RealWindow& input) const = 0;

/**
* Create a gradient of the colormap, displaying all possible colors.
* @param width Width of the gradient (in pixels).
* @return Array of bytes, one for each pixel, RGBA format.
*/
std::vector<uint8_t> Gradient(std::size_t width) const;

/**
* @return Copy of this colormap.
*/
virtual std::unique_ptr<ColorMap> Copy() const = 0;
};

/**
* Color map that linearly interpolates between a number of specified colors,
* based on value landmarks.
*/
class InterpolationColorMap : public ColorMap {
private:
const std::vector<sf::Color> colors_;
Expand All @@ -56,23 +87,49 @@ class InterpolationColorMap : public ColorMap {
std::vector<uint8_t> GetColor(double value) const;

public:
/**
* Create an interpolation-based colormap.
* @param colors Vectors of colors used for interpolation.
* @param vals The corresponding value for each color.
*
* NOTE: First value in "vals" must be 0.0 and last value must be "1.0".
* Thus, the whole [0..1] domain is covered.
*/
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;
};

/**
* Specialization for only two colors.
*/
class TwoColorMap : public InterpolationColorMap {
public:
/**
* @param c1 First color, corresponding to 0.0.
* @param c2 Second color, corresponding to 1.0.
*/
TwoColorMap(const sf::Color& c1, const sf::Color& c2);
};

/**
* Specialization for only three colors.
*/
class ThreeColorMap : public InterpolationColorMap {
public:
/**
* @param c1 First color, corresponding to 0.0.
* @param c2 Second color, corresponding to 0.5.
* @param c3 Third color, corresponding to 1.0.
*/
ThreeColorMap(const sf::Color& c1, const sf::Color& c2, const sf::Color& c3);
};

/**
* Jet colormap, as seen in MATLAB, matplotlib and others.
*/
class JetColorMap : public InterpolationColorMap {
public:
JetColorMap();
Expand Down
2 changes: 1 addition & 1 deletion src/configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ Configuration::StringToScale(const std::string &str)
}

std::tuple<Configuration, int, bool>
Configuration::FromArgs(int argc, char **argv)
Configuration::Build(int argc, char **argv)
{
Configuration conf;

Expand Down
95 changes: 57 additions & 38 deletions src/configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,48 +17,52 @@
#include <optional>
#include <tuple>

/**
* Configuration God object. This parses program arguments into usable,
* structured configuration options.
*/
class Configuration {
private:
std::optional<std::string> input_filename_;
std::optional<std::string> output_filename_;
bool dump_to_stdout_;

std::size_t block_size_;
double rate_;
DataType datatype_;
bool has_complex_input_;
double prescale_factor_;

std::size_t fft_width_;
std::size_t fft_stride_;
WindowFunctionType window_function_;
std::size_t average_count_;
bool alias_negative_;

bool no_resampling_;
std::size_t width_;
double min_freq_;
double max_freq_;
ValueMapType scale_type_;
std::string scale_unit_;
bool dump_to_stdout_; /* true if output PNG image must go to stdout */

std::size_t block_size_; /* group read values in blocks of block_size_ items */
double rate_; /* sampling rate of signal, in Hz */
DataType datatype_; /* input data type (does not cover complex/real discrimination) */
bool has_complex_input_; /* true if input is complex */
double prescale_factor_; /* value to scale input with before applying other transformations */

std::size_t fft_width_; /* size of FFT window, in values */
std::size_t fft_stride_; /* stride of FFT window, in values */
WindowFunctionType window_function_; /* window function to apply before FFT */
std::size_t average_count_; /* number of windows to average for each displayed window */
bool alias_negative_; /* alias negative frequencies to positive */

bool no_resampling_; /* do not perform resampling; if true, width_ is meaningless */
std::size_t width_; /* width of resampled output window, in values or pixels */
double min_freq_; /* lower bound of displayed frewquency band */
double max_freq_; /* upper bound of displayed frewquency band */
ValueMapType scale_type_; /* type of scale used on FFT output */
std::string scale_unit_; /* unit of the scale (just the text) */
double scale_lower_bound_;
double scale_upper_bound_;
ColorMapType color_map_;
sf::Color color_map_custom_color_;
sf::Color background_color_;
sf::Color foreground_color_;
bool has_axes_;
bool has_legend_;
bool is_horizontal_;
bool print_input_;
bool print_fft_;
bool print_output_;

bool live_;
std::size_t count_;
std::string title_;

bool has_live_window_;
ColorMapType color_map_; /* color map to apply to scaled output */
sf::Color color_map_custom_color_; /* custom color for color map (where applicable) */
sf::Color background_color_; /* background color of rendered output */
sf::Color foreground_color_; /* foreground color of rendered output (text, axes etc) */
bool has_axes_; /* render axes */
bool has_legend_; /* render legend */
bool is_horizontal_; /* flows from left to right, instead of top to bottom */
bool print_input_; /* debug printing of input */
bool print_fft_; /* debug printing of FFT values */
bool print_output_; /* debug printing of output */

bool live_; /* whether we have live output or not */
std::size_t count_; /* number of output windows to display in spectrogoram */
std::string title_; /* window title */

bool has_live_window_; /* display a live plot of the current FFT window */

std::size_t margin_size_;
std::size_t live_margin_size_;
Expand All @@ -69,15 +73,30 @@ class Configuration {

Configuration();

/**
* Translate a hex color to a sf::Color.
* @param str RGB/RGBA hex color code.
* @return Color.
*/
static sf::Color StringToColor(const std::string& str);

/**
* Parse a scale string.
* @param str Scale string.
* @return Optional bounds and unit string.
*/
using OptionalBound = std::optional<double>;
using ScaleProperties = std::tuple<OptionalBound, OptionalBound, std::string>;
static ScaleProperties StringToScale(const std::string& str);

public:
/* parse command line arguments and return a configuration object */
static std::tuple<Configuration, int, bool> FromArgs(int argc, char **argv);
/**
* Parse command line arguments and return a configuration object.
* @param argc Argument strings.
* @param argv Argument count.
* @return New Configuration object instance.
*/
static std::tuple<Configuration, int, bool> Build(int argc, char **argv);

/* generic getters */
Configuration GetForLive() const;
Expand Down
77 changes: 77 additions & 0 deletions src/fft.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

#include <fftw3.h>

/**
* Computes the fast Fourier transform of an input window.
*/
class FFT {
private:
/* FFT window width */
Expand All @@ -28,21 +31,95 @@ class FFT {
std::unique_ptr<WindowFunction> window_function_;

public:
/* plan and buffers are not copiable */
FFT() = delete;
FFT(const FFT &c) = delete;
FFT(FFT &&) = delete;
FFT & operator=(const FFT&) = delete;

/**
* @param win_width Width of window this object must support.
* NOTE: Only supports this window size!
*/
explicit FFT(std::size_t win_width);

/**
* @param win_width Width of window this object must support.
* @param win_func Window function to apply before FFT computations.
* NOTE: Only supports this window size!
*/
FFT(std::size_t win_width, std::unique_ptr<WindowFunction>& win_func);

virtual ~FFT();

/**
* Compute the fast Fourier transform.
* @param input Array of complex input values.
* @return Complex values corresponding to the FFT terms, equal in size to input.
*
* NOTE: This functions normalizes the output by 1/N.
* NOTE: This function provides the negative frequencies in the first half
* and the positive frequencies in the second half.
* NOTE: For even-sized inputs, the Nyquist frequency term is the last in
* the output vector.
*/
ComplexWindow Compute(const ComplexWindow& input);

/**
* Retrieve the (real) magnitudes of a complex input vector (window).
* @param input Array of complex values.
* @param alias If true, will alias negative and positive frequencies.
* @return Array of real values, containing amplitudes.
*
* NOTE: When aliasing, each output value will be the sum of that term's
* magnitude as well as the corresponding negative or positive
* frequency term's magnitude.
*/
static RealWindow GetMagnitude(const ComplexWindow& input, bool alias);

/**
* Compute the frequency bounds of a specific FFT window.
* @param rate Sampling rate of the input signal.
* @param width Width of the FFT window.
* @return Lower and upper bounds, in Hz.
*/
static std::tuple<double, double> GetFrequencyLimits(double rate, std::size_t width);

/**
* Compute the index in the FFT window of a given frequency.
* @param rate Sampling rate of input.
* @param width Width of the FFT window.
* @param f Frequency, in Hz.
* @return Index (computed exactly) of the frequency.
*/
static double GetFrequencyIndex(double rate, std::size_t width, double f);

/**
* Resample a real, scaled output of the FFT.
* @param input Real window, values between [0..1].
* @param rate Sampling rate of input.
* @param width Desired output width.
* @param fmin Frequency lower bound (from input).
* @param fmax Frequency upper bound (from input).
* @return Resampled values, clamped to [0..1].
*
* NOTE: Uses Lanczos resampling algorithm.
* NOTE: Will resize the [fmin..fmax] band from input (computed as if
* input is a FFT output) to a width-sized output window.
*/
static RealWindow Resample(const RealWindow& input, double rate, std::size_t width, double fmin, double fmax);

/**
* Crop a real, scaled output of the FFT.
* @param input Real window, values between [0..1].
* @param rate Sampling rate of input.
* @param fmin fmin Frequency lower bound (from input).
* @param fmax fmax Frequency upper bound (from input).
* @return Cropped window.
*
* NOTE: The [fmin..fmax] band from input is computed as if input is a FFT
* output, which under normal circumstances it should be.
*/
static RealWindow Crop(const RealWindow& input, double rate, double fmin, double fmax);
};

Expand Down
2 changes: 1 addition & 1 deletion src/input-parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ InputParser::RemoveValues(std::size_t count)
}

std::unique_ptr<InputParser>
InputParser::FromDataType(DataType dtype, double prescale, bool is_complex)
InputParser::Build(DataType dtype, double prescale, bool is_complex)
{
if (dtype == DataType::kSignedInt8) {
return std::make_unique<IntegerInputParser<std::int8_t>>(prescale, is_complex);
Expand Down
Loading

0 comments on commit ee8a157

Please sign in to comment.