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.

548 lines
24KB

  1. /*
  2. ===============================================================================
  3. LUFSMeterAudioProcessorEditor.cpp
  4. This file is part of the LUFS Meter audio measurement plugin.
  5. Copyright 2011-12 by Klangfreund, Samuel Gaehwiler.
  6. -------------------------------------------------------------------------------
  7. The LUFS Meter can be redistributed and/or modified under the terms of the GNU
  8. General Public License Version 2, as published by the Free Software Foundation.
  9. A copy of the license is included with these source files. It can also be found
  10. at www.gnu.org/licenses.
  11. The LUFS Meter is distributed WITHOUT ANY WARRANTY.
  12. See the GNU General Public License for more details.
  13. -------------------------------------------------------------------------------
  14. To release a closed-source product which uses the LUFS Meter or parts of it,
  15. a commercial license is available. Visit www.klangfreund.com/lufsmeter for more
  16. information.
  17. ===============================================================================
  18. */
  19. #include "LUFSMeterAudioProcessor.h"
  20. #include "LUFSMeterAudioProcessorEditor.h"
  21. //==============================================================================
  22. LUFSMeterAudioProcessorEditor::LUFSMeterAudioProcessorEditor (LUFSMeterAudioProcessor* ownerFilter)
  23. : AudioProcessorEditor (ownerFilter),
  24. momentaryLoudnessValue (var(-300.0)),
  25. shortTermLoudnessValue (var(-300.0)),
  26. loudnessRangeStartValue (var(-300.0)),
  27. loudnessRangeEndValue (var(-300.0)),
  28. loudnessRangeValue(var(0.0)),
  29. integratedLoudnessValue (var(-300.0)),
  30. distanceBetweenLoudnessBarAndTop (10),
  31. distanceBetweenLoudnessBarAndBottom (32),
  32. backgroundGridCaption (distanceBetweenLoudnessBarAndTop,
  33. distanceBetweenLoudnessBarAndBottom,
  34. getProcessor()->loudnessBarMinValue,
  35. getProcessor()->loudnessBarMaxValue),
  36. momentaryLoudnessBar (getProcessor()->loudnessBarMinValue,
  37. getProcessor()->loudnessBarMaxValue),
  38. momentaryLoudnessBarSum (momentaryLoudnessValue,
  39. getProcessor()->loudnessBarMinValue,
  40. getProcessor()->loudnessBarMaxValue),
  41. shortTermLoudnessBar (shortTermLoudnessValue,
  42. getProcessor()->loudnessBarMinValue,
  43. getProcessor()->loudnessBarMaxValue),
  44. loudnessRangeBar (loudnessRangeStartValue,
  45. loudnessRangeEndValue,
  46. getProcessor()->loudnessBarMinValue,
  47. getProcessor()->loudnessBarMaxValue),
  48. integratedLoudnessBar (integratedLoudnessValue,
  49. getProcessor()->loudnessBarMinValue,
  50. getProcessor()->loudnessBarMaxValue),
  51. momentaryLoudnessCaption (String(), "M"),
  52. shortTermLoudnessCaption (String(), "S"),
  53. loudnessRangeCaption (String(), "LRA"),
  54. integratedLoudnessCaption (String(), "I"),
  55. momentaryLoudnessHistory (momentaryLoudnessValue, getProcessor()->loudnessBarMinValue, getProcessor()->loudnessBarMaxValue),
  56. shortTermLoudnessHistory (shortTermLoudnessValue, getProcessor()->loudnessBarMinValue, getProcessor()->loudnessBarMaxValue),
  57. loudnessRangeHistory (loudnessRangeStartValue, loudnessRangeEndValue, getProcessor()->loudnessBarMinValue, getProcessor()->loudnessBarMaxValue),
  58. integratedLoudnessHistory (integratedLoudnessValue, getProcessor()->loudnessBarMinValue, getProcessor()->loudnessBarMaxValue),
  59. preferencesPane(getProcessor()->loudnessBarWidth,
  60. getProcessor()->loudnessBarMinValue,
  61. getProcessor()->loudnessBarMaxValue,
  62. getProcessor()->showIntegratedLoudnessHistory,
  63. getProcessor()->showLoudnessRangeHistory,
  64. getProcessor()->showShortTermLoudnessHistory,
  65. getProcessor()->showMomentaryLoudnessHistory)
  66. {
  67. LookAndFeel::setDefaultLookAndFeel(&lookAndFeelV3);
  68. // Add the background
  69. addAndMakeVisible (&backgroundGrid);
  70. addAndMakeVisible (&backgroundGridCaption);
  71. addAndMakeVisible(&backgroundVerticalLinesAndCaption);
  72. // TEMP:
  73. // Add a label that will display the current timecode and status..
  74. // addAndMakeVisible (&infoLabel);
  75. // infoLabel.setColour (Label::textColourId, Colours::green);
  76. Colour momentaryLoudnessColour = Colours::darkgreen;
  77. Colour momentaryLoudnessSumColour = Colours::darkgreen.darker().darker();
  78. Colour loudnessRangeColour = Colours::blue.darker();
  79. Colour loudnessRangeColourTransparent = loudnessRangeColour.withAlpha(0.3f);
  80. Colour integratedLoudnessColour = Colours::yellow.darker().darker();
  81. // Add the meter bars
  82. momentaryLoudnessBarSum.setColour (momentaryLoudnessSumColour);
  83. addAndMakeVisible(&momentaryLoudnessBarSum);
  84. momentaryLoudnessBar.setColour (momentaryLoudnessColour);
  85. addAndMakeVisible (&momentaryLoudnessBar);
  86. addAndMakeVisible (&shortTermLoudnessBar);
  87. loudnessRangeBar.setColour (loudnessRangeColourTransparent);
  88. addAndMakeVisible (&loudnessRangeBar);
  89. integratedLoudnessBar.setColour (integratedLoudnessColour);
  90. addAndMakeVisible (&integratedLoudnessBar);
  91. // Add the numeric values
  92. momentaryLoudnessNumeric.setColour(momentaryLoudnessColour);
  93. addAndMakeVisible (&momentaryLoudnessNumeric);
  94. momentaryLoudnessNumeric.getLoudnessValueObject().referTo(momentaryLoudnessValue);
  95. addAndMakeVisible (&shortTermLoudnessNumeric);
  96. shortTermLoudnessNumeric.getLoudnessValueObject().referTo(shortTermLoudnessValue);
  97. loudnessRangeNumeric.setColour(loudnessRangeColour);
  98. addAndMakeVisible (&loudnessRangeNumeric);
  99. loudnessRangeNumeric.getLoudnessValueObject().referTo(loudnessRangeValue);
  100. integratedLoudnessNumeric.setColour(integratedLoudnessColour);
  101. addAndMakeVisible (&integratedLoudnessNumeric);
  102. integratedLoudnessNumeric.getLoudnessValueObject().referTo(integratedLoudnessValue);
  103. // Add the captions
  104. const int fontHeight = 16;
  105. const Font fontForCaptions (fontHeight);
  106. const Justification justification (Justification::horizontallyCentred);
  107. momentaryLoudnessCaption.setFont(fontForCaptions);
  108. momentaryLoudnessCaption.setColour (Label::textColourId, momentaryLoudnessColour);
  109. // momentaryLoudnessCaption.setColour (Label::backgroundColourId, Colours::red);
  110. momentaryLoudnessCaption.setJustificationType(justification);
  111. addAndMakeVisible (&momentaryLoudnessCaption);
  112. shortTermLoudnessCaption.setFont(fontForCaptions);
  113. shortTermLoudnessCaption.setColour (Label::textColourId, Colours::green);
  114. shortTermLoudnessCaption.setJustificationType(justification);
  115. addAndMakeVisible (&shortTermLoudnessCaption);
  116. loudnessRangeCaption.setFont(fontForCaptions);
  117. loudnessRangeCaption.setColour (Label::textColourId, loudnessRangeColour);
  118. loudnessRangeCaption.setJustificationType(justification);
  119. addAndMakeVisible (&loudnessRangeCaption);
  120. integratedLoudnessCaption.setFont(fontForCaptions);
  121. integratedLoudnessCaption.setColour (Label::textColourId, integratedLoudnessColour);
  122. integratedLoudnessCaption.setJustificationType(justification);
  123. addAndMakeVisible (&integratedLoudnessCaption);
  124. // Add the loudness history graphs
  125. addAndMakeVisible(&loudnessHistoryGroup);
  126. loudnessRangeHistory.setColour (loudnessRangeColourTransparent);
  127. loudnessRangeHistory.setVisible (bool(getProcessor()->showLoudnessRangeHistory.getValue()));
  128. loudnessHistoryGroup.addChildComponent(&loudnessRangeHistory);
  129. momentaryLoudnessHistory.setColour(momentaryLoudnessSumColour);
  130. momentaryLoudnessHistory.setVisible (bool(getProcessor()->showMomentaryLoudnessHistory.getValue()));
  131. loudnessHistoryGroup.addChildComponent(&momentaryLoudnessHistory);
  132. shortTermLoudnessHistory.setVisible (bool(getProcessor()->showShortTermLoudnessHistory.getValue()));
  133. loudnessHistoryGroup.addChildComponent(&shortTermLoudnessHistory);
  134. integratedLoudnessHistory.setColour (integratedLoudnessColour);
  135. integratedLoudnessHistory.setVisible (bool(getProcessor()->showIntegratedLoudnessHistory.getValue()));
  136. loudnessHistoryGroup.addChildComponent(&integratedLoudnessHistory);
  137. // Add the reset button
  138. resetButton.addListener(this);
  139. resetButton.setButtonText("reset");
  140. resetButton.setColour(TextButton::buttonColourId, Colours::darkred);
  141. resetButton.setColour(TextButton::textColourOffId, Colours::lightgrey);
  142. addAndMakeVisible (&resetButton);
  143. // Add the preferences pane
  144. addAndMakeVisible (&preferencesPane);
  145. preferencesPane.setTopLeftPosition(- preferencesPane.getWidthWithoutHandle(), 50);
  146. // Add the triangular resizer component for the bottom-right of the UI.
  147. addAndMakeVisible (resizer = new ResizableCornerComponent (this, &resizeLimits));
  148. resizeLimits.setMinimumSize(150, 150);
  149. // Set our component's initial size to be the last one that was stored in
  150. // the filter's settings.
  151. setSize (ownerFilter->lastUIWidth,
  152. ownerFilter->lastUIHeight);
  153. // Listen to some Values
  154. getProcessor()->loudnessBarWidth.addListener (this);
  155. getProcessor()->showIntegratedLoudnessHistory.addListener (this);
  156. getProcessor()->showLoudnessRangeHistory.addListener (this);
  157. getProcessor()->showShortTermLoudnessHistory.addListener (this);
  158. getProcessor()->showMomentaryLoudnessHistory.addListener (this);
  159. getProcessor()->numberOfInputChannels.addListener (this);
  160. momentaryLoudnessHistory.reset();
  161. shortTermLoudnessHistory.reset();
  162. loudnessRangeHistory.reset();
  163. integratedLoudnessHistory.reset();
  164. // Start the timer which will refresh the GUI elements.
  165. const int refreshIntervalInMilliseconds = 50;
  166. startTimer (refreshIntervalInMilliseconds);
  167. }
  168. LUFSMeterAudioProcessorEditor::~LUFSMeterAudioProcessorEditor()
  169. {
  170. if (getProcessor())
  171. {
  172. getProcessor()->loudnessBarWidth.removeListener (this);
  173. getProcessor()->showIntegratedLoudnessHistory.removeListener (this);
  174. getProcessor()->showLoudnessRangeHistory.removeListener (this);
  175. getProcessor()->showShortTermLoudnessHistory.removeListener (this);
  176. getProcessor()->showMomentaryLoudnessHistory.removeListener (this);
  177. }
  178. }
  179. //==============================================================================
  180. void LUFSMeterAudioProcessorEditor::paint (Graphics& g)
  181. {
  182. // Draw the background
  183. g.fillAll(Colours::black);
  184. }
  185. void LUFSMeterAudioProcessorEditor::resized()
  186. {
  187. // DEB("Height of main component = " + String(getHeight()))
  188. resizeGuiComponents();
  189. // Some more fix sized components:
  190. // TEMP
  191. //infoLabel.setBounds (10, 4, 380, 25);
  192. // resetButton.setBounds(10, getHeight()-35, 80, 25);
  193. resetButton.setBounds(12, 12, 50, 25);
  194. resizer->setBounds (getWidth() - 16, getHeight() - 16, 16, 16);
  195. getProcessor()->lastUIWidth = getWidth();
  196. getProcessor()->lastUIHeight = getHeight();
  197. }
  198. // This timer periodically updates the labels.
  199. void LUFSMeterAudioProcessorEditor::timerCallback()
  200. {
  201. // AudioPlayHead::CurrentPositionInfo newPos (getProcessor()->lastPosInfo);
  202. //
  203. // if (lastDisplayedPosition != newPos)
  204. // displayPositionInfo (newPos);
  205. // momentary loudness values
  206. // -------------------------
  207. momentaryLoudnessValue.setValue (getProcessor()->getMomentaryLoudness());
  208. momentaryLoudnessBar.setLoudness (getProcessor()->getMomentaryLoudnessForIndividualChannels());
  209. /*
  210. // source:
  211. const Array<float>& momentaryLoudnessFromEbu128LM = getProcessor()->getMomentaryLoudnessForIndividualChannels();
  212. // destination:
  213. Array<var> momentaryLoudness;
  214. for (int k = 0; k != momentaryLoudnessFromEbu128LM.size() ; ++k)
  215. {
  216. double momentaryLoudnessOfTheKthChannel = double (momentaryLoudnessFromEbu128LM[k]);
  217. momentaryLoudness.add (momentaryLoudnessOfTheKthChannel);
  218. }
  219. */
  220. // short loudness values
  221. // ---------------------
  222. float shortTermLoudness = getProcessor()->getShortTermLoudness();
  223. jassert(shortTermLoudness > -400);
  224. shortTermLoudnessValue.setValue(shortTermLoudness);
  225. // loudness range values
  226. // ---------------------
  227. float loudnessRange = getProcessor()->getLoudnessRange();
  228. jassert(loudnessRange > -400);
  229. loudnessRangeValue.setValue(loudnessRange);
  230. float loudnessRangeStart = getProcessor()->getLoudnessRangeStart();
  231. jassert (loudnessRangeStart > -400);
  232. loudnessRangeStartValue.setValue(loudnessRangeStart);
  233. float loudnessRangeEnd = getProcessor()->getLoudnessRangeEnd();
  234. jassert (loudnessRangeEnd > -400);
  235. loudnessRangeEndValue.setValue(loudnessRangeEnd);
  236. // integrated loudness values
  237. // --------------------------
  238. float integratedLoudness = getProcessor()->getIntegratedLoudness();
  239. jassert(integratedLoudness > -400);
  240. integratedLoudnessValue.setValue(integratedLoudness);
  241. }
  242. void LUFSMeterAudioProcessorEditor::buttonClicked(Button* button)
  243. {
  244. if (button == &resetButton)
  245. {
  246. getProcessor()->ebu128LoudnessMeter.reset();
  247. momentaryLoudnessHistory.reset();
  248. shortTermLoudnessHistory.reset();
  249. loudnessRangeHistory.reset();
  250. integratedLoudnessHistory.reset();
  251. }
  252. }
  253. void LUFSMeterAudioProcessorEditor::valueChanged (Value & value)
  254. {
  255. if (value.refersToSameSourceAs (getProcessor()->loudnessBarWidth) ||
  256. value.refersToSameSourceAs (getProcessor()->numberOfInputChannels))
  257. // Because the width of the of the MultiChannelLoudnessBar needs to be a multiple
  258. // of the numberOfInputChannels.
  259. {
  260. resizeGuiComponents();
  261. }
  262. else if (value.refersToSameSourceAs (getProcessor()->showIntegratedLoudnessHistory))
  263. {
  264. integratedLoudnessHistory.setVisible (bool(getProcessor()->showIntegratedLoudnessHistory.getValue()));
  265. }
  266. else if (value.refersToSameSourceAs (getProcessor()->showLoudnessRangeHistory))
  267. {
  268. loudnessRangeHistory.setVisible (bool(getProcessor()->showLoudnessRangeHistory.getValue()));
  269. }
  270. else if (value.refersToSameSourceAs (getProcessor()->showShortTermLoudnessHistory))
  271. {
  272. shortTermLoudnessHistory.setVisible (bool(getProcessor()->showShortTermLoudnessHistory.getValue()));
  273. }
  274. else if (value.refersToSameSourceAs (getProcessor()->showMomentaryLoudnessHistory))
  275. {
  276. momentaryLoudnessHistory.setVisible (bool(getProcessor()->showMomentaryLoudnessHistory.getValue()));
  277. }
  278. }
  279. LUFSMeterAudioProcessor* LUFSMeterAudioProcessorEditor::getProcessor() const
  280. {
  281. return static_cast <LUFSMeterAudioProcessor*> (getAudioProcessor());
  282. }
  283. void LUFSMeterAudioProcessorEditor::resizeGuiComponents ()
  284. {
  285. // Distances
  286. // ---------
  287. const int loudnessBarWidth = int(getProcessor()->loudnessBarWidth.getValue()) * -1;
  288. // Ensure that the momentaryLoudnessBarWidth % numberOfChannels = 0.
  289. int momentaryLoudnessBarWidth = loudnessBarWidth;
  290. // Determine widthOfIndividualChannel.
  291. const int numberOfChannels = getProcessor()->getMomentaryLoudnessForIndividualChannels().size();
  292. if (numberOfChannels != 0)
  293. {
  294. const int widthOfIndividualChannel = loudnessBarWidth / numberOfChannels;
  295. // Integer division.
  296. momentaryLoudnessBarWidth = numberOfChannels * widthOfIndividualChannel;
  297. }
  298. const int spaceBetweenBars = jmin (loudnessBarWidth/5, 10);
  299. // This distance is also used for the border on the right side.
  300. const int heightOfNumericValues = loudnessBarWidth/3;
  301. const int heightOfLoudnessCaptions = heightOfNumericValues;
  302. distanceBetweenLoudnessBarAndBottom = heightOfNumericValues
  303. + heightOfLoudnessCaptions;
  304. const int loudnessBarBottomPosition = getHeight()
  305. - distanceBetweenLoudnessBarAndBottom;
  306. const int heightOfLoudnessBar = loudnessBarBottomPosition
  307. - distanceBetweenLoudnessBarAndTop;
  308. const int loudnessBarNumericTopPosition = getHeight()
  309. - distanceBetweenLoudnessBarAndBottom;
  310. const int loudnessBarCaptionTopPosition = getHeight()
  311. - heightOfLoudnessCaptions;
  312. const int backgroundGridCaptionWidth = 35;
  313. // Background Grid
  314. backgroundGrid.setBounds(0,
  315. distanceBetweenLoudnessBarAndTop,
  316. getWidth(),
  317. heightOfLoudnessBar);
  318. // Font for the loudnessCaptions
  319. const int fontHeight = heightOfLoudnessCaptions;
  320. const Font fontForCaptions (fontHeight);
  321. // Momentary Loudness
  322. const int momentaryLoudnessBarX = getWidth() - spaceBetweenBars
  323. - momentaryLoudnessBarWidth;
  324. momentaryLoudnessBarSum.setBounds(momentaryLoudnessBarX,
  325. distanceBetweenLoudnessBarAndTop,
  326. momentaryLoudnessBarWidth,
  327. heightOfLoudnessBar);
  328. momentaryLoudnessBar.setBounds(momentaryLoudnessBarX,
  329. distanceBetweenLoudnessBarAndTop,
  330. momentaryLoudnessBarWidth,
  331. heightOfLoudnessBar);
  332. momentaryLoudnessNumeric.setBounds (momentaryLoudnessBarX,
  333. loudnessBarNumericTopPosition,
  334. momentaryLoudnessBarWidth,
  335. heightOfNumericValues);
  336. momentaryLoudnessCaption.setBounds(momentaryLoudnessBarX,
  337. loudnessBarCaptionTopPosition,
  338. momentaryLoudnessBarWidth,
  339. heightOfLoudnessCaptions);
  340. momentaryLoudnessCaption.setFont(fontForCaptions);
  341. // Short Term Loudness
  342. const int shortTermLoudnessBarX = momentaryLoudnessBarX - spaceBetweenBars - loudnessBarWidth;
  343. shortTermLoudnessBar.setBounds(shortTermLoudnessBarX,
  344. distanceBetweenLoudnessBarAndTop,
  345. loudnessBarWidth,
  346. heightOfLoudnessBar);
  347. shortTermLoudnessNumeric.setBounds (shortTermLoudnessBarX,
  348. loudnessBarNumericTopPosition,
  349. loudnessBarWidth,
  350. heightOfNumericValues);
  351. shortTermLoudnessCaption.setBounds(shortTermLoudnessBarX,
  352. loudnessBarCaptionTopPosition,
  353. loudnessBarWidth,
  354. heightOfLoudnessCaptions);
  355. shortTermLoudnessCaption.setFont(fontForCaptions);
  356. // Loudness Range
  357. const int loudnessRangeBarX = shortTermLoudnessBarX - spaceBetweenBars - loudnessBarWidth;
  358. loudnessRangeBar.setBounds (loudnessRangeBarX,
  359. distanceBetweenLoudnessBarAndTop,
  360. loudnessBarWidth,
  361. heightOfLoudnessBar);
  362. loudnessRangeNumeric.setBounds (loudnessRangeBarX,
  363. loudnessBarNumericTopPosition,
  364. loudnessBarWidth,
  365. heightOfNumericValues);
  366. loudnessRangeCaption.setBounds (loudnessRangeBarX,
  367. loudnessBarCaptionTopPosition,
  368. loudnessBarWidth,
  369. heightOfLoudnessCaptions);
  370. loudnessRangeCaption.setFont(fontForCaptions);
  371. // Integrated Loudness
  372. const int integratedLoudnessBarX = loudnessRangeBarX - spaceBetweenBars - loudnessBarWidth;
  373. integratedLoudnessBar.setBounds(integratedLoudnessBarX,
  374. distanceBetweenLoudnessBarAndTop,
  375. loudnessBarWidth,
  376. heightOfLoudnessBar);
  377. integratedLoudnessNumeric.setBounds (integratedLoudnessBarX,
  378. loudnessBarNumericTopPosition,
  379. loudnessBarWidth,
  380. heightOfNumericValues);
  381. integratedLoudnessCaption.setBounds(integratedLoudnessBarX,
  382. loudnessBarCaptionTopPosition,
  383. loudnessBarWidth,
  384. heightOfLoudnessCaptions);
  385. integratedLoudnessCaption.setFont(fontForCaptions);
  386. // Background grid caption
  387. const int backgroundGridCaptionX = integratedLoudnessBarX - spaceBetweenBars - backgroundGridCaptionWidth;
  388. backgroundGridCaption.setBounds(backgroundGridCaptionX, 0, backgroundGridCaptionWidth, loudnessBarBottomPosition + 32);
  389. // Background vertical lines and caption
  390. backgroundVerticalLinesAndCaption.setBounds(0, distanceBetweenLoudnessBarAndTop, jmax(backgroundGridCaptionX, 0), loudnessBarBottomPosition + 32 - distanceBetweenLoudnessBarAndTop);
  391. // Loudness history
  392. loudnessHistoryGroup.setBounds(0,
  393. distanceBetweenLoudnessBarAndTop,
  394. jmax(backgroundGridCaptionX, 0),
  395. heightOfLoudnessBar);
  396. }
  397. // quick-and-dirty function to format a timecode string
  398. static const String timeToTimecodeString (const double seconds)
  399. {
  400. const double absSecs = fabs (seconds);
  401. const int hours = (int) (absSecs / (60.0 * 60.0));
  402. const int mins = ((int) (absSecs / 60.0)) % 60;
  403. const int secs = ((int) absSecs) % 60;
  404. String s;
  405. if (seconds < 0)
  406. s = "-";
  407. s << String (hours).paddedLeft ('0', 2) << ":"
  408. << String (mins).paddedLeft ('0', 2) << ":"
  409. << String (secs).paddedLeft ('0', 2) << ":"
  410. << String (roundToInt (absSecs * 1000) % 1000).paddedLeft ('0', 3);
  411. return s;
  412. }
  413. #if 0
  414. // quick-and-dirty function to format a bars/beats string
  415. static const String ppqToBarsBeatsString (double ppq, double /*lastBarPPQ*/, int numerator, int denominator)
  416. {
  417. if (numerator == 0 || denominator == 0)
  418. return "1|1|0";
  419. const int ppqPerBar = (numerator * 4 / denominator);
  420. const double beats = (fmod (ppq, ppqPerBar) / ppqPerBar) * numerator;
  421. const int bar = ((int) ppq) / ppqPerBar + 1;
  422. const int beat = ((int) beats) + 1;
  423. const int ticks = ((int) (fmod (beats, 1.0) * 960.0));
  424. String s;
  425. s << bar << '|' << beat << '|' << ticks;
  426. return s;
  427. }
  428. #endif
  429. // Updates the text in our position label.
  430. void LUFSMeterAudioProcessorEditor::displayPositionInfo (const AudioPlayHead::CurrentPositionInfo& pos)
  431. {
  432. lastDisplayedPosition = pos;
  433. String displayText;
  434. displayText.preallocateBytes (128);
  435. displayText << String (pos.bpm, 2) << " bpm, "
  436. << pos.timeSigNumerator << '/' << pos.timeSigDenominator
  437. << " - " << timeToTimecodeString (pos.timeInSeconds);
  438. // << " - " << ppqToBarsBeatsString (pos.ppqPosition, pos.ppqPositionOfLastBarStart,
  439. // pos.timeSigNumerator, pos.timeSigDenominator);
  440. if (pos.isRecording)
  441. displayText << " (recording)";
  442. else if (pos.isPlaying)
  443. displayText << " (playing)";
  444. //infoLabel.setText (displayText, false);
  445. }