You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

86 lines
3.3 KiB

// test_radio_audio.cpp — тест аудио-движка рации (jitter + микшер).
//
// Проверяет сервисный слой src/radio/radio_audio.c без полного UTUN_INSTANCE:
// 1. single-source: подаём кодированные Opus-кадры через radio_audio_on_frame,
// radio_audio_pull_pcm выдаёт декодированный ненулевой PCM (jitter+decode).
// 2. mixing: два источника с большими амплитудами — сумма насыщается (soft-clip),
// что доказывает микширование нескольких источников.
//
// Сборка/запуск: через CMake (tools/chatgui), линкуется utun_voice + utun.
#include "radio/radio_audio.h"
extern "C" {
#include "../../lib/opus_codec.h"
}
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define GID 0x1234567890abcdefULL
#define SRC_A 0xAAAAULL
#define SRC_B 0xBBBBULL
static int G_PASSED = 0, G_FAILED = 0, G_TOTAL = 0;
#define TEST(n) do { G_TOTAL++; printf(" %-58s", n); fflush(stdout); } while(0)
#define OK() do { G_PASSED++; printf("OK\n"); } while(0)
#define FAIL(f,...) do { G_FAILED++; printf("FAIL: " f "\n", ##__VA_ARGS__); } while(0)
/* закодировать N кадров постоянного PCM и подать через on_frame */
static void push_const(uint64_t src, uint16_t stream, int value, int nframes) {
opus_codec_encoder_t* enc = opus_codec_encoder_create(48000, 1);
if (!enc) { FAIL("encoder create failed"); return; }
opus_codec_encoder_bitrate_set(enc, 32000);
int16_t pcm[960];
for (int i = 0; i < 960; i++) pcm[i] = (int16_t)value;
for (int f = 0; f < nframes; f++) {
uint8_t opus[256];
int len = opus_codec_encode(enc, pcm, 960, opus, (int)sizeof(opus));
if (len <= 0) { FAIL("encode failed"); break; }
radio_audio_on_frame(NULL, GID, src, stream, (uint16_t)f, 0, opus, len, NULL);
}
opus_codec_encoder_destroy(enc);
}
/* вытянуть pull-цикл, вернуть max |sample| */
static int pull_max_abs(int npulls) {
int mx = 0;
int16_t out[960];
for (int p = 0; p < npulls; p++) {
int n = radio_audio_pull_pcm(GID, out, 960);
(void)n;
for (int i = 0; i < 960; i++) {
int a = out[i] < 0 ? -out[i] : out[i];
if (a > mx) mx = a;
}
}
return mx;
}
int main() {
printf("=== test_radio_audio ===\n"); fflush(stdout);
TEST("single-source: decode через jitter-буфер выдаёт ненулевой PCM"); {
radio_audio_start(GID);
push_const(SRC_A, 1, 10000, 5);
int mx = pull_max_abs(10);
radio_audio_stop();
if (mx > 1000) OK(); else FAIL("max|pcm|=%d (ожидали > 1000)", mx);
}
TEST("mixing: два источника складываются (soft-clip)"); {
radio_audio_start(GID);
push_const(SRC_A, 1, 20000, 5);
push_const(SRC_B, 1, 20000, 5);
int mx = pull_max_abs(10);
radio_audio_stop();
if (mx > 30000) OK(); else FAIL("max|pcm|=%d (ожидали > 30000 — сумма двух источников)", mx);
}
printf("\n%d/%d passed, %d failed\n", G_PASSED, G_TOTAL, G_FAILED);
return G_FAILED > 0 ? 1 : 0;
}