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.

301 lines
8.1KB

  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 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. fPaintTimer(this)
  35. {
  36. setChannels(0);
  37. setColor(GREEN);
  38. fPaintTimer.setInterval(60);
  39. connect(&fPaintTimer, SIGNAL(timeout()), this, SLOT(update()));
  40. fPaintTimer.start();
  41. }
  42. DigitalPeakMeter::~DigitalPeakMeter()
  43. {
  44. if (fChannelsData != nullptr)
  45. delete[] fChannelsData;
  46. if (fLastValueData != nullptr)
  47. delete[] fLastValueData;
  48. }
  49. void DigitalPeakMeter::displayMeter(int meter, float level)
  50. {
  51. Q_ASSERT(fChannelsData != nullptr);
  52. Q_ASSERT(meter > 0 && meter <= fChannels);
  53. if (meter <= 0 || meter > fChannels || fChannelsData == nullptr)
  54. return qCritical("DigitalPeakMeter::displayMeter(%i, %f) - invalid meter number", meter, level);
  55. if (level < 0.0f)
  56. level = -level;
  57. else if (level > 1.0f)
  58. level = 1.0f;
  59. fChannelsData[meter-1] = level;
  60. }
  61. void DigitalPeakMeter::setChannels(int channels)
  62. {
  63. Q_ASSERT(channels >= 0);
  64. if (channels < 0)
  65. return qCritical("DigitalPeakMeter::setChannels(%i) - 'channels' must be a positive integer", channels);
  66. fChannels = channels;
  67. if (fChannelsData != nullptr)
  68. delete[] fChannelsData;
  69. if (fLastValueData != nullptr)
  70. delete[] fLastValueData;
  71. if (channels > 0)
  72. {
  73. fChannelsData = new float[channels];
  74. fLastValueData = new float[channels];
  75. for (int i=0; i < channels; ++i)
  76. {
  77. fChannelsData[i] = 0.0f;
  78. fLastValueData[i] = 0.0f;
  79. }
  80. }
  81. else
  82. {
  83. fChannelsData = nullptr;
  84. fLastValueData = nullptr;
  85. }
  86. }
  87. void DigitalPeakMeter::setColor(Color color)
  88. {
  89. if (color == GREEN)
  90. {
  91. fColorBase = QColor(93, 231, 61);
  92. fColorBaseAlt = QColor(15, 110, 15, 100);
  93. }
  94. else if (color == BLUE)
  95. {
  96. fColorBase = QColor(82, 238, 248);
  97. fColorBaseAlt = QColor(15, 15, 110, 100);
  98. }
  99. else
  100. return qCritical("DigitalPeakMeter::setColor(%i) - invalid color", color);
  101. setOrientation(fOrientation);
  102. }
  103. void DigitalPeakMeter::setOrientation(Orientation orientation)
  104. {
  105. fOrientation = orientation;
  106. if (fOrientation == HORIZONTAL)
  107. {
  108. fGradientMeter.setColorAt(0.0f, fColorBase);
  109. fGradientMeter.setColorAt(0.2f, fColorBase);
  110. fGradientMeter.setColorAt(0.4f, fColorBase);
  111. fGradientMeter.setColorAt(0.6f, fColorBase);
  112. fGradientMeter.setColorAt(0.8f, Qt::yellow);
  113. fGradientMeter.setColorAt(1.0f, Qt::red);
  114. }
  115. else if (fOrientation == VERTICAL)
  116. {
  117. fGradientMeter.setColorAt(0.0f, Qt::red);
  118. fGradientMeter.setColorAt(0.2f, Qt::yellow);
  119. fGradientMeter.setColorAt(0.4f, fColorBase);
  120. fGradientMeter.setColorAt(0.6f, fColorBase);
  121. fGradientMeter.setColorAt(0.8f, fColorBase);
  122. fGradientMeter.setColorAt(1.0f, fColorBase);
  123. }
  124. else
  125. return qCritical("DigitalPeakMeter::setOrientation(%i) - invalid orientation", orientation);
  126. updateSizes();
  127. }
  128. void DigitalPeakMeter::setRefreshRate(int rate)
  129. {
  130. Q_ASSERT(rate > 0);
  131. fPaintTimer.stop();
  132. fPaintTimer.setInterval(rate);
  133. fPaintTimer.start();
  134. }
  135. void DigitalPeakMeter::setSmoothRelease(int value)
  136. {
  137. Q_ASSERT(value >= 0 && value <= 5);
  138. if (value < 0)
  139. value = 0;
  140. else if (value > 5)
  141. value = 5;
  142. fSmoothMultiplier = value;
  143. }
  144. QSize DigitalPeakMeter::minimumSizeHint() const
  145. {
  146. return QSize(30, 30);
  147. }
  148. QSize DigitalPeakMeter::sizeHint() const
  149. {
  150. return QSize(fWidth, fHeight);
  151. }
  152. void DigitalPeakMeter::updateSizes()
  153. {
  154. fWidth = width();
  155. fHeight = height();
  156. fSizeMeter = 0;
  157. if (fOrientation == HORIZONTAL)
  158. {
  159. fGradientMeter.setFinalStop(fWidth, 0);
  160. if (fChannels > 0)
  161. fSizeMeter = fHeight/fChannels;
  162. }
  163. else if (fOrientation == VERTICAL)
  164. {
  165. fGradientMeter.setFinalStop(0, fHeight);
  166. if (fChannels > 0)
  167. fSizeMeter = fWidth/fChannels;
  168. }
  169. }
  170. void DigitalPeakMeter::paintEvent(QPaintEvent* event)
  171. {
  172. QPainter painter(this);
  173. event->accept();
  174. painter.setPen(Qt::black);
  175. painter.setBrush(Qt::black);
  176. painter.drawRect(0, 0, fWidth, fHeight);
  177. int meterX = 0;
  178. painter.setPen(fColorBackground);
  179. painter.setBrush(fGradientMeter);
  180. for (int i=0; i < fChannels; ++i)
  181. {
  182. float value, level = fChannelsData[i];
  183. if (level == fLastValueData[i])
  184. continue;
  185. if (fOrientation == HORIZONTAL)
  186. value = level * float(fWidth);
  187. else if (fOrientation == VERTICAL)
  188. value = float(fHeight) - (level * float(fHeight));
  189. else
  190. value = 0.0f;
  191. if (value < 0.0f)
  192. value = 0.0f;
  193. else if (fSmoothMultiplier > 0)
  194. value = (fLastValueData[i] * float(fSmoothMultiplier) + value) / float(fSmoothMultiplier + 1);
  195. if (fOrientation == HORIZONTAL)
  196. painter.drawRect(0, meterX, int(value), fSizeMeter);
  197. else if (fOrientation == VERTICAL)
  198. painter.drawRect(meterX, int(value), fSizeMeter, fHeight);
  199. meterX += fSizeMeter;
  200. fLastValueData[i] = value;
  201. }
  202. painter.setBrush(Qt::black);
  203. if (fOrientation == HORIZONTAL)
  204. {
  205. // Variables
  206. float lsmall = fWidth;
  207. float lfull = fHeight - 1;
  208. // Base
  209. painter.setPen(fColorBaseAlt);
  210. painter.drawLine(lsmall * 0.25f, 2, lsmall * 0.25f, lfull-2.0f);
  211. painter.drawLine(lsmall * 0.50f, 2, lsmall * 0.50f, lfull-2.0f);
  212. // Yellow
  213. painter.setPen(QColor(110, 110, 15, 100));
  214. painter.drawLine(lsmall * 0.70f, 2, lsmall * 0.70f, lfull-2.0f);
  215. painter.drawLine(lsmall * 0.83f, 2, lsmall * 0.83f, lfull-2.0f);
  216. // Orange
  217. painter.setPen(QColor(180, 110, 15, 100));
  218. painter.drawLine(lsmall * 0.90f, 2, lsmall * 0.90f, lfull-2.0f);
  219. // Red
  220. painter.setPen(QColor(110, 15, 15, 100));
  221. painter.drawLine(lsmall * 0.96f, 2, lsmall * 0.96f, lfull-2.0f);
  222. }
  223. else if (fOrientation == VERTICAL)
  224. {
  225. // Variables
  226. float lsmall = fHeight;
  227. float lfull = fWidth - 1;
  228. // Base
  229. painter.setPen(fColorBaseAlt);
  230. painter.drawLine(2, lsmall - (lsmall * 0.25f), lfull-2.0f, lsmall - (lsmall * 0.25f));
  231. painter.drawLine(2, lsmall - (lsmall * 0.50f), lfull-2.0f, lsmall - (lsmall * 0.50f));
  232. // Yellow
  233. painter.setPen(QColor(110, 110, 15, 100));
  234. painter.drawLine(2, lsmall - (lsmall * 0.70f), lfull-2.0f, lsmall - (lsmall * 0.70f));
  235. painter.drawLine(2, lsmall - (lsmall * 0.83f), lfull-2.0f, lsmall - (lsmall * 0.83f));
  236. // Orange
  237. painter.setPen(QColor(180, 110, 15, 100));
  238. painter.drawLine(2, lsmall - (lsmall * 0.90f), lfull-2.0f, lsmall - (lsmall * 0.90f));
  239. // Red
  240. painter.setPen(QColor(110, 15, 15, 100));
  241. painter.drawLine(2, lsmall - (lsmall * 0.96f), lfull-2.0f, lsmall - (lsmall * 0.96f));
  242. }
  243. }
  244. void DigitalPeakMeter::resizeEvent(QResizeEvent* event)
  245. {
  246. updateSizes();
  247. QWidget::resizeEvent(event);
  248. }