--------------------------------------------------------------------------- JSON output ---------------------------------------------------------------------------
| 214 | // JSON output |
| 215 | // --------------------------------------------------------------------------- |
| 216 | static void emitJson(int samples, int bands, float fmin, float fmax, |
| 217 | int sampleRate, int numSteps) { |
| 218 | fl::json root = fl::json::object(); |
| 219 | root.set("samples", samples); |
| 220 | root.set("bands", bands); |
| 221 | root.set("fmin", static_cast<double>(fmin)); |
| 222 | root.set("fmax", static_cast<double>(fmax)); |
| 223 | root.set("sample_rate", sampleRate); |
| 224 | root.set("num_steps", numSteps); |
| 225 | root.set("nyquist", static_cast<double>(sampleRate) / 2.0); |
| 226 | |
| 227 | fl::json sweeps = fl::json::array(); |
| 228 | |
| 229 | fl::vector<SweepPoint> points; |
| 230 | |
| 231 | for (int m = 0; m < NUM_MODES; m++) { |
| 232 | for (int w = 0; w < NUM_WINDOWS; w++) { |
| 233 | runSweep(MODES[m].mode, WINDOWS[w].window, |
| 234 | samples, bands, fmin, fmax, sampleRate, numSteps, |
| 235 | points); |
| 236 | |
| 237 | fl::json entry = fl::json::object(); |
| 238 | entry.set("mode", MODES[m].label); |
| 239 | entry.set("window", WINDOWS[w].label); |
| 240 | |
| 241 | SweepSummary inBand = computeSummary(points, true); |
| 242 | SweepSummary outBand = computeSummary(points, false); |
| 243 | |
| 244 | fl::json inBandJson = fl::json::object(); |
| 245 | inBandJson.set("aliasing_events", inBand.aliasingEvents); |
| 246 | inBandJson.set("non_monotonic_events", inBand.nonMonotonicEvents); |
| 247 | inBandJson.set("min_energy_concentration", |
| 248 | static_cast<double>(inBand.minConcentration)); |
| 249 | inBandJson.set("avg_energy_concentration", |
| 250 | static_cast<double>(inBand.avgConcentration)); |
| 251 | inBandJson.set("total_steps", inBand.totalSteps); |
| 252 | |
| 253 | fl::json outBandJson = fl::json::object(); |
| 254 | outBandJson.set("aliasing_events", outBand.aliasingEvents); |
| 255 | outBandJson.set("non_monotonic_events", |
| 256 | outBand.nonMonotonicEvents); |
| 257 | outBandJson.set("min_energy_concentration", |
| 258 | static_cast<double>(outBand.minConcentration)); |
| 259 | outBandJson.set("avg_energy_concentration", |
| 260 | static_cast<double>(outBand.avgConcentration)); |
| 261 | outBandJson.set("total_steps", outBand.totalSteps); |
| 262 | |
| 263 | entry.set("in_band", inBandJson); |
| 264 | entry.set("out_of_band", outBandJson); |
| 265 | |
| 266 | fl::json dataPoints = fl::json::array(); |
| 267 | for (int i = 0; i < static_cast<int>(points.size()); i++) { |
| 268 | const SweepPoint &pt = points[i]; |
| 269 | |
| 270 | fl::json p = fl::json::object(); |
| 271 | p.set("input_freq_hz", static_cast<double>(pt.inputFreq)); |
| 272 | p.set("peak_bin", pt.peakBinIdx); |
| 273 | p.set("peak_bin_freq_hz", |