36 lines
1.2 KiB
C
36 lines
1.2 KiB
C
/* 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 <alsa/asoundlib.h>
|
|
#include <dlfcn.h>
|
|
#include <errno.h>
|
|
#include <pthread.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
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;
|
|
}
|