Files
utun2/tools/chatgui/transport/audio_diagnostics.h
T

85 lines
7.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include <stdint.h>
/* Desktop-аудиодиагностика Linux/Windows; на других платформах API ничего не делает.
* После start несколько producers передают метаданные в MPSC-кольцо на 8192 события.
* Публикация без allocation/логирования/ожидания, не более четырёх попыток резервирования;
* перегрузка/конкуренция дают потерю события, которую reporter отмечает в сводке.
* Отдельный поток опрашивает очередь каждые 20 мс, пишет секундные сводки в call:
* штатные стадии TRACE, часы DEBUG, аномалии WARN (первая каждого типа за интервал + счётчики).
* Указатели device/log — только числовые ключи, могут быть NULL; reporter их не разыменовывает.
* Строки копируются до 191 байта плюс NUL, timing копируется целиком до возврата вызова.
* PCM и содержимое сообщений не принимаются. До start/после stop события игнорируются. */
#ifdef __cplusplus
extern "C" {
#endif
/* Только метаданные: PCM и содержимое сообщений не записываются. */
enum audio_diag_stage {
AUDIO_DIAG_LOOP, AUDIO_DIAG_READ, AUDIO_DIAG_WRITE, AUDIO_DIAG_MAP,
AUDIO_DIAG_SUBMIT, AUDIO_DIAG_DUPLEX, AUDIO_DIAG_CALLBACK,
AUDIO_DIAG_FEED, AUDIO_DIAG_PULL, AUDIO_DIAG_STAGE_COUNT
};
enum audio_diag_kind {
AUDIO_DIAG_ENTER, AUDIO_DIAG_LEAVE, AUDIO_DIAG_OPEN, AUDIO_DIAG_CLOSE,
AUDIO_DIAG_NOTIFY, AUDIO_DIAG_BACKEND_STARTED, AUDIO_DIAG_HOLE, AUDIO_DIAG_UNFILLED, AUDIO_DIAG_CAPTURE_DROP,
AUDIO_DIAG_NO_PROGRESS, AUDIO_DIAG_BACKEND_UNDERRUN, AUDIO_DIAG_BACKEND_OVERFLOW, AUDIO_DIAG_ERROR, AUDIO_DIAG_LABEL, AUDIO_DIAG_LOG,
AUDIO_DIAG_CAPTURE_CLOCK, AUDIO_DIAG_PLAYBACK_CLOCK, AUDIO_DIAG_WASAPI_PLAYBACK
};
struct audio_capture_timing {
int64_t first_us; // оценка monotonic-времени первого кадра блока, микросекунды
int64_t latency_us; // знаковая backend latency, учитывается только при measured!=0
int64_t converter_us; // задержка converter/cache, микросекунды
unsigned frames, rate; // размер блока и его частота, Гц; rate=0 исключает расчёт длительности
int measured; // backend-оценка доступна; 0 означает оценочный блок без измеренной latency
int missing; // блок с hole: в missing_frames попадают все frames этого блока
};
struct audio_playback_timing {
int64_t latency_us, converter_us; // backend latency и задержка converter/cache, микросекунды
unsigned frames, rate; // размер блока и частота, Гц; rate=0 исключает расчёт длительности
int measured; // ненулевой: latency_us участвует в диапазоне; отрицательная latency допустима
};
/* Снимок перед заполнением client PCM. Padding — текущая очередь, stream_latency — отдельное
* свойство WASAPI; их сумма не объявляется измеренным временем физического воспроизведения. */
struct audio_wasapi_timing {
int64_t stream_latency_us, converter_us; // Задержка stream API и converter/cache соответственно.
unsigned frames, rate, device_rate; // Размер client callback, client/device частоты в Гц.
unsigned padding_frames, buffer_frames, period_frames, periods; // Размеры очереди/буфера в device PCM.
unsigned mapped_frames; // Уже заполненная часть незавершённого WASAPI buffer.
int shared, fixed_callback; // Режим доступа и наличие дополнительного callback-буфера.
int32_t padding_result, latency_result; // HRESULT каждого запроса; отрицательное значение — ошибка.
};
/* Один управляющий владелец сериализует start/stop. Повторный start активного reporter — no-op;
* отказ создания потока логируется, диагностика остаётся выключенной (возврата статуса нет).
* Перед stop остановить и дождаться всех producers, включая незавершённые публикации.
* stop дренирует очередь, пишет последнюю сводку и join; повторный stop допустим.
* Следующий start очищает статистику и очередь. Не вызывать stop из reporter. */
void audio_diag_start(void);
void audio_diag_stop(void);
/* kind — ENTER..ERROR; LABEL/LOG/CLOCK передавать специализированными функциями.
* ENTER/LEAVE требуют stage=0..STAGE_COUNT-1; остальные события могут использовать -1.
* value/detail — backend-метрики: ENTER value=frames, OPEN value=тип/detail=частота;
* для аномалий value даёт max(value,1) в счётчик. Неверные kind/stage дают ERROR-событие. */
void audio_diag_event(const void* device, int kind, int stage, int64_t value, int64_t detail);
/* Метка ресурса; id без интерпретации, NULL name означает пустую строку. */
void audio_diag_label(const void* device, uint64_t id, const char* name);
/* miniaudio level 1/2/3/остальные -> ERROR/WARN/DEBUG/TRACE; NULL message — пустая строка.
* Строки с Hole. подавляются: число hole-кадров собирает отдельное событие. */
void audio_diag_log(const void* log, unsigned int level, const char* message);
/* Снимки из потока устройства; timing обязателен, NULL даёт ERROR-событие без снимка. */
void audio_diag_capture_clock(const void* device, const struct audio_capture_timing* timing);
void audio_diag_playback_clock(const void* device, const struct audio_playback_timing* timing);
/* Снимок перед заполнением playback buffer; timing обязателен, NULL даёт ERROR-событие.
* Только shared padding с успешным HRESULT и device_rate>0 даёт оценку очереди;
* stream latency учитывается отдельно, даже в exclusive mode. */
void audio_diag_wasapi_playback(const void* device, const struct audio_wasapi_timing* timing);
#ifdef __cplusplus
}
#endif