110 lines
4.9 KiB
C
110 lines
4.9 KiB
C
#define _POSIX_C_SOURCE 200809L
|
|
/* Offline workload timing, not hardware or hard realtime qualification. */
|
|
#include "xtc/xtc_midi.h"
|
|
#include "xtc/xtc_mixer.h"
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#define REQUIRE(c) \
|
|
do { \
|
|
if (!(c)) { \
|
|
fprintf(stderr, "FAIL %s:%d: %s\n", __FILE__, __LINE__, #c); \
|
|
goto cleanup; \
|
|
} \
|
|
} while (0)
|
|
static double now(void)
|
|
{
|
|
struct timespec t;
|
|
clock_gettime(CLOCK_MONOTONIC, &t);
|
|
return (double)t.tv_sec + (double)t.tv_nsec / 1e9;
|
|
}
|
|
static int compare(const void *left, const void *right)
|
|
{
|
|
double a = *(const double *)left, b = *(const double *)right;
|
|
return a < b ? -1 : a > b;
|
|
}
|
|
int main(int argc, char **argv)
|
|
{
|
|
xtc_project *project = NULL;
|
|
xtc_graph *graph = NULL;
|
|
xtc_plan *plan = NULL;
|
|
xtc_midi_plan *midi = NULL;
|
|
long blocks = 2000;
|
|
char *end;
|
|
size_t i, j, source, previous, node;
|
|
uint64_t track, clip, note, future;
|
|
float left[128], right[128], out_left[128], out_right[128];
|
|
double *times = NULL, total = 0, begin, prepare_ms;
|
|
int result = EXIT_FAILURE;
|
|
if (argc > 2)
|
|
return EXIT_FAILURE;
|
|
if (argc == 2) {
|
|
blocks = strtol(argv[1], &end, 10);
|
|
if (!*argv[1] || *end || blocks < 1 || blocks > 100000)
|
|
return EXIT_FAILURE;
|
|
}
|
|
times = calloc((size_t)blocks, sizeof(*times));
|
|
REQUIRE(times);
|
|
begin = now();
|
|
REQUIRE(xtc_project_create(&project) == XTC_OK);
|
|
for (i = 0; i < 16; ++i) {
|
|
xtc_automation_point point;
|
|
REQUIRE(xtc_project_add_track(project, "Performance", &track) == XTC_OK);
|
|
REQUIRE(xtc_project_add_midi_clip(project, track, 0, 384000, &clip) == XTC_OK);
|
|
REQUIRE(xtc_project_set_mix(project, track, 0.1f, i % 2 ? 0.5f : -0.5f, 0, 0) == XTC_OK);
|
|
for (j = 0; j < 2; ++j)
|
|
REQUIRE(xtc_project_add_note(project, clip, 0, 384000, 48 + (unsigned int)i, 100, 0,
|
|
¬e) == XTC_OK);
|
|
point = (xtc_automation_point){track, 0, XTC_AUTOMATION_GAIN, 0.1f};
|
|
REQUIRE(xtc_project_set_automation(project, &point) == XTC_OK);
|
|
point.tick = 384000;
|
|
point.value = 0.2f;
|
|
REQUIRE(xtc_project_set_automation(project, &point) == XTC_OK);
|
|
}
|
|
REQUIRE(xtc_project_add_midi_clip(project, track, 1000000, 10000, &future) == XTC_OK);
|
|
for (i = 32; i < XTC_PROJECT_MAX_NOTES; ++i)
|
|
REQUIRE(xtc_project_add_note(project, future, (i - 32) * 2, 1, 60, 100, 0, ¬e) ==
|
|
XTC_OK);
|
|
REQUIRE(xtc_graph_create(64, &graph) == XTC_OK &&
|
|
xtc_graph_add_instrument(graph, &source) == XTC_OK);
|
|
previous = source;
|
|
for (i = 0; i < 61; ++i) {
|
|
REQUIRE(xtc_graph_add_gain(graph, 0.99f, &node) == XTC_OK &&
|
|
xtc_graph_connect(graph, previous, node) == XTC_OK);
|
|
previous = node;
|
|
}
|
|
REQUIRE(xtc_graph_add_meter(graph, &node) == XTC_OK &&
|
|
xtc_graph_connect(graph, previous, node) == XTC_OK);
|
|
previous = node;
|
|
REQUIRE(xtc_graph_add_output(graph, &node) == XTC_OK &&
|
|
xtc_graph_connect(graph, previous, node) == XTC_OK);
|
|
REQUIRE(xtc_graph_compile(graph, 48000, 128, &plan) == XTC_OK &&
|
|
xtc_midi_plan_create(project, 48000, &midi) == XTC_OK);
|
|
prepare_ms = (now() - begin) * 1000;
|
|
for (i = 0; i < (size_t)blocks; ++i) {
|
|
begin = now();
|
|
REQUIRE(xtc_midi_plan_render_stereo(midi, i * 128, NULL, 0, left, right, 128) == XTC_OK);
|
|
REQUIRE(xtc_plan_process_stereo(plan, NULL, NULL, NULL, left, right, out_left, out_right,
|
|
128) == XTC_OK);
|
|
times[i] = now() - begin;
|
|
total += times[i];
|
|
for (j = 0; j < 128; ++j)
|
|
REQUIRE(isfinite(out_left[j]) && isfinite(out_right[j]));
|
|
}
|
|
qsort(times, (size_t)blocks, sizeof(*times), compare);
|
|
printf("Offline 48kHz/128, 64 nodes, 4096 notes (32 active), 16 automated tracks; %ld blocks\n",
|
|
blocks);
|
|
printf("Prepare %.3f ms; block mean %.3f us, p99 %.3f us, max %.3f us; deadline 2666.667 us; "
|
|
"CPU/audio %.4f\n",
|
|
prepare_ms, total / (double)blocks * 1e6, times[(size_t)blocks * 99 / 100] * 1e6,
|
|
times[blocks - 1] * 1e6, total / ((double)blocks * 128 / 48000));
|
|
result = EXIT_SUCCESS;
|
|
cleanup:
|
|
free(times);
|
|
xtc_midi_plan_destroy(midi);
|
|
xtc_plan_destroy(plan);
|
|
xtc_graph_destroy(graph);
|
|
xtc_project_destroy(project);
|
|
return result;
|
|
}
|