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.

319 lines
8.3KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCETICE project - Copyright 2009 by Lucio Asnaghi.
  4. JUCETICE is based around the JUCE library - "Jules' Utility Class Extensions"
  5. Copyright 2007 by Julian Storer.
  6. ------------------------------------------------------------------------------
  7. JUCE and JUCETICE can be redistributed and/or modified under the terms of
  8. the GNU General Public License, as published by the Free Software Foundation;
  9. either version 2 of the License, or (at your option) any later version.
  10. JUCE and JUCETICE are distributed in the hope that they 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. You should have received a copy of the GNU General Public License
  15. along with JUCE and JUCETICE; if not, visit www.gnu.org/licenses or write to
  16. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  17. Boston, MA 02111-1307 USA
  18. ==============================================================================
  19. @author Rui Nuno Capela
  20. @tweaker Lucio Asnaghi
  21. ==============================================================================
  22. */
  23. BEGIN_JUCE_NAMESPACE
  24. //==============================================================================
  25. // Meter level limits (in dB).
  26. #define HQ_METER_MAXDB (+4.0f)
  27. #define HQ_METER_MINDB (-70.0f)
  28. // The decay rates (magic goes here :).
  29. // - value decay rate (faster)
  30. #define HQ_METER_DECAY_RATE1 (1.0f - 3E-2f)
  31. // - peak decay rate (slower)
  32. #define HQ_METER_DECAY_RATE2 (1.0f - 3E-6f)
  33. // Number of cycles the peak stays on hold before fall-off.
  34. #define HQ_METER_PEAK_FALLOFF 16
  35. //==============================================================================
  36. HighQualityMeterValue::HighQualityMeterValue (HighQualityMeter *pMeter)
  37. : m_pMeter (pMeter),
  38. m_fValue (0.0f),
  39. m_iValueHold (0),
  40. m_fValueDecay (HQ_METER_DECAY_RATE1),
  41. m_iPeak (0),
  42. m_iPeakHold (0),
  43. m_fPeakDecay (HQ_METER_DECAY_RATE2),
  44. m_iPeakColor (HighQualityMeter::Color6dB)
  45. {
  46. }
  47. HighQualityMeterValue::~HighQualityMeterValue ()
  48. {
  49. }
  50. void HighQualityMeterValue::setValue (const float fValue)
  51. {
  52. m_fValue = fValue;
  53. }
  54. void HighQualityMeterValue::peakReset ()
  55. {
  56. m_iPeak = 0;
  57. }
  58. void HighQualityMeterValue::refresh ()
  59. {
  60. if (m_fValue > 0.001f || m_iPeak > 0)
  61. repaint();
  62. }
  63. void HighQualityMeterValue::paint (Graphics& g)
  64. {
  65. int w = getWidth();
  66. int h = getHeight();
  67. int y;
  68. if (isEnabled())
  69. {
  70. g.setColour (m_pMeter->color (HighQualityMeter::ColorBack));
  71. g.fillRect (0, 0, w, h);
  72. y = m_pMeter->iec_level (HighQualityMeter::Color0dB);
  73. g.setColour (m_pMeter->color (HighQualityMeter::ColorFore));
  74. g.drawLine (0, h - y, w, h - y);
  75. }
  76. else
  77. {
  78. g.setColour (Colours::black);
  79. g.fillRect (0, 0, w, h);
  80. }
  81. float dB = HQ_METER_MINDB;
  82. if (m_fValue > 0.0f)
  83. dB = 20.0f * log10f (m_fValue);
  84. if (dB < HQ_METER_MINDB)
  85. dB = HQ_METER_MINDB;
  86. else if (dB > HQ_METER_MAXDB)
  87. dB = HQ_METER_MAXDB;
  88. int y_over = 0;
  89. int y_curr = 0;
  90. y = m_pMeter->iec_scale (dB);
  91. if (m_iValueHold < y)
  92. {
  93. m_iValueHold = y;
  94. m_fValueDecay = HQ_METER_DECAY_RATE1;
  95. }
  96. else
  97. {
  98. m_iValueHold = int (float (m_iValueHold * m_fValueDecay));
  99. if (m_iValueHold < y)
  100. m_iValueHold = y;
  101. else {
  102. m_fValueDecay *= m_fValueDecay;
  103. y = m_iValueHold;
  104. }
  105. }
  106. int iLevel;
  107. for (iLevel = HighQualityMeter::Color10dB;
  108. iLevel > HighQualityMeter::ColorOver && y >= y_over; iLevel--)
  109. {
  110. y_curr = m_pMeter->iec_level (iLevel);
  111. // g.setColour (m_pMeter->color (iLevel));
  112. g.setGradientFill (ColourGradient (m_pMeter->color (iLevel), 0, h - y_over,
  113. m_pMeter->color (iLevel-1), 0, h - y_curr,
  114. false));
  115. if (y < y_curr)
  116. g.fillRect(0, h - y, w, y - y_over);
  117. else
  118. g.fillRect(0, h - y_curr, w, y_curr - y_over);
  119. y_over = y_curr;
  120. }
  121. if (y > y_over)
  122. {
  123. g.setColour (m_pMeter->color (HighQualityMeter::ColorOver));
  124. g.fillRect (0, h - y, w, y - y_over);
  125. }
  126. if (m_iPeak < y)
  127. {
  128. m_iPeak = y;
  129. m_iPeakHold = 0;
  130. m_fPeakDecay = HQ_METER_DECAY_RATE2;
  131. m_iPeakColor = iLevel;
  132. }
  133. else if (++m_iPeakHold > m_pMeter->getPeakFalloff())
  134. {
  135. m_iPeak = int (float (m_iPeak * m_fPeakDecay));
  136. if (m_iPeak < y) {
  137. m_iPeak = y;
  138. } else {
  139. if (m_iPeak < m_pMeter->iec_level (HighQualityMeter::Color10dB))
  140. m_iPeakColor = HighQualityMeter::Color6dB;
  141. m_fPeakDecay *= m_fPeakDecay;
  142. }
  143. }
  144. g.setColour (m_pMeter->color (m_iPeakColor));
  145. g.drawLine (0, h - m_iPeak, w, h - m_iPeak);
  146. }
  147. void HighQualityMeterValue::resized ()
  148. {
  149. m_iPeak = 0;
  150. }
  151. //==============================================================================
  152. HighQualityMeter::HighQualityMeter (const int numPorts)
  153. : m_iPortCount (numPorts), // FIXME: Default port count.
  154. m_ppValues (0),
  155. m_fScale (0.0f),
  156. m_iPeakFalloff (HQ_METER_PEAK_FALLOFF)
  157. {
  158. for (int i = 0; i < LevelCount; i++)
  159. m_levels[i] = 0;
  160. m_colors[ColorOver] = findColour (levelOverColourId);
  161. m_colors[Color0dB] = findColour (level0dBColourId);
  162. m_colors[Color3dB] = findColour (level3dBColourId);
  163. m_colors[Color6dB] = findColour (level6dBColourId);
  164. m_colors[Color10dB] = findColour (level10dBColourId);
  165. m_colors[ColorBack] = findColour (backgroundColourId);
  166. m_colors[ColorFore] = findColour (foregroundColourId);
  167. if (m_iPortCount > 0)
  168. {
  169. m_ppValues = new HighQualityMeterValue* [m_iPortCount];
  170. for (int iPort = 0; iPort < m_iPortCount; iPort++)
  171. {
  172. m_ppValues[iPort] = new HighQualityMeterValue (this);
  173. addAndMakeVisible (m_ppValues[iPort]);
  174. }
  175. }
  176. }
  177. // Default destructor.
  178. HighQualityMeter::~HighQualityMeter (void)
  179. {
  180. for (int iPort = 0; iPort < m_iPortCount; iPort++)
  181. delete m_ppValues[iPort];
  182. delete [] m_ppValues;
  183. }
  184. void HighQualityMeter::resized ()
  185. {
  186. m_fScale = 0.85f * getHeight();
  187. m_levels[Color0dB] = iec_scale ( 0.0f);
  188. m_levels[Color3dB] = iec_scale ( -3.0f);
  189. m_levels[Color6dB] = iec_scale ( -6.0f);
  190. m_levels[Color10dB] = iec_scale (-10.0f);
  191. int size = getWidth () / m_iPortCount;
  192. for (int iPort = 0; iPort < m_iPortCount; iPort++)
  193. {
  194. m_ppValues[iPort]->setBounds (iPort * size, 0, size, getHeight ());
  195. }
  196. }
  197. void HighQualityMeter::paint (Graphics& g)
  198. {
  199. LookAndFeel_V2::drawBevel (g,
  200. 0, 0, getWidth(), getHeight(), 1,
  201. Colours::black.withAlpha(0.2f),
  202. Colours::white.withAlpha(0.2f));
  203. }
  204. // Child widget accessors.
  205. int HighQualityMeter::iec_scale (const float dB) const
  206. {
  207. float fDef = 1.0;
  208. if (dB < -70.0)
  209. fDef = 0.0;
  210. else if (dB < -60.0)
  211. fDef = (dB + 70.0) * 0.0025;
  212. else if (dB < -50.0)
  213. fDef = (dB + 60.0) * 0.005 + 0.025;
  214. else if (dB < -40.0)
  215. fDef = (dB + 50.0) * 0.0075 + 0.075;
  216. else if (dB < -30.0)
  217. fDef = (dB + 40.0) * 0.015 + 0.15;
  218. else if (dB < -20.0)
  219. fDef = (dB + 30.0) * 0.02 + 0.3;
  220. else // if (dB < 0.0)
  221. fDef = (dB + 20.0) * 0.025 + 0.5;
  222. return (int) (fDef * m_fScale);
  223. }
  224. int HighQualityMeter::iec_level (const int index) const
  225. {
  226. return m_levels[index];
  227. }
  228. int HighQualityMeter::portCount () const
  229. {
  230. return m_iPortCount;
  231. }
  232. void HighQualityMeter::setPeakFalloff (const int iPeakFalloff)
  233. {
  234. m_iPeakFalloff = iPeakFalloff;
  235. }
  236. int HighQualityMeter::getPeakFalloff () const
  237. {
  238. return m_iPeakFalloff;
  239. }
  240. void HighQualityMeter::peakReset ()
  241. {
  242. for (int iPort = 0; iPort < m_iPortCount; iPort++)
  243. m_ppValues[iPort]->peakReset();
  244. }
  245. void HighQualityMeter::refresh ()
  246. {
  247. for (int iPort = 0; iPort < m_iPortCount; iPort++)
  248. m_ppValues[iPort]->refresh();
  249. }
  250. void HighQualityMeter::setValue (const int iPort, const float fValue)
  251. {
  252. m_ppValues[iPort]->setValue(fValue);
  253. }
  254. const Colour& HighQualityMeter::color (const int index) const
  255. {
  256. return m_colors[index];
  257. }
  258. END_JUCE_NAMESPACE