Phase 10: Audit engine reliability and strengthen lifecycle regression tests
This commit is contained in:
parent
4eb2080933
commit
8dd96d3cc5
13 changed files with 394 additions and 5 deletions
|
|
@ -79,6 +79,33 @@ static int routing(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* External mono input is read by both channels, including when left aliases it. */
|
||||
static int stereo_alias(void)
|
||||
{
|
||||
xtc_graph *graph = NULL;
|
||||
xtc_plan *plan = NULL;
|
||||
size_t gain, audio, output, i;
|
||||
float left[4] = {1, 2, 3, 4}, right[4];
|
||||
CHECK(xtc_graph_create(3, &graph) == XTC_OK);
|
||||
CHECK(xtc_graph_add_gain(graph, 2, &gain) == XTC_OK);
|
||||
CHECK(xtc_graph_add_audio(graph, &audio) == XTC_OK);
|
||||
CHECK(xtc_graph_add_output(graph, &output) == XTC_OK);
|
||||
CHECK(xtc_graph_connect(graph, gain, output) == XTC_OK);
|
||||
CHECK(xtc_graph_connect(graph, audio, output) == XTC_OK);
|
||||
CHECK(xtc_graph_compile(graph, 48000, 4, &plan) == XTC_OK);
|
||||
CHECK(xtc_plan_process_stereo(plan, left, NULL, NULL, NULL, NULL, left, right, 4) == XTC_OK);
|
||||
for (i = 0; i < 4; ++i)
|
||||
CHECK(left[i] == 2 * (float)(i + 1) && right[i] == left[i]);
|
||||
for (i = 0; i < 4; ++i) right[i] = 10 + (float)i;
|
||||
/* Cross-channel source alias must also retain the original source samples. */
|
||||
CHECK(xtc_plan_process_stereo(plan, NULL, right, left, NULL, NULL, left, right, 4) == XTC_OK);
|
||||
for (i = 0; i < 4; ++i)
|
||||
CHECK(left[i] == 10 + (float)i && right[i] == 2 * (float)(i + 1));
|
||||
xtc_plan_destroy(plan);
|
||||
xtc_graph_destroy(graph);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int validation(void)
|
||||
{
|
||||
xtc_graph *graph = NULL;
|
||||
|
|
@ -133,6 +160,7 @@ int main(void)
|
|||
CHECK(oscillator() == 0);
|
||||
CHECK(routing() == 0);
|
||||
CHECK(validation() == 0);
|
||||
CHECK(stereo_alias() == 0);
|
||||
puts("All offline graph tests passed.");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,46 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include "xtc/xtc_realtime.h"
|
||||
#include "xtc/xtc_native.h"
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define CHECK(c) do { if (!(c)) { fprintf(stderr,"FAIL %s:%d: %s\n",__FILE__,__LINE__,#c); return 1; } } while (0)
|
||||
|
||||
/* Count native lifetimes on the serialized producer while a real consumer
|
||||
* traverses plans. Destruction on that consumer is always a contract violation. */
|
||||
static pthread_t control_thread;
|
||||
static unsigned int prepared, destroyed;
|
||||
static xtc_result prepare(double rate, size_t frames, float gain, void **state)
|
||||
{
|
||||
(void)rate; (void)frames;
|
||||
assert(pthread_equal(pthread_self(), control_thread));
|
||||
*state = malloc(sizeof(float));
|
||||
if (!*state) return XTC_ERR_OUT_OF_MEMORY;
|
||||
*(float *)*state = gain;
|
||||
++prepared;
|
||||
return XTC_OK;
|
||||
}
|
||||
static void reset(void *state) { (void)state; }
|
||||
static xtc_result process(void *state, const xtc_native_block *block)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < block->frames; ++i)
|
||||
block->output[i] = block->input[i] * *(float *)state;
|
||||
return XTC_OK;
|
||||
}
|
||||
static void destroy(void *state)
|
||||
{
|
||||
assert(pthread_equal(pthread_self(), control_thread));
|
||||
if (state) ++destroyed;
|
||||
free(state);
|
||||
}
|
||||
static const xtc_native_descriptor descriptor = {
|
||||
XTC_NATIVE_ABI_VERSION, sizeof(xtc_native_descriptor), "concurrent.gain",
|
||||
XTC_NATIVE_EFFECT, prepare, reset, process, destroy
|
||||
};
|
||||
|
||||
typedef struct { xtc_realtime *engine; unsigned int stop, failed; } worker_state;
|
||||
static void *worker(void *context)
|
||||
{
|
||||
|
|
@ -40,9 +75,9 @@ static int run(void)
|
|||
CHECK(xtc_realtime_create(48000.0, 32U, &engine) == XTC_OK);
|
||||
CHECK(xtc_realtime_process(engine, input, output, 4U) == XTC_OK && output[0] == 0.0f);
|
||||
CHECK(xtc_graph_create(1U, &one) == XTC_OK);
|
||||
CHECK(xtc_graph_add_gain(one, 1.0f, &node) == XTC_OK);
|
||||
CHECK(xtc_graph_add_native(one, &descriptor, 1.0f, &node) == XTC_OK);
|
||||
CHECK(xtc_graph_create(1U, &two) == XTC_OK);
|
||||
CHECK(xtc_graph_add_gain(two, 2.0f, &node) == XTC_OK);
|
||||
CHECK(xtc_graph_add_native(two, &descriptor, 2.0f, &node) == XTC_OK);
|
||||
CHECK(xtc_realtime_submit(engine, one) == XTC_OK);
|
||||
CHECK(xtc_realtime_submit(engine, two) == XTC_ERR_CAPACITY);
|
||||
CHECK(xtc_realtime_get_status(engine, &status) == XTC_OK && status.submitted_revision == 1U && status.active_revision == 0U);
|
||||
|
|
@ -68,6 +103,7 @@ static int run(void)
|
|||
CHECK(state.failed == 0U);
|
||||
CHECK(xtc_realtime_get_status(engine, &status) == XTC_OK && status.processed_blocks > 3U);
|
||||
xtc_realtime_destroy(engine); /* Also cleans pending and retired plans. */
|
||||
CHECK(prepared == destroyed);
|
||||
xtc_graph_destroy(one); xtc_graph_destroy(two);
|
||||
for (i = 0U; i < 100U; ++i) {
|
||||
CHECK(xtc_realtime_create(48000.0, 4U, &engine) == XTC_OK);
|
||||
|
|
@ -80,6 +116,7 @@ static int run(void)
|
|||
}
|
||||
int main(void)
|
||||
{
|
||||
control_thread = pthread_self();
|
||||
CHECK(run() == 0);
|
||||
puts("Realtime handoff and concurrent replacement tests passed.");
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue