Audio: robust rate estimation + color-coded log levels

Harden the guessed-stream sample-rate measurement that produced wrong rates
(e.g. 44100 read as ~46205). New rate_estimator.hpp measures over longer
~0.5 s windows, rejects any window that doesn't snap to a standard rate
(standard rates are >8% apart, so a quantization/burst error big enough to
miss one lands in no-man's-land, never on a wrong neighbour), and requires
consensus across windows before committing. If consensus isn't reached it
commits a low-confidence estimate (new AudioFormat_LowConfidence, shown red)
rather than spinning or publishing garbage. Pure logic, unit-tested with
adversarial cadences (rate_estimator_test) incl. the real 46205 bug value.

Add log severity levels: hook logw/loge set LogRecord.level; the host Log
window colors warnings amber and errors red. The low-confidence rate logs a
warning. Protocol -> v15 (new format states); also reserves AudioFormat_Override.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 01:11:06 +02:00
parent f72da74f78
commit cb6749b511
11 changed files with 462 additions and 102 deletions

View File

@@ -21,7 +21,7 @@ void LogPanel::add_line(const LogRecord& rec)
char buf[256];
std::snprintf(buf, sizeof(buf), "[%8.3f] %s", secs, rec.text);
lines_.emplace_back(buf);
lines_.push_back({buf, rec.level});
while (lines_.size() > kMaxLines)
{
lines_.pop_front();
@@ -53,13 +53,24 @@ void LogPanel::draw()
if (ImGui::BeginChild("loglines", ImVec2(0, 0), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar))
{
const bool has_filter = filter_[0] != '\0';
for (const std::string& line : lines_)
for (const Line& line : lines_)
{
if (has_filter && line.find(filter_) == std::string::npos)
if (has_filter && line.text.find(filter_) == std::string::npos)
{
continue;
}
ImGui::TextUnformatted(line.c_str());
switch (line.level)
{
case LogLevel_Warn:
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.3f, 1.0f), "%s", line.text.c_str()); // amber
break;
case LogLevel_Error:
ImGui::TextColored(ImVec4(1.0f, 0.45f, 0.4f, 1.0f), "%s", line.text.c_str()); // red
break;
default:
ImGui::TextUnformatted(line.text.c_str());
break;
}
}
// Stick to the bottom while new lines arrive (unless the user scrolled up).
if (autoscroll_ && ImGui::GetScrollY() >= ImGui::GetScrollMaxY() - 1.0f)