/* Copyright (c) 2026 Storm Dragon * SPDX-License-Identifier: GPL-3.0-or-later * Test-only preload for cninjam configured with ALSA null input/output at 48kHz. * Null capture is not clocked and need not initialize its buffer. Supply silence * and real-time pacing without accessing a microphone or playback device. */ #define _GNU_SOURCE #include #include #include #include #include #include static pthread_once_t readOnce = PTHREAD_ONCE_INIT; static snd_pcm_sframes_t (*realRead)(snd_pcm_t *, void *, snd_pcm_uframes_t); static void resolve_read(void) { *(void **)(&realRead) = dlsym(RTLD_NEXT, "snd_pcm_readi"); } snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t frames) { pthread_once(&readOnce, resolve_read); if (!realRead) return -ENOSYS; snd_pcm_sframes_t count = realRead(pcm, buffer, frames); if (count > 0) { memset(buffer, 0, snd_pcm_frames_to_bytes(pcm, count)); struct timespec delay = { .tv_sec = count / 48000, .tv_nsec = (count % 48000) * 1000000000LL / 48000, }; while (nanosleep(&delay, &delay) < 0 && errno == EINTR) {} } return count; }