// Harness for verify_rtp.py: opens the real HyperHDR RTP sink, points it at a // port on the loopback and writes a deterministic ramp through it. The Python // side receives the datagrams and checks that what comes out of the wire is // exactly what went in. // // rtp_send [frames-per-block] [sap] #include "../native/src/common/audio.h" #include "../native/src/common/json.h" #include "../native/src/common/log.h" #include "../native/src/dsp.h" #include "../native/src/sinks/sink.h" #include #include #include // Must match sample_at() in verify_rtp.py. static int16_t sample_at(long index) { return (int16_t)((index * 251) % 65536 - 32768); } int main(int argc, char** argv) { if (argc < 3) { fprintf(stderr, "usage: %s [frames]\n", argv[0]); return 2; } int port = atoi(argv[1]); int blocks = atoi(argv[2]); int frames = argc > 3 ? atoi(argv[3]) : AUDIO_BLOCK_FRAMES; bool sap = argc > 4 && strcmp(argv[4], "sap") == 0; log_set_level(LOG_ERROR); char cfg_text[256]; snprintf(cfg_text, sizeof(cfg_text), "{\"hyperhdr\":{\"host\":\"127.0.0.1\",\"port\":%d," "\"multicast\":false,\"sapAnnounce\":%s}}", port, sap ? "true" : "false"); json_value_t* cfg = json_parse(cfg_text); if (!cfg) { fprintf(stderr, "bad config\n"); return 1; } audio_format_t fmt = { .rate = 48000, .channels = 2 }; char err[256] = { 0 }; sink_t* sink = sink_open("hyperhdr", cfg, &fmt, err, sizeof(err)); if (!sink) { fprintf(stderr, "sink_open failed: %s\n", err); json_free(cfg); return 1; } int16_t* pcm = malloc((size_t)frames * fmt.channels * sizeof(int16_t)); dsp_levels_t levels; memset(&levels, 0, sizeof(levels)); long index = 0; for (int b = 0; b < blocks; b++) { for (int i = 0; i < frames * fmt.channels; i++) pcm[i] = sample_at(index++); sink->write(sink, pcm, frames, &levels); } printf("%ld\n", index); // samples written, for the receiver to expect fflush(stdout); free(pcm); sink_close(sink); json_free(cfg); return 0; }