Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

289 lines
7.7KB

  1. /*
  2. * Digital Peak Meter, a custom Qt4 widget
  3. * Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or 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. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "digitalpeakmeter.hpp"
  18. #include <QtGui/QPainter>
  19. #include <QtGui/QPaintEvent>
  20. DigitalPeakMeter::DigitalPeakMeter(QWidget* parent)
  21. : QWidget(parent),
  22. fChannels(0),
  23. fSmoothMultiplier(1),
  24. fWidth(0),
  25. fHeight(0),
  26. fSizeMeter(0),
  27. fOrientation(VERTICAL),
  28. fColorBackground("#111111"),
  29. fGradientMeter(0, 0, 1, 1),
  30. fColorBase(93, 231, 61),
  31. fColorBaseAlt(15, 110, 15, 100),
  32. fChannelsData(nullptr),
  33. fLastValueData(nullptr)
  34. {
  35. setChannels(0);
  36. setColor(GREEN);
  37. }
  38. DigitalPeakMeter::~DigitalPeakMeter()
  39. {
  40. if (fChannelsData != nullptr)
  41. delete[] fChannelsData;
  42. if (fLastValueData != nullptr)
  43. delete[] fLastValueData;
  44. }
  45. void DigitalPeakMeter::displayMeter(int meter, float level)
  46. {
  47. Q_ASSERT(fChannelsData != nullptr);
  48. Q_ASSERT(meter > 0 && meter <= fChannels);
  49. if (meter <= 0 || meter > fChannels || fChannelsData == nullptr)
  50. return qCritical("DigitalPeakMeter::displayMeter(%i, %f) - invalid meter number", meter, level);
  51. int i = meter - 1;
  52. if (fSmoothMultiplier > 0)
  53. level = (fLastValueData[i] * fSmoothMultiplier + level) / float(fSmoothMultiplier + 1);
  54. if (level < 0.001f)
  55. level = 0.0f;
  56. else if (level > 0.999f)
  57. level = 1.0f;
  58. if (fChannelsData[i] != level)
  59. {
  60. fChannelsData[i] = level;
  61. update();
  62. }
  63. fLastValueData[i] = level;
  64. }
  65. void DigitalPeakMeter::setChannels(int channels)
  66. {
  67. Q_ASSERT(channels >= 0);
  68. if (channels < 0)
  69. return qCritical("DigitalPeakMeter::setChannels(%i) - 'channels' must be a positive integer", channels);
  70. fChannels = channels;
  71. if (fChannelsData != nullptr)
  72. delete[] fChannelsData;
  73. if (fLastValueData != nullptr)
  74. delete[] fLastValueData;
  75. if (channels > 0)
  76. {
  77. fChannelsData = new float[channels];
  78. fLastValueData = new float[channels];
  79. for (int i=0; i < channels; ++i)
  80. {
  81. fChannelsData[i] = 0.0f;
  82. fLastValueData[i] = 0.0f;
  83. }
  84. }
  85. else
  86. {
  87. fChannelsData = nullptr;
  88. fLastValueData = nullptr;
  89. }
  90. }
  91. void DigitalPeakMeter::setColor(Color color)
  92. {
  93. if (color == GREEN)
  94. {
  95. fColorBase = QColor(93, 231, 61);
  96. fColorBaseAlt = QColor(15, 110, 15, 100);
  97. }
  98. else if (color == BLUE)
  99. {
  100. fColorBase = QColor(82, 238, 248);
  101. fColorBaseAlt = QColor(15, 15, 110, 100);
  102. }
  103. else
  104. return qCritical("DigitalPeakMeter::setColor(%i) - invalid color", color);
  105. setOrientation(fOrientation);
  106. }
  107. void DigitalPeakMeter::setOrientation(Orientation orientation)
  108. {
  109. fOrientation = orientation;
  110. if (fOrientation == HORIZONTAL)
  111. {
  112. fGradientMeter.setColorAt(0.0f, fColorBase);
  113. fGradientMeter.setColorAt(0.2f, fColorBase);
  114. fGradientMeter.setColorAt(0.4f, fColorBase);
  115. fGradientMeter.setColorAt(0.6f, fColorBase);
  116. fGradientMeter.setColorAt(0.8f, Qt::yellow);
  117. fGradientMeter.setColorAt(1.0f, Qt::red);
  118. }
  119. else if (fOrientation == VERTICAL)
  120. {
  121. fGradientMeter.setColorAt(0.0f, Qt::red);
  122. fGradientMeter.setColorAt(0.2f, Qt::yellow);
  123. fGradientMeter.setColorAt(0.4f, fColorBase);
  124. fGradientMeter.setColorAt(0.6f, fColorBase);
  125. fGradientMeter.setColorAt(0.8f, fColorBase);
  126. fGradientMeter.setColorAt(1.0f, fColorBase);
  127. }
  128. else
  129. return qCritical("DigitalPeakMeter::setOrientation(%i) - invalid orientation", orientation);
  130. updateSizes();
  131. }
  132. void DigitalPeakMeter::setSmoothRelease(int value)
  133. {
  134. Q_ASSERT(value >= 0 && value <= 5);
  135. if (value < 0)
  136. value = 0;
  137. else if (value > 5)
  138. value = 5;
  139. fSmoothMultiplier = value;
  140. }
  141. QSize DigitalPeakMeter::minimumSizeHint() const
  142. {
  143. return QSize(10, 10);
  144. }
  145. QSize DigitalPeakMeter::sizeHint() const
  146. {
  147. return QSize(fWidth, fHeight);
  148. }
  149. void DigitalPeakMeter::updateSizes()
  150. {
  151. fWidth = width();
  152. fHeight = height();
  153. fSizeMeter = 0;
  154. if (fOrientation == HORIZONTAL)
  155. {
  156. fGradientMeter.setFinalStop(fWidth, 0);
  157. if (fChannels > 0)
  158. fSizeMeter = fHeight/fChannels;
  159. }
  160. else if (fOrientation == VERTICAL)
  161. {
  162. fGradientMeter.setFinalStop(0, fHeight);
  163. if (fChannels > 0)
  164. fSizeMeter = fWidth/fChannels;
  165. }
  166. }
  167. void DigitalPeakMeter::paintEvent(QPaintEvent* event)
  168. {
  169. QPainter painter(this);
  170. event->accept();
  171. painter.setPen(Qt::black);
  172. painter.setBrush(Qt::black);
  173. painter.drawRect(0, 0, fWidth, fHeight);
  174. int meterX = 0;
  175. painter.setPen(fColorBackground);
  176. painter.setBrush(fGradientMeter);
  177. for (int i=0; i < fChannels; ++i)
  178. {
  179. float value, level = fChannelsData[i];
  180. if (fOrientation == HORIZONTAL)
  181. value = level * float(fWidth);
  182. else if (fOrientation == VERTICAL)
  183. value = float(fHeight) - (level * float(fHeight));
  184. else
  185. value = 0.0f;
  186. if (fOrientation == HORIZONTAL)
  187. painter.drawRect(0, meterX, int(value), fSizeMeter);
  188. else if (fOrientation == VERTICAL)
  189. painter.drawRect(meterX, int(value), fSizeMeter, fHeight);
  190. meterX += fSizeMeter;
  191. }
  192. painter.setBrush(Qt::black);
  193. if (fOrientation == HORIZONTAL)
  194. {
  195. // Variables
  196. float lsmall = fWidth;
  197. float lfull = fHeight - 1;
  198. // Base
  199. painter.setPen(fColorBaseAlt);
  200. painter.drawLine(lsmall * 0.25f, 2, lsmall * 0.25f, lfull-2.0f);
  201. painter.drawLine(lsmall * 0.50f, 2, lsmall * 0.50f, lfull-2.0f);
  202. // Yellow
  203. painter.setPen(QColor(110, 110, 15, 100));
  204. painter.drawLine(lsmall * 0.70f, 2, lsmall * 0.70f, lfull-2.0f);
  205. painter.drawLine(lsmall * 0.83f, 2, lsmall * 0.83f, lfull-2.0f);
  206. // Orange
  207. painter.setPen(QColor(180, 110, 15, 100));
  208. painter.drawLine(lsmall * 0.90f, 2, lsmall * 0.90f, lfull-2.0f);
  209. // Red
  210. painter.setPen(QColor(110, 15, 15, 100));
  211. painter.drawLine(lsmall * 0.96f, 2, lsmall * 0.96f, lfull-2.0f);
  212. }
  213. else if (fOrientation == VERTICAL)
  214. {
  215. // Variables
  216. float lsmall = fHeight;
  217. float lfull = fWidth - 1;
  218. // Base
  219. painter.setPen(fColorBaseAlt);
  220. painter.drawLine(2, lsmall - (lsmall * 0.25f), lfull-2.0f, lsmall - (lsmall * 0.25f));
  221. painter.drawLine(2, lsmall - (lsmall * 0.50f), lfull-2.0f, lsmall - (lsmall * 0.50f));
  222. // Yellow
  223. painter.setPen(QColor(110, 110, 15, 100));
  224. painter.drawLine(2, lsmall - (lsmall * 0.70f), lfull-2.0f, lsmall - (lsmall * 0.70f));
  225. painter.drawLine(2, lsmall - (lsmall * 0.83f), lfull-2.0f, lsmall - (lsmall * 0.83f));
  226. // Orange
  227. painter.setPen(QColor(180, 110, 15, 100));
  228. painter.drawLine(2, lsmall - (lsmall * 0.90f), lfull-2.0f, lsmall - (lsmall * 0.90f));
  229. // Red
  230. painter.setPen(QColor(110, 15, 15, 100));
  231. painter.drawLine(2, lsmall - (lsmall * 0.96f), lfull-2.0f, lsmall - (lsmall * 0.96f));
  232. }
  233. }
  234. void DigitalPeakMeter::resizeEvent(QResizeEvent* event)
  235. {
  236. updateSizes();
  237. QWidget::resizeEvent(event);
  238. }