fix: guard spectrogram buffer against height=2
A buffer of height 2 made half-1 zero, dividing by zero in pushColumn and writing NaN into the column. Clamp the denominator and add a regression test for the 2-row case.
This commit is contained in:
@@ -30,22 +30,21 @@ float SpectrogramBuffer::norm01(float magnitude) {
|
||||
|
||||
void SpectrogramBuffer::pushColumn(const std::vector<float>& magCh1,
|
||||
const std::vector<float>& magCh2) {
|
||||
const int col = writeIndex_;
|
||||
const int half = height_ / 2;
|
||||
const int col = writeIndex_;
|
||||
const int half = height_ / 2;
|
||||
const float denom = static_cast<float>(std::max(1, half - 1));
|
||||
|
||||
// CH1 -> northern rows [half, height_): row half = equator (low freq),
|
||||
// row height_-1 = north pole (high freq).
|
||||
for (int r = half; r < height_; ++r) {
|
||||
const float frac = static_cast<float>(r - half) /
|
||||
static_cast<float>(half - 1);
|
||||
const float frac = static_cast<float>(r - half) / denom;
|
||||
data_[static_cast<std::size_t>(r) * width_ + col] =
|
||||
norm01(logResample(magCh1, frac));
|
||||
}
|
||||
// CH2 -> southern rows [0, half): row half-1 = equator (low freq),
|
||||
// row 0 = south pole (high freq).
|
||||
for (int r = 0; r < half; ++r) {
|
||||
const float frac = static_cast<float>(half - 1 - r) /
|
||||
static_cast<float>(half - 1);
|
||||
const float frac = static_cast<float>(half - 1 - r) / denom;
|
||||
data_[static_cast<std::size_t>(r) * width_ + col] =
|
||||
norm01(logResample(magCh2, frac));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "check.h"
|
||||
#include "SpectrogramBuffer.h"
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
using oscope::SpectrogramBuffer;
|
||||
@@ -25,8 +26,22 @@ static void test_high_freq_maps_to_poles() {
|
||||
CHECK(d[0 * W + 0] > d[3 * W + 0]); // CH2: south pole > equator
|
||||
}
|
||||
|
||||
// A 2-row buffer (half == 1) must not divide by zero / emit NaN.
|
||||
static void test_height_two_is_finite() {
|
||||
SpectrogramBuffer buf(4, 2);
|
||||
std::vector<float> m(1024, 0.0f);
|
||||
m[500] = 50.0f;
|
||||
buf.pushColumn(m, m);
|
||||
const std::vector<float>& d = buf.data();
|
||||
bool allFinite = true;
|
||||
for (float v : d)
|
||||
if (!std::isfinite(v)) allFinite = false;
|
||||
CHECK(allFinite);
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_write_index_wraps();
|
||||
test_high_freq_maps_to_poles();
|
||||
test_height_two_is_finite();
|
||||
REPORT();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user