fix: resolve duplicate main and missing includes in test_audio_routing.c
Co-authored-by: aider (deepseek/deepseek-coder) <aider@aider.chat>
This commit is contained in:
@@ -1,195 +1,21 @@
|
|||||||
/*
|
#define _GNU_SOURCE
|
||||||
* test_audio_routing.c
|
|
||||||
*
|
|
||||||
* External test program for the looper application.
|
|
||||||
* Connects to JACK, sends a test tone to the application's audio_in ports,
|
|
||||||
* captures the output from audio_out ports, and verifies that audio is flowing.
|
|
||||||
*
|
|
||||||
* Compile with:
|
|
||||||
* gcc -o test_audio_routing test_audio_routing.c -ljack -lm
|
|
||||||
*
|
|
||||||
* Run after the looper application is running and JACK is active.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <jack/jack.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define TEST_DURATION_SECONDS 2
|
|
||||||
#define SAMPLE_RATE 48000
|
|
||||||
#define NUM_CHANNELS 2 // test first two channels
|
|
||||||
|
|
||||||
static jack_client_t *client = NULL;
|
|
||||||
static jack_port_t *test_out_ports[NUM_CHANNELS];
|
|
||||||
static jack_port_t *test_in_ports[NUM_CHANNELS];
|
|
||||||
static float *captured_output[NUM_CHANNELS];
|
|
||||||
static jack_nframes_t captured_frames = 0;
|
|
||||||
static volatile int running = 1;
|
|
||||||
|
|
||||||
/* Generate a sine wave sample */
|
|
||||||
static float sine_sample(jack_nframes_t frame, float freq, float sample_rate) {
|
|
||||||
return sinf(2.0f * M_PI * freq * frame / sample_rate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process callback: generate test tone on output ports, capture input ports */
|
|
||||||
static int process(jack_nframes_t nframes, void *arg) {
|
|
||||||
(void)arg;
|
|
||||||
|
|
||||||
/* Generate test tone on each output port */
|
|
||||||
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
|
||||||
jack_default_audio_sample_t *out =
|
|
||||||
(jack_default_audio_sample_t *)jack_port_get_buffer(test_out_ports[ch], nframes);
|
|
||||||
for (jack_nframes_t i = 0; i < nframes; i++) {
|
|
||||||
/* 440 Hz sine wave, amplitude 0.5 */
|
|
||||||
out[i] = 0.5f * sine_sample(captured_frames + i, 440.0f, SAMPLE_RATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Capture input ports */
|
|
||||||
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
|
||||||
jack_default_audio_sample_t *in =
|
|
||||||
(jack_default_audio_sample_t *)jack_port_get_buffer(test_in_ports[ch], nframes);
|
|
||||||
/* Append to captured buffer */
|
|
||||||
if (captured_output[ch]) {
|
|
||||||
memcpy(captured_output[ch] + captured_frames, in, nframes * sizeof(float));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
captured_frames += nframes;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shutdown callback */
|
|
||||||
static void shutdown(void *arg) {
|
|
||||||
(void)arg;
|
|
||||||
running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
jack_status_t status;
|
|
||||||
const char *client_name = "test_audio_routing";
|
|
||||||
|
|
||||||
client = jack_client_open(client_name, JackNullOption, &status, NULL);
|
|
||||||
if (!client) {
|
|
||||||
fprintf(stderr, "Failed to open JACK client, status = 0x%2.0x\n", status);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register ports */
|
|
||||||
char port_name[64];
|
|
||||||
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
|
||||||
snprintf(port_name, sizeof(port_name), "test_out_%d", ch);
|
|
||||||
test_out_ports[ch] = jack_port_register(client, port_name,
|
|
||||||
JACK_DEFAULT_AUDIO_TYPE,
|
|
||||||
JackPortIsOutput, 0);
|
|
||||||
if (!test_out_ports[ch]) {
|
|
||||||
fprintf(stderr, "Failed to register output port %d\n", ch);
|
|
||||||
jack_client_close(client);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(port_name, sizeof(port_name), "test_in_%d", ch);
|
|
||||||
test_in_ports[ch] = jack_port_register(client, port_name,
|
|
||||||
JACK_DEFAULT_AUDIO_TYPE,
|
|
||||||
JackPortIsInput, 0);
|
|
||||||
if (!test_in_ports[ch]) {
|
|
||||||
fprintf(stderr, "Failed to register input port %d\n", ch);
|
|
||||||
jack_client_close(client);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set process callback */
|
|
||||||
jack_set_process_callback(client, process, NULL);
|
|
||||||
jack_on_shutdown(client, shutdown, NULL);
|
|
||||||
|
|
||||||
/* Allocate capture buffers */
|
|
||||||
jack_nframes_t sample_rate = jack_get_sample_rate(client);
|
|
||||||
jack_nframes_t total_frames = sample_rate * TEST_DURATION_SECONDS;
|
|
||||||
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
|
||||||
captured_output[ch] = (float *)calloc(total_frames, sizeof(float));
|
|
||||||
if (!captured_output[ch]) {
|
|
||||||
fprintf(stderr, "Memory allocation failed\n");
|
|
||||||
jack_client_close(client);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Activate client */
|
|
||||||
if (jack_activate(client) != 0) {
|
|
||||||
fprintf(stderr, "Failed to activate JACK client\n");
|
|
||||||
jack_client_close(client);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Connect to the looper application's ports */
|
|
||||||
const char *app_client_name = "looper"; /* adjust if your app uses a different name */
|
|
||||||
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
|
||||||
char src_port[128], dst_port[128];
|
|
||||||
snprintf(src_port, sizeof(src_port), "%s:test_out_%d", client_name, ch);
|
|
||||||
snprintf(dst_port, sizeof(dst_port), "%s:audio_in_%d", app_client_name, ch);
|
|
||||||
if (jack_connect(client, src_port, dst_port) != 0) {
|
|
||||||
fprintf(stderr, "Warning: could not connect %s -> %s\n", src_port, dst_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(src_port, sizeof(src_port), "%s:audio_out_%d", app_client_name, ch);
|
|
||||||
snprintf(dst_port, sizeof(dst_port), "%s:test_in_%d", client_name, ch);
|
|
||||||
if (jack_connect(client, src_port, dst_port) != 0) {
|
|
||||||
fprintf(stderr, "Warning: could not connect %s -> %s\n", src_port, dst_port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Run for the test duration */
|
|
||||||
printf("Running test for %d seconds...\n", TEST_DURATION_SECONDS);
|
|
||||||
sleep(TEST_DURATION_SECONDS);
|
|
||||||
|
|
||||||
/* Deactivate and close */
|
|
||||||
jack_deactivate(client);
|
|
||||||
jack_client_close(client);
|
|
||||||
|
|
||||||
/* Analyze captured output */
|
|
||||||
int pass = 1;
|
|
||||||
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
|
||||||
float max_val = 0.0f;
|
|
||||||
for (jack_nframes_t i = 0; i < total_frames; i++) {
|
|
||||||
float abs_val = fabsf(captured_output[ch][i]);
|
|
||||||
if (abs_val > max_val) max_val = abs_val;
|
|
||||||
}
|
|
||||||
printf("Channel %d: max output amplitude = %f\n", ch, max_val);
|
|
||||||
if (max_val < 0.001f) {
|
|
||||||
printf("FAIL: Channel %d output is near zero (no audio flowing)\n", ch);
|
|
||||||
pass = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cleanup */
|
|
||||||
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
|
||||||
free(captured_output[ch]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pass) {
|
|
||||||
printf("PASS: Audio routing is working correctly.\n");
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
printf("FAIL: Audio routing test failed.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <jack/jack.h>
|
#include <jack/jack.h>
|
||||||
#include <jack/midiport.h>
|
#include <jack/midiport.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
|
|
||||||
// Test configuration
|
// Test configuration
|
||||||
#define TEST_SAMPLE_RATE 48000
|
#define TEST_SAMPLE_RATE 48000
|
||||||
#define TEST_NFRAMES 1024
|
#define TEST_NFRAMES 1024
|
||||||
|
|||||||
Reference in New Issue
Block a user