xtc/tests/unit/test_graph_edits.c

83 lines
5 KiB
C
Raw Normal View History

#include "xtc/xtc_engine.h"
#include <math.h>
#include <stdio.h>
#define CHECK(c) do { if (!(c)) { fprintf(stderr,"FAIL %s:%d: %s\n",__FILE__,__LINE__,#c); return 1; } } while (0)
static xtc_result apply(xtc_graph **graph, xtc_graph_edit *edit, size_t *id)
{
xtc_graph *candidate = NULL;
xtc_result result = xtc_graph_apply_edit(*graph, edit, &candidate, id);
if (result == XTC_OK) { xtc_graph_destroy(*graph); *graph = candidate; }
return result;
}
int main(void)
{
xtc_graph *graph = NULL, *candidate = NULL;
xtc_plan *old = NULL, *fresh = NULL;
xtc_graph_edit edit = {0};
xtc_node_info info;
xtc_connection_info connection;
size_t osc, gain, meter, output, added = 77U, nodes, edges;
float samples[4] = {9,9,9,9}, peak;
CHECK(xtc_graph_create(8U, &graph) == XTC_OK);
CHECK(xtc_graph_require_output_nodes(graph, 2) == XTC_ERR_INVALID_ARGUMENT);
CHECK(xtc_graph_require_output_nodes(graph, 1) == XTC_OK);
CHECK(xtc_graph_compile(graph, 48000.0, 4U, &fresh) == XTC_OK);
CHECK(xtc_plan_process(fresh, NULL, samples, 4U) == XTC_OK && samples[0] == 0.0f && samples[3] == 0.0f);
xtc_plan_destroy(fresh);
edit.kind = XTC_EDIT_ADD_NODE; edit.data.add.type = XTC_NODE_OSCILLATOR; edit.data.add.value = 12000.0f;
CHECK(apply(&graph, &edit, &osc) == XTC_OK);
CHECK(xtc_graph_compile(graph, 48000.0, 4U, &fresh) == XTC_OK);
CHECK(xtc_plan_process(fresh, NULL, samples, 4U) == XTC_OK && samples[1] == 0.0f); /* No output. */
xtc_plan_destroy(fresh);
edit.data.add.type = XTC_NODE_GAIN; edit.data.add.value = 0.25f;
CHECK(apply(&graph, &edit, &gain) == XTC_OK);
edit.data.add.type = XTC_NODE_METER;
CHECK(apply(&graph, &edit, &meter) == XTC_OK);
edit.data.add.type = XTC_NODE_OUTPUT;
CHECK(apply(&graph, &edit, &output) == XTC_OK);
edit.kind = XTC_EDIT_CONNECT;
edit.data.connection = (xtc_connection_info){osc, 1U, gain, 0U};
CHECK(apply(&graph, &edit, NULL) == XTC_OK);
edit.data.connection = (xtc_connection_info){gain, 1U, meter, 0U};
CHECK(apply(&graph, &edit, NULL) == XTC_OK);
edit.data.connection = (xtc_connection_info){meter, 1U, output, 0U};
CHECK(apply(&graph, &edit, NULL) == XTC_OK);
CHECK(xtc_graph_get_connection(graph, 2U, &connection) == XTC_OK && connection.source_node == meter && connection.destination_node == output);
CHECK(xtc_graph_compile(graph, 48000.0, 4U, &old) == XTC_OK);
edit.data.connection = (xtc_connection_info){meter, 1U, gain, 0U};
CHECK(xtc_graph_apply_edit(graph, &edit, &candidate, &added) == XTC_ERR_GRAPH_CYCLE && candidate == NULL && added == 77U);
CHECK(xtc_graph_get_counts(graph, &nodes, &edges) == XTC_OK && nodes == 4U && edges == 3U);
edit.data.connection = (xtc_connection_info){gain, 0U, meter, 0U};
CHECK(apply(&graph, &edit, NULL) == XTC_ERR_INVALID_ARGUMENT);
edit.kind = XTC_EDIT_REMOVE_NODE; edit.data.node_id = gain;
CHECK(apply(&graph, &edit, NULL) == XTC_OK);
CHECK(xtc_graph_get_counts(graph, &nodes, &edges) == XTC_OK && nodes == 3U && edges == 1U);
CHECK(xtc_graph_get_node(graph, 1U, &info) == XTC_OK && info.id == meter && info.type == XTC_NODE_METER);
CHECK(xtc_graph_get_connection(graph, 0U, &connection) == XTC_OK && connection.source_node == meter);
edit.kind = XTC_EDIT_CONNECT; edit.data.connection = (xtc_connection_info){osc, 1U, meter, 0U};
CHECK(apply(&graph, &edit, NULL) == XTC_OK);
CHECK(xtc_graph_compile(graph, 48000.0, 4U, &fresh) == XTC_OK);
CHECK(xtc_plan_process(old, NULL, samples, 4U) == XTC_OK && fabsf(samples[1] - 0.25f) < 0.00001f);
CHECK(xtc_plan_process(fresh, NULL, samples, 4U) == XTC_OK && fabsf(samples[1] - 1.0f) < 0.00001f);
CHECK(xtc_plan_meter_peak(fresh, meter, &peak) == XTC_OK && fabsf(peak - 1.0f) < 0.00001f);
xtc_plan_destroy(old); xtc_plan_destroy(fresh);
edit.kind = XTC_EDIT_DISCONNECT;
CHECK(apply(&graph, &edit, NULL) == XTC_OK);
CHECK(apply(&graph, &edit, NULL) == XTC_ERR_NOT_FOUND);
edit.kind = XTC_EDIT_ADD_NODE; edit.data.add.type = XTC_NODE_GAIN; edit.data.add.value = NAN;
CHECK(apply(&graph, &edit, &added) == XTC_ERR_INVALID_ARGUMENT && added == 77U);
edit.data.add.value = 2.0f;
CHECK(apply(&graph, &edit, &added) == XTC_OK && added > output); /* Never reuse gain's ID. */
edit.kind = XTC_EDIT_REMOVE_NODE; edit.data.node_id = gain;
CHECK(apply(&graph, &edit, NULL) == XTC_ERR_NOT_FOUND);
edit.kind = (xtc_graph_edit_kind)999;
CHECK(apply(&graph, &edit, NULL) == XTC_ERR_INVALID_ARGUMENT);
edit.kind = XTC_EDIT_ADD_NODE; edit.data.add.type = (xtc_node_type)999;
CHECK(apply(&graph, &edit, NULL) == XTC_ERR_INVALID_ARGUMENT);
CHECK(xtc_graph_get_node(graph, SIZE_MAX, &info) == XTC_ERR_NOT_FOUND);
CHECK(xtc_graph_get_connection(graph, SIZE_MAX, &connection) == XTC_ERR_NOT_FOUND);
CHECK(xtc_graph_apply_edit(NULL, &edit, &candidate, NULL) == XTC_ERR_INVALID_ARGUMENT && candidate == NULL);
xtc_graph_destroy(graph);
puts("Transactional graph edits, stable IDs, snapshots and rendering passed.");
return 0;
}