| 123 | } |
| 124 | |
| 125 | void WaterFall::drawFFT() { |
| 126 | // Calculate scaling factor |
| 127 | float startLine = floorf(fftMax / vRange) * vRange; |
| 128 | float vertRange = fftMax - fftMin; |
| 129 | float scaleFactor = fftHeight / vertRange; |
| 130 | char buf[100]; |
| 131 | |
| 132 | ImU32 trace = ImGui::GetColorU32(ImGuiCol_PlotLines); |
| 133 | ImU32 shadow = ImGui::GetColorU32(ImGuiCol_PlotLines, 0.2); |
| 134 | ImU32 text = ImGui::GetColorU32(ImGuiCol_Text); |
| 135 | |
| 136 | // Vertical scale |
| 137 | for (float line = startLine; line > fftMin; line -= vRange) { |
| 138 | float yPos = widgetPos.y + fftHeight + 10 - ((line - fftMin) * scaleFactor); |
| 139 | window->DrawList->AddLine(ImVec2(roundf(widgetPos.x + 50), roundf(yPos)), |
| 140 | ImVec2(roundf(widgetPos.x + dataWidth + 50), roundf(yPos)), |
| 141 | IM_COL32(50, 50, 50, 255), 1.0); |
| 142 | sprintf(buf, "%d", (int)line); |
| 143 | ImVec2 txtSz = ImGui::CalcTextSize(buf); |
| 144 | window->DrawList->AddText(ImVec2(widgetPos.x + 40 - txtSz.x, roundf(yPos - (txtSz.y / 2.0))), text, buf); |
| 145 | } |
| 146 | |
| 147 | // Horizontal scale |
| 148 | double startFreq = ceilf(lowerFreq / range) * range; |
| 149 | double horizScale = (double)dataWidth / viewBandwidth; |
| 150 | for (double freq = startFreq; freq < upperFreq; freq += range) { |
| 151 | double xPos = widgetPos.x + 50 + ((freq - lowerFreq) * horizScale); |
| 152 | window->DrawList->AddLine(ImVec2(roundf(xPos), widgetPos.y + 10), |
| 153 | ImVec2(roundf(xPos), widgetPos.y + fftHeight + 10), |
| 154 | IM_COL32(50, 50, 50, 255), 1.0); |
| 155 | window->DrawList->AddLine(ImVec2(roundf(xPos), widgetPos.y + fftHeight + 10), |
| 156 | ImVec2(roundf(xPos), widgetPos.y + fftHeight + 17), |
| 157 | text, 1.0); |
| 158 | printAndScale(freq, buf); |
| 159 | ImVec2 txtSz = ImGui::CalcTextSize(buf); |
| 160 | window->DrawList->AddText(ImVec2(roundf(xPos - (txtSz.x / 2.0)), widgetPos.y + fftHeight + 10 + txtSz.y), text, buf); |
| 161 | } |
| 162 | |
| 163 | // Data |
| 164 | if (latestFFT != NULL && fftLines != 0) { |
| 165 | for (int i = 1; i < dataWidth; i++) { |
| 166 | double aPos = widgetPos.y + fftHeight + 10 - ((latestFFT[i - 1] - fftMin) * scaleFactor); |
| 167 | double bPos = widgetPos.y + fftHeight + 10 - ((latestFFT[i] - fftMin) * scaleFactor); |
| 168 | aPos = std::clamp<double>(aPos, widgetPos.y + 10, widgetPos.y + fftHeight + 10); |
| 169 | bPos = std::clamp<double>(bPos, widgetPos.y + 10, widgetPos.y + fftHeight + 10); |
| 170 | window->DrawList->AddLine(ImVec2(widgetPos.x + 49 + i, roundf(aPos)), |
| 171 | ImVec2(widgetPos.x + 50 + i, roundf(bPos)), trace, 1.0); |
| 172 | window->DrawList->AddLine(ImVec2(widgetPos.x + 50 + i, roundf(bPos)), |
| 173 | ImVec2(widgetPos.x + 50 + i, widgetPos.y + fftHeight + 10), shadow, 1.0); |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | FFTRedrawArgs args; |
| 178 | args.min = ImVec2(widgetPos.x + 50, widgetPos.y + 9); |
| 179 | args.max = ImVec2(widgetPos.x + dataWidth + 50, widgetPos.y + fftHeight + 10); |
| 180 | args.lowFreq = lowerFreq; |
| 181 | args.highFreq = upperFreq; |
| 182 | args.freqToPixelRatio = horizScale; |