Beatmup
signal_plot.cpp
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2019, lnstadrum
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "signal_plot.h"
20 #include "../color/constants.h"
21 #include "../bitmap/bitmap_access.h"
22 #include "../bitmap/processing.h"
23 #include <algorithm>
24 #include <vector>
25 
26 using namespace Beatmup;
27 using namespace Audio;
28 
29 namespace Kernels {
30  template<class out_t> class DrawBars3 {
31  public:
32 
33  /**
34  Plots three vertical bars
35  \param bitmap A bitmap to draw onto
36  \param x The horizontal coordinate
37  \param y The bar top vertical coordinate
38  \param y1 End of first bar (excluded)
39  \param y2 End of second bar (included)
40  \param y3 End of third bar (included)
41  \param color1 Color of 1st and 3rd bars
42  \param color2 Color of 2nd bar
43  */
44  static void process(AbstractBitmap& bitmap, int x, int y, int y1, int y2, int y3, const color4i& color1, const color4i& color2) {
45  out_t ptr(bitmap, x, y);
46  out_t ref = ptr;
47  ref.goTo(x, y1);
48  while (ptr < ref) {
50  ptr += ptr.getWidth();
51  }
52  ref.goTo(x, y2);
53  while (ptr < ref) {
55  ptr += ptr.getWidth();
56  }
58  ptr += ptr.getWidth();
59  ref.goTo(x, y3);
60  while (ptr < ref) {
62  ptr += ptr.getWidth();
63  }
65  }
66  };
67 
68 
69  template<typename out_t> class DrawBars5 {
70  public:
71 
72  /**
73  Plots five vertical bars
74  \param bitmap A bitmap to draw onto
75  \param x The horizontal coordinate
76  \param y The bar top vertical coordinate
77  \param y1 End of first bar (excluded)
78  \param y2 End of second bar (excluded)
79  \param y3 End of third bar (included)
80  \param y4 End of fourth bar (included)
81  \param y5 End of fifth bar (included)
82  \param color1 Color of 1st and 5th bars
83  \param color2 Color of 2nd and 4th bars
84  \param color3 Color of 3rd bar
85  */
86  static void process(
88  int x, int y, int y1, int y2, int y3, int y4, int y5,
89  const color4i& color1, const color4i& color2, const color4i& color3
90  ) {
91  out_t ptr(bitmap, x, y);
92  out_t ref = ptr;
93  ref.goTo(x, y1);
94  while (ptr < ref) {
96  ptr += ptr.getWidth();
97  }
98  ref.goTo(x, y2);
99  while (ptr < ref) {
100  ptr = pixint4::fromColor(color2);
101  ptr += ptr.getWidth();
102  }
103  ref.goTo(x, y3);
104  while (ptr < ref) {
105  ptr = pixint4::fromColor(color3);
106  ptr += ptr.getWidth();
107  }
108  ptr = pixint4::fromColor(color3);
109  ptr += ptr.getWidth();
110  ref.goTo(x, y4);
111  while (ptr < ref) {
112  ptr = pixint4::fromColor(color2);
113  ptr += ptr.getWidth();
114  }
115  if (y3 < y4) {
116  ptr = pixint4::fromColor(color2);
117  ptr += ptr.getWidth();
118  }
119  ref.goTo(x, y5);
120  while (ptr < ref) {
121  ptr = pixint4::fromColor(color1);
122  ptr += ptr.getWidth();
123  }
124  ptr = pixint4::fromColor(color1);
125  }
126  };
127 }
128 
129 
130 void SignalPlot::getPlot(TaskThread& thread, std::vector<int>& data, int& left, int& right) {
131  const dtime
132  startTime = signalWindow.a.x + thread.currentThread() * signalWindow.width() / thread.numThreads(),
133  stopTime = signalWindow.a.x + (thread.currentThread() + 1) * signalWindow.width() / thread.numThreads(),
134  length = stopTime - startTime;
135  left = thread.currentThread() * outputRect.width() / thread.numThreads();
136  right = (thread.currentThread() + 1) * outputRect.width() / thread.numThreads();
137 
138  const int width = right - left;
139 
140  const float
141  mag = (float)signalWindow.height(),
142  heightMag = (outputRect.height() - 1) / mag;
143 
144  // measure!
145  const int count = width * signal->getChannelCount();
146  typedef sample16 sample;
147  sample *min = new sample[count], *max = new sample[count];
148  Signal::Meter ptr(*signal, startTime);
149  ptr.measure<sample>(length, width, min, max);
150 
151  // compute bin heights in function of the channel mode
152  // single channel
153  if (0 <= channels && channels < signal->getChannelCount()) {
154  data.reserve(2 * width);
155  sample* pMin = min + channels, *pMax = max + channels;
156  for (int x = 0; x < width; x++) {
157  data.push_back( outputRect.b.y - (int)std::min(std::max(.0f, pMin->x * scale - signalWindow.a.y), mag) * heightMag );
158  data.push_back( outputRect.b.y - (int)std::min(std::max(.0f, pMax->x * scale - signalWindow.a.y), mag) * heightMag );
159  pMin += channels;
160  pMax += channels;
161  }
162  }
163  // combined channels: minmin --- minmax *** maxmin --- maxmax
164  else {
165  data.reserve(4 * width);
166  sample* pMin = min, *pMax = max;
167  for (int x = 0; x < width; x++) {
168  sample ymm = *pMin++, ymM = ymm, yMm = *pMax++, yMM = yMm;
169  for (int ch = 1; ch < signal->getChannelCount(); ch++) {
170  ymm = std::min(ymm, *pMin);
171  ymM = std::max(ymM, *pMin++);
172  yMm = std::min(yMm, *pMax);
173  yMM = std::max(yMM, *pMax++);
174  }
175  if (yMm < ymM) {
176  sample _ = ymM;
177  ymM = yMm;
178  yMm = _;
179  }
180  data.push_back(outputRect.b.y - (int)std::min(std::max(.0f, yMM.x * scale - signalWindow.a.y), mag) * heightMag);
181  data.push_back(outputRect.b.y - (int)std::min(std::max(.0f, yMm.x * scale - signalWindow.a.y), mag) * heightMag);
182  data.push_back(outputRect.b.y - (int)std::min(std::max(.0f, ymM.x * scale - signalWindow.a.y), mag) * heightMag);
183  data.push_back(outputRect.b.y - (int)std::min(std::max(.0f, ymm.x * scale - signalWindow.a.y), mag) * heightMag);
184  }
185  }
186  delete[] min;
187  delete[] max;
188 }
189 
190 
192  signal(NULL), bitmap(NULL), outputRect(0,0,100,100), signalWindow(0,-32768,100,32767), scale(1.0f), channels(-1)
193  //fixme: set reasonable values
194 {
195  palette.bgColor = Color::WHITE;
198 }
199 
200 
202  std::vector<int> yyy;
203  int x0, x1;
204  getPlot(thread, yyy, x0, x1);
205  thread.synchronize();
206  auto y = yyy.begin();
207  // single channel
208  if (0 <= channels && channels < signal->getChannelCount())
209  for (int x = x0; x < x1 && !thread.isTaskAborted(); x++) {
210  int y0 = *y++, y1 = *y++;
211  BitmapProcessing::write<Kernels::DrawBars3>(*bitmap, x, outputRect.a.y, y0, y1, outputRect.b.y, palette.bgColor, palette.color1);
212  }
213  // all channels
214  else
215  for (int x = x0; x < x1 && !thread.isTaskAborted(); x++) {
216  int y0 = *y++, y1 = *y++, y2 = *y++, y3 = *y++;
217  BitmapProcessing::write<Kernels::DrawBars5>(
218  *bitmap, x, outputRect.a.y, y0, y1, y2, y3, outputRect.b.y,
219  palette.bgColor, palette.color1, palette.color2
220  );
221  }
222  return true;
223 }
224 
225 
227  NullTaskInput::check(signal, "input signal");
228  NullTaskInput::check(bitmap, "output bitmap");
232 }
233 
234 
236  unlock(bitmap);
237 }
238 
239 
242 }
243 
244 
246  BEATMUP_ASSERT_DEBUG(bitmap != nullptr);
247  return validThreadCount(bitmap->getWidth());
248 }
249 
250 
252  this->signal = signal;
253 }
254 
255 
257  this->bitmap = bitmap;
258 }
259 
260 
262  this->outputRect = rectangle;
263 }
264 
265 
267  this->signalWindow = window;
268  this->scale = scale;
269 }
270 
271 
273  palette.bgColor = bgColor;
274  palette.color1 = color1;
275  palette.color2 = color2;
276 }
277 
278 
280  this->channels = channels;
281 }
A very basic class for any image.
static ThreadIndex validThreadCount(int number)
Valid thread count from a given integer value.
Definition: parallelism.cpp:45
TaskDeviceRequirement
Specifies which device (CPU and/or GPU) is used to run the task.
Definition: parallelism.h:95
@ CPU_ONLY
this task does not use GPU
virtual ThreadIndex getMaxThreads() const
Gives the upper limint on the number of threads the task may be performed by.
struct Beatmup::Audio::SignalPlot::@0 palette
void setSignal(Signal *)
Sets the input signal to plot.
void getPlot(TaskThread &thread, std::vector< int > &data, int &left, int &right)
void setChannels(int channels)
Specifies which channels to plot.
void setPlotArea(IntRectangle)
Specifies a rectangular area in pixels in the output bitmap where the plot will be drawn.
AbstractBitmap * bitmap
Definition: signal_plot.h:34
void setPalette(color4i bgColor, color4i color1, color4i color2)
Specifies plot colors.
virtual void beforeProcessing(ThreadIndex, ProcessingTarget target, GraphicPipeline *)
Instruction called before the task is executed.
void setWindow(IntRectangle window, float scale)
Specifies a time range (X coordinate) and a magnitude range (Y coordinate scaled by scale) that will ...
virtual void afterProcessing(ThreadIndex, GraphicPipeline *, bool)
Instruction called after the task is executed.
virtual TaskDeviceRequirement getUsedDevices() const
Communicates devices (CPU and/or GPU) the task is run on.
virtual bool process(TaskThread &thread)
Executes the task on CPU within a given thread.
void setBitmap(AbstractBitmap *)
Sets the output bitmap.
Signal dynamics meter.
Definition: signal.h:71
void measure(dtime len, int resolution, sample min[], sample max[])
Measures signal dynamics in a given period of time.
An audio signal.
Definition: signal.h:36
unsigned char getChannelCount() const
Definition: signal.h:232
void unlock(AbstractBitmap *bitmap)
Drops a lock to the bitmap.
void writeLock(GraphicPipeline *gpu, AbstractBitmap *bitmap, ProcessingTarget target)
Locks content of a bitmap for writing using a specific processing target device.
numeric height() const
Definition: geometry.h:178
CustomPoint< numeric > b
Definition: geometry.h:131
numeric width() const
Definition: geometry.h:174
CustomPoint< numeric > a
Definition: geometry.h:131
void normalize()
Flips corners coordinates guaranteeing that it has a non negative area, i.e.
Definition: geometry.h:192
virtual const int getWidth() const =0
Width of the texture in pixels.
Internal low-level GPU control API.
Definition: pipeline.h:33
static void check(const void *pointer, const char *which)
Definition: exception.h:115
Thread executing tasks.
Definition: parallelism.h:154
virtual ThreadIndex numThreads() const =0
virtual void synchronize()=0
Blocks until all the other threads running the same task reach the same point.
ThreadIndex currentThread() const
Definition: parallelism.h:165
virtual bool isTaskAborted() const =0
Returns true if the task is asked to stop from outside.
static void process(AbstractBitmap &bitmap, int x, int y, int y1, int y2, int y3, const color4i &color1, const color4i &color2)
Plots three vertical bars.
Definition: signal_plot.cpp:44
static void process(AbstractBitmap &bitmap, int x, int y, int y1, int y2, int y3, int y4, int y5, const color4i &color1, const color4i &color2, const color4i &color3)
Plots five vertical bars.
Definition: signal_plot.cpp:86
#define BEATMUP_ASSERT_DEBUG(C)
Definition: exception.h:163
static const color4i DARK_SEA_GREEN2
Definition: constants.h:29
static const color4i DARK_SEA_GREEN1
Definition: constants.h:28
static const color4i WHITE
Definition: constants.h:26
unsigned char ThreadIndex
number of threads / thread index
Definition: parallelism.h:68
int dtime
discrete time
Definition: basic_types.h:37
ProcessingTarget
Definition: basic_types.h:55
Operations kernels.
Definition: basic_types.h:85
CustomPoint< numeric > min(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:724
CustomPoint< numeric > max(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:728
static pixint4 fromColor(const color4i &_)
JNIEnv jlong jint jint color1
JNIEnv jlong jint jint jint jint y2
JNIEnv jlong jint jint jint jint jfloat scale
JNIEnv jobject jint jint jint channels
JNIEnv jlong jint x1
return signal getChannelCount()
JNIEnv jlong jint jint jint color2
JNIEnv jlong jint jint jint y1
jobject jlong jint jint y
JNIEnv jlong jint jint count
jlong jint width
jobject jlong jint x
Beatmup::InternalBitmap * bitmap
jlong jlong jint jint jint jint jint left