|
|
|
|
@ -122,11 +122,11 @@ static void test_vad_compressor(UTUN_INSTANCE* instance, int channels, int max_g
|
|
|
|
|
check_vad_pcm(pcm.data(), idle + live, channels, max_gain); |
|
|
|
|
REQUIRE(*std::max_element(vad_input.begin(), vad_input.end()) > 240.0f / 32768.0f * 1.5f); |
|
|
|
|
uasync_poll(instance->ua, 0); |
|
|
|
|
REQUIRE(packets.size() == 54 && events.front() == 'B' && events.back() == 'F'); |
|
|
|
|
REQUIRE(packets.size() == 34 && events.front() == 'B' && events.back() == 'F'); |
|
|
|
|
auto* encoder = opus_codec_encoder_create(48000, channels); REQUIRE(encoder); |
|
|
|
|
opus_codec_encoder_bitrate_set(encoder, 32000); |
|
|
|
|
auto* tx = reference_compressor(channels, 6); |
|
|
|
|
for (int i = 0; i < 54; ++i) check_packet(encoder, pcm.data() + (idle - 48000 + i * 960) * channels, i, tx, channels); |
|
|
|
|
for (int i = 0; i < 34; ++i) check_packet(encoder, pcm.data() + (idle - 28800 + i * 960) * channels, i, tx, channels); |
|
|
|
|
audio_compressor_destroy(tx); opus_codec_encoder_destroy(encoder); |
|
|
|
|
// Разрыв и новый захват должны убрать и неполный блок 20мс, и историю усиления.
|
|
|
|
|
feed_chunks(pcm.data(), 800); |
|
|
|
|
@ -143,7 +143,7 @@ static void test_vad_compressor(UTUN_INSTANCE* instance, int channels, int max_g
|
|
|
|
|
debug_set_category_level(DEBUG_CATEGORY_RADIO, DEBUG_LEVEL_NONE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Полная секунда кольца, граница VAD внутри кадра и live должны совпасть с непрерывным Opus-потоком. */ |
|
|
|
|
/* Полные 600мс кольца, граница VAD внутри кадра и live должны совпасть с непрерывным Opus-потоком. */ |
|
|
|
|
static void test_prefetch(UTUN_INSTANCE* instance, int channels, int compressor_enabled = 0) { |
|
|
|
|
debug_set_category_level(DEBUG_CATEGORY_RADIO, DEBUG_LEVEL_INFO); |
|
|
|
|
packets.clear(); events.clear(); probability = 0; radio_compressor_enabled = compressor_enabled; |
|
|
|
|
@ -163,14 +163,14 @@ static void test_prefetch(UTUN_INSTANCE* instance, int channels, int compressor_
|
|
|
|
|
REQUIRE(radio_audio_feed_pcm(7, pcm.data() + (trigger + 1) * channels, live * channels) == 0); |
|
|
|
|
int pending = 0; |
|
|
|
|
for (auto* task = instance->ua->posted_tasks_head; task; task = task->next) ++pending; |
|
|
|
|
REQUIRE(pending == 3); // BEGIN + одна задача на 50 кадров prefetch + один live-кадр.
|
|
|
|
|
REQUIRE(pending == 3); // BEGIN + одна задача на 30 кадров prefetch + один live-кадр.
|
|
|
|
|
radio_audio_capture_stop(); uasync_poll(instance->ua, 0); |
|
|
|
|
REQUIRE(packets.size() == 51 && events.size() == 53 && events.front() == 'B' && events.back() == 'F'); |
|
|
|
|
REQUIRE(packets.size() == 31 && events.size() == 33 && events.front() == 'B' && events.back() == 'F'); |
|
|
|
|
auto* encoder = opus_codec_encoder_create(48000, channels); REQUIRE(encoder); |
|
|
|
|
opus_codec_encoder_bitrate_set(encoder, 32000); |
|
|
|
|
auto* tx = compressor_enabled ? reference_compressor(channels, 15) : nullptr; |
|
|
|
|
const int first = trigger - 48000; |
|
|
|
|
for (int i = 0; i < 51; ++i) check_packet(encoder, pcm.data() + (first + i * 960) * channels, i, tx, channels); |
|
|
|
|
const int first = trigger - 28800; |
|
|
|
|
for (int i = 0; i < 31; ++i) check_packet(encoder, pcm.data() + (first + i * 960) * channels, i, tx, channels); |
|
|
|
|
audio_compressor_destroy(tx); |
|
|
|
|
opus_codec_encoder_destroy(encoder); |
|
|
|
|
radio_compressor_enabled = 0; |
|
|
|
|
@ -208,7 +208,7 @@ static void test_prefetch(UTUN_INSTANCE* instance, int channels, int compressor_
|
|
|
|
|
check_packet(encoder, tail.data(), 0); |
|
|
|
|
opus_codec_encoder_destroy(encoder); |
|
|
|
|
radio_audio_stop(); uasync_poll(instance->ua, 0); |
|
|
|
|
printf("voice TX: prefetch 1000ms, exact ring/live order, short history, discontinuity, no replay ch=%d PASS\n", channels); |
|
|
|
|
printf("voice TX: prefetch 600ms, exact ring/live order, short history, discontinuity, no replay ch=%d PASS\n", channels); |
|
|
|
|
debug_set_category_level(DEBUG_CATEGORY_RADIO, DEBUG_LEVEL_NONE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -233,12 +233,12 @@ static void test_prefetch_deferred(UTUN_INSTANCE* instance) {
|
|
|
|
|
packets.clear(); events.clear(); |
|
|
|
|
REQUIRE(radio_audio_feed_pcm(7, pcm.data() + idle + confirm, 1) == 0 && radio_audio_transmitting()); |
|
|
|
|
radio_audio_capture_stop(); uasync_poll(instance->ua, 0); |
|
|
|
|
REQUIRE(packets.size() == 51 && events.front() == 'B' && events.back() == 'F'); |
|
|
|
|
REQUIRE(packets.size() == 31 && events.front() == 'B' && events.back() == 'F'); |
|
|
|
|
auto* encoder = opus_codec_encoder_create(48000, 1); REQUIRE(encoder); |
|
|
|
|
opus_codec_encoder_bitrate_set(encoder, 32000); |
|
|
|
|
const int first = idle + confirm - 48000; |
|
|
|
|
for (int i = 0; i < 50; ++i) check_packet(encoder, pcm.data() + first + i * 960, i); |
|
|
|
|
std::array<int16_t, 960> tail{}; tail[0] = pcm.back(); check_packet(encoder, tail.data(), 50); |
|
|
|
|
const int first = idle + confirm - 28800; |
|
|
|
|
for (int i = 0; i < 30; ++i) check_packet(encoder, pcm.data() + first + i * 960, i); |
|
|
|
|
std::array<int16_t, 960> tail{}; tail[0] = pcm.back(); check_packet(encoder, tail.data(), 30); |
|
|
|
|
opus_codec_encoder_destroy(encoder); |
|
|
|
|
radio_audio_stop(); uasync_poll(instance->ua, 0); |
|
|
|
|
puts("voice TX: full media queue defers BEGIN and preserves complete prefetch PASS"); |
|
|
|
|
|