| 99 | } |
| 100 | |
| 101 | void SpectrumComponent::paint(juce::Graphics& g) |
| 102 | { |
| 103 | g.fillAll(juce::Colours::transparentBlack); |
| 104 | |
| 105 | auto width = getLocalBounds().getWidth(); |
| 106 | auto height = getLocalBounds().getHeight(); |
| 107 | auto mindB = -100.0f; |
| 108 | auto maxdB = 0.0f; |
| 109 | |
| 110 | // mouseOver state is updated in paint(), which is more robust |
| 111 | mouseOver = getLocalBounds().contains(getMouseXYRelative()); |
| 112 | maxDecibelValue = -100.0f; |
| 113 | |
| 114 | if (mouseOver && ! wasMouseOver) |
| 115 | { |
| 116 | isPeakLineVisible = true; |
| 117 | resetPeakData(); |
| 118 | } |
| 119 | wasMouseOver = mouseOver; |
| 120 | |
| 121 | juce::Path currentSpecPath, maxSpecPath; |
| 122 | currentSpecPath.startNewSubPath(0, (float) height); |
| 123 | if (mDrawPeak) |
| 124 | maxSpecPath.startNewSubPath(0, (float) height); |
| 125 | |
| 126 | std::array<float, 1024> smoothedDisplayData; |
| 127 | |
| 128 | { |
| 129 | juce::ScopedLock locker(dataLock); |
| 130 | |
| 131 | for (int i = 0; i < numberOfBins; ++i) |
| 132 | { |
| 133 | if (i == 0 || i == numberOfBins - 1) |
| 134 | smoothedDisplayData[i] = displayData[i]; |
| 135 | else |
| 136 | smoothedDisplayData[i] = (displayData[i - 1] + displayData[i] + displayData[i + 1]) / 3.0f; |
| 137 | } |
| 138 | |
| 139 | for (int i = 1; i < numberOfBins; ++i) |
| 140 | { |
| 141 | // --- CRITICAL CHANGE HERE --- |
| 142 | // Only capture new peaks when the mouse is hovering over the component. |
| 143 | if (mDrawPeak && mouseOver && smoothedDisplayData[i] > maxData[i]) |
| 144 | { |
| 145 | maxData[i] = smoothedDisplayData[i]; |
| 146 | } |
| 147 | |
| 148 | float currentDecibel = juce::Decibels::gainToDecibels(smoothedDisplayData[i] / (float) numberOfBins); |
| 149 | float maxDecibel = juce::Decibels::gainToDecibels(maxData[i] / (float) numberOfBins); |
| 150 | |
| 151 | float yPercent = juce::jmap(juce::jlimit(mindB, maxdB, currentDecibel), mindB, maxdB, 0.0f, 1.0f); |
| 152 | float yMaxPercent = juce::jmap(juce::jlimit(mindB, maxdB, maxDecibel), mindB, maxdB, 0.0f, 1.0f); |
| 153 | double currentFreq = i * mBinWidth.load(); |
| 154 | float currentX = transformToLog(currentFreq) * width; |
| 155 | float currentY = juce::jmap(yPercent, 0.0f, 1.0f, (float) height, 0.0f); |
| 156 | float maxY = juce::jmap(yMaxPercent, 0.0f, 1.0f, (float) height, 0.0f); |
| 157 | if (! std::isnan(currentX) && ! std::isinf(currentX)) |
| 158 | { |
nothing calls this directly
no test coverage detected