HART  0.2.0
High level Audio Regression and Testing
Loading...
Searching...
No Matches
hart_plot.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "dependencies/choc/platform/choc_DisableAllWarnings.h"
4#include "dependencies/signalsmith/plot.h"
5#include "dependencies/choc/platform/choc_ReenableAllWarnings.h"
6
8
9namespace hart {
10
11/// @brief Plots audio buffers as an svg file
12/// @private
13template <typename SampleType>
14void plotData (const AudioBuffer<SampleType>& input, const AudioBuffer<SampleType>& output, const std::string& plotFilePath)
15{
16 // Missing sample rates are not a big deal, but
17 // we're expecting this method to be called by the
18 // test runner, where sample rates are properly defined
19 hassert (input.hasSampleRate());
20 hassert (output.hasSampleRate());
21 hassert (! floatsEqual (input.getSampleRateHz(), 0.0));
22 hassert (! floatsEqual (output.getSampleRateHz(), 0.0));
23 hassert (floatsEqual (input.getSampleRateHz(), output.getSampleRateHz()));
24
25 const double bufferSizeSeconds = output.getLengthSeconds();
26 const double timeIncrementSeconds = 1.0 / output.getSampleRateHz();
27
28 signalsmith::plot::Figure figure;
29 auto& inputSignalPlot = figure (0, 0).plot (1200, 200);
30 auto& outputSignalPlot = figure (0, 1).plot (1200, 200);
31
32 inputSignalPlot.y.major (0).label ("Value");
33 outputSignalPlot.y.major (0).label ("Value");
34 inputSignalPlot.x.major (0);
35 outputSignalPlot.x.major (0).label("Time (s)");
36 inputSignalPlot.title ("Input audio");
37 outputSignalPlot.title ("Output audio");
38
39 const SampleType inputSamplePeak = input.getMagnitude (0, input.getNumFrames());
40 inputSignalPlot.y.minor (inputSamplePeak).minor (-inputSamplePeak);
41 const SampleType outputSamplePeak = output.getMagnitude (0, output.getNumFrames());
42 outputSignalPlot.y.minor (outputSamplePeak).minor (-outputSamplePeak);
43
44 for (double t = 0.1; t < bufferSizeSeconds + 1e-6; t += 0.1)
45 {
46 inputSignalPlot.x.minor (t);
47 outputSignalPlot.x.minor (t);
48 }
49
50 for (double t = 1.0; t < bufferSizeSeconds + 1e-6; t += 1.0)
51 {
52 inputSignalPlot.x.major (t);
53 outputSignalPlot.x.major (t);
54 }
55
56 double timeSeconds = 0.0;
57
58 for (size_t channel = 0; channel < input.getNumChannels(); ++channel)
59 {
60 auto &inputSignalLine = inputSignalPlot.line();
61
62 for (size_t frame = 0; frame < input.getNumFrames(); ++frame)
63 {
64 inputSignalLine.add (timeSeconds, input[channel][frame]);
65 timeSeconds += timeIncrementSeconds;
66 }
67 }
68
69 timeSeconds = 0.0;
70
71 for (size_t channel = 0; channel < output.getNumChannels(); ++channel)
72 {
73 auto &outputSignalLine = outputSignalPlot.line();
74
75 for (size_t frame = 0; frame < output.getNumFrames(); ++frame)
76 {
77 outputSignalLine.add (timeSeconds, output[channel][frame]);
78 timeSeconds += timeIncrementSeconds;
79 }
80 }
81
82 figure.write (plotFilePath);
83}
84
85} // namespace hart
Container for audio data.
#define hassert(condition)
Triggers a HartAssertException if the condition is false