diff --git a/tests/integration.c b/tests/integration.c index 4c2ba65..3b99579 100644 --- a/tests/integration.c +++ b/tests/integration.c @@ -7,6 +7,41 @@ #include #include #include +#include +#include + +/* static variables for passthrough test */ +static jack_port_t *passthrough_output_port = NULL; +static jack_port_t *passthrough_input_port = NULL; +static float passthrough_phase = 0.0f; +static float passthrough_freq = 440.0f; +static int passthrough_sample_rate = 0; +static long passthrough_total_samples = 0; +static double passthrough_sum_sq = 0.0; +static volatile int passthrough_done = 0; + +static int passthrough_process(jack_nframes_t nframes, void *arg) { + (void)arg; + jack_default_audio_sample_t *out = + (jack_default_audio_sample_t *)jack_port_get_buffer(passthrough_output_port, nframes); + jack_default_audio_sample_t *in = + (jack_default_audio_sample_t *)jack_port_get_buffer(passthrough_input_port, nframes); + if (!out || !in) return 0; + float *outf = out; + const float *inf = in; + for (jack_nframes_t i = 0; i < nframes; i++) { + float val = sinf(passthrough_phase); + outf[i] = val; + passthrough_phase += 2.0f * (float)M_PI * passthrough_freq / passthrough_sample_rate; + if (passthrough_phase > 2.0f * M_PI) passthrough_phase -= 2.0f * M_PI; + passthrough_sum_sq += (double)inf[i] * (double)inf[i]; + passthrough_total_samples++; + } + if (passthrough_total_samples >= passthrough_sample_rate * 2) { + passthrough_done = 1; + } + return 0; +} /* * Integration test for the JACK looper. @@ -173,51 +208,69 @@ static void test_clock_continue(void) { static int test_audio_pass_through(void) { printf("Test: audio pass‑through (connectivity)\n"); - - /* check required tools */ - if (system("which jack_lsp >/dev/null 2>&1") != 0) { - fprintf(stderr, " SKIP: jack_lsp not installed\n"); + jack_client_t *client; + jack_status_t status; + client = jack_client_open("test_passthrough", JackNoStartServer, &status); + if (client == NULL) { + fprintf(stderr, " SKIP: cannot open JACK client (server not running?)\n"); return 1; } - if (system("which jack_connect >/dev/null 2>&1") != 0) { - fprintf(stderr, " SKIP: jack_connect not installed\n"); + jack_port_t *output_port = jack_port_register(client, "output", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, 0); + jack_port_t *input_port = jack_port_register(client, "input", + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, 0); + if (!output_port || !input_port) { + fprintf(stderr, " FAIL: could not register ports\n"); + jack_client_close(client); return 1; } - - pid_t pid = start_looper(); - if (pid < 0) { - fprintf(stderr, "FAIL: could not start looper\n"); + usleep(200000); + const char *looper_input = "looper:input"; + const char *looper_output = "looper:output"; + char my_output[64], my_input[64]; + snprintf(my_output, sizeof(my_output), "test_passthrough:output"); + snprintf(my_input, sizeof(my_input), "test_passthrough:input"); + if (jack_connect(client, my_output, looper_input) != 0) { + fprintf(stderr, " FAIL: cannot connect test_passthrough:output -> looper:input\n"); + jack_client_close(client); return 1; } - - /* connect looper input to a dummy JACK source? No sine needed. - Instead just verify ports appear. */ - char buf[512]; - snprintf(buf, sizeof(buf), - "jack_lsp -c looper 2>/dev/null | grep -q -E '^looper:'"); - if (system(buf) != 0) { - fprintf(stderr, "FAIL: looper ports not visible\n"); - kill(pid, SIGTERM); - waitpid(pid, NULL, 0); + if (jack_connect(client, looper_output, my_input) != 0) { + fprintf(stderr, " FAIL: cannot connect looper:output -> test_passthrough:input\n"); + jack_client_close(client); return 1; } - - /* try connecting to itself (loopback) as a connectivity test */ - if (system("jack_connect looper:output looper:input 2>/dev/null") != 0) { - fprintf(stderr, "FAIL: could not connect looper:output -> looper:input\n"); - kill(pid, SIGTERM); - waitpid(pid, NULL, 0); + passthrough_output_port = output_port; + passthrough_input_port = input_port; + passthrough_phase = 0.0f; + passthrough_freq = 440.0f; + passthrough_sample_rate = jack_get_sample_rate(client); + passthrough_total_samples = 0; + passthrough_sum_sq = 0.0; + passthrough_done = 0; + jack_set_process_callback(client, passthrough_process, NULL); + if (jack_activate(client) != 0) { + fprintf(stderr, " FAIL: cannot activate client\n"); + jack_client_close(client); return 1; } - - /* wait briefly then disconnect */ - sleep(1); - system("jack_disconnect looper:output looper:input 2>/dev/null"); - - kill(pid, SIGTERM); - waitpid(pid, NULL, 0); - - printf(" PASS (connectivity established)\n"); + usleep(2200000); /* 2.2 seconds */ + int saw_input = passthrough_done; + double rms = passthrough_total_samples > 0 ? + sqrt(passthrough_sum_sq / passthrough_total_samples) : 0.0; + jack_deactivate(client); + jack_client_close(client); + if (!saw_input) { + fprintf(stderr, " FAIL: looper did not produce output (no callback run?)\n"); + return 1; + } + if (rms < 0.001) { + fprintf(stderr, " FAIL: looper output RMS too small (%.6f)\n", rms); + return 1; + } + printf(" PASS (RMS %.6f)\n", rms); return 0; }