78 lines
4.7 KiB
C
78 lines
4.7 KiB
C
/* Виртуальное устройство сохраняет уже поставленные темпы: проверка догона и истории без реального времени. */
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "../src/stream/stream_playback_clock.h"
|
|
#include "../lib/debug_config.h"
|
|
|
|
#define CHECK(x) do { if (!(x)) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "playback test line=%d: %s", __LINE__, #x); exit(1); } } while (0)
|
|
|
|
static void test_history_correction(void) {
|
|
struct stream_playback_clock clock; struct stream_playback_state state;
|
|
stream_playback_clock_reset(&clock, 1);
|
|
CHECK(!stream_playback_clock_update(&clock, 0, 0, 120000, 20000, 0, 0, &state));
|
|
CHECK(!stream_playback_clock_update(&clock, 1000000, 1000000, 1300000, 20000, 0, 0, &state));
|
|
CHECK(state.minimum_us == 120000 && state.correction_us == 0);
|
|
CHECK(!stream_playback_clock_update(&clock, 1080000, 1000000, 1300000, 20000, 0, 1, &state));
|
|
CHECK(state.minimum_us == 200000 && state.correction_us == 80000 && state.waiting);
|
|
CHECK(!stream_playback_clock_update(&clock, 1090000, 1010000, 1310000, 20000, 0, 0, &state));
|
|
CHECK(!state.waiting && state.tempo_milli == 1000);
|
|
CHECK(!stream_playback_clock_update(&clock, 2090000, 2110000, 2410000, 20000, 0, 0, &state));
|
|
CHECK(state.minimum_us == 100000 && state.correction_us == -20000);
|
|
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] history: pause shifts all minima +80ms, actual x1.1 shifts -100ms");
|
|
}
|
|
|
|
static void test_catchup_device_queue(void) {
|
|
struct stream_playback_clock clock; struct stream_playback_state state;
|
|
stream_playback_clock_reset(&clock, 2);
|
|
int queued[100]; for (unsigned i = 0; i < 100; i++) queued[i] = 1000;
|
|
int64_t position = 0;
|
|
int accelerated = 0, maximum = 1000;
|
|
for (int64_t tick = 0; tick <= 120000; tick++) {
|
|
unsigned slot = (unsigned)(tick % 100);
|
|
if (tick) position += queued[slot];
|
|
int64_t pending_gain = 0;
|
|
for (unsigned i = 0; i < 100; i++) pending_gain += queued[i] - 1000;
|
|
CHECK(!stream_playback_clock_update(&clock, tick * 1000, position, tick * 1000 + 300000,
|
|
30000, pending_gain, 0, &state));
|
|
CHECK(state.tempo_milli >= 1000 && state.tempo_milli <= 1100);
|
|
if (tick < 60000) CHECK(state.tempo_milli == 1000);
|
|
if (state.tempo_milli > 1000) accelerated = 1;
|
|
if (state.tempo_milli > maximum) maximum = state.tempo_milli;
|
|
CHECK(state.minimum_us >= 29000);
|
|
queued[slot] = state.tempo_milli;
|
|
}
|
|
CHECK(accelerated && maximum == 1100 && state.history_ready);
|
|
CHECK(state.reserve_us >= 29000 && state.reserve_us < 33000 && state.tempo_milli == 1000);
|
|
/* Короткая остановка, попавшая между секундными отсчётами, блокирует догон на полную минуту. */
|
|
int64_t now = 120000000;
|
|
CHECK(!stream_playback_clock_update(&clock, now + 10000, position, position, 30000, 0, 1, &state));
|
|
CHECK(!stream_playback_clock_update(&clock, now + 20000, position, position + 500000, 30000, 0, 0, &state));
|
|
for (int64_t tick = 1; tick < 60000; tick++) {
|
|
CHECK(!stream_playback_clock_update(&clock, now + 20000 + tick * 1000, position + tick * 1000,
|
|
position + tick * 1000 + 500000, 30000, 0, 0, &state));
|
|
CHECK(state.tempo_milli == 1000);
|
|
}
|
|
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] catchup: healthy minute, smooth x1.1, queued audio, safe residual and pause cooldown");
|
|
}
|
|
|
|
static void test_invalid_and_sampling_gap(void) {
|
|
struct stream_playback_clock clock; struct stream_playback_state state, before;
|
|
stream_playback_clock_reset(&clock, 3); memset(&state, 0xa5, sizeof(state)); before = state;
|
|
CHECK(stream_playback_clock_update(&clock, -1, 0, 0, 0, 0, 0, &state) < 0 && !memcmp(&state, &before, sizeof(state)));
|
|
CHECK(!stream_playback_clock_update(&clock, 0, 0, 200000, 20000, 0, 0, &state));
|
|
CHECK(!stream_playback_clock_update(&clock, 2000000, 2000000, 2200000, 20000, 0, 0, &state));
|
|
CHECK(!state.stable_us && state.tempo_milli == 1000 && !state.history_ready);
|
|
before = state;
|
|
CHECK(stream_playback_clock_update(&clock, 2000001, 1000000, 2200000, 20000, 0, 0, &state) < 0);
|
|
CHECK(!memcmp(&state, &before, sizeof(state)));
|
|
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "[PASS] clock: invalid/backward positions preserve result, missed samples reset healthy minute");
|
|
}
|
|
|
|
int main(void) {
|
|
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR);
|
|
debug_set_category_level(DEBUG_CATEGORY_STREAM, DEBUG_LEVEL_INFO);
|
|
test_history_correction(); test_catchup_device_queue(); test_invalid_and_sampling_gap();
|
|
return 0;
|
|
}
|