First of all, thank you for the various suggestions. I should've explained in more detail what I'm trying to achieve.
The software I'm trying to interface with is slmodem (
https://github.com/leggewie/pkg-sl-modem), a software modem driver; I'm trying (admittedly with no practical reason other than curiosity) to adapt it to use a sound card, instead of the actual modem circuitry as the "analog interface" (for lack of a better term) so that I can make two computers talk to each other using audio signals.
The software is made of two parts, a kernel mode driver and an user mode daemon (slmodemd) which has all the DSP code; the thing that makes the software ideal for my purposes is that slmodemd can be compiled to use ALSA to interface with the hardware (since the MC97 spec treats all the audio to and from the actual modem circuitry as standard PCM audio streams like the ones to and from an AC97-compliant soundcard). I can tell it to use my soundcard (alsa hw:01,00 in my case) as the modem device, and it will happily use it, BUT the DSP code is proprietary and provided as a compiled 32-bit x86 binary blob (dsplibs.o) that is hardcoded to work at 9.6 kHz sample rate; changing the "srate" parameter in the modem structure seems to work at first, but it will refuse to generate the appropriate signals without throwing any meaningful error; I disassembled dsplibs.o and, sure enough, it checks that the rate is set to 9600 and quits if it's not.
My first thought at this point was to simply modify the code used to read and write data from the "modem" to resample the data before sending it. The relevant code is in "modem_main.c", but basically it works as follows:
- It calls snd_pcm_readi() to read all available data and put it into a buffer called inbuf (up to 2048 samples)
- It feeds inbuf to modem_process (which is part of dsplibs.o), which does its magic and writes the result in another buffer, outbuf (also 2048 bytes)
- It then calls snd_pcm_writei() to write the data to the sound card
As said before, I tried using libsamplerate to resample the data: on startup, I allocated all the needed buffers (1 for data converted to float, 1 for the resampled data, 1 for the resampled data converted back to s16_le) and initialized two SRC_DATA structures pointing to the appropriate buffers. Then, when the code calls alsa_device_write, I would just call
src_short_to_float_array to convert the data to float,
src_process to resample, then convert the data back to short, and interleave it with zeroes to turn it into a stereo stream (again, the final buffer was already allocated, I just wrote the resampled data in buffer[0], buffer[2] ecc) and finally feed it to
snd_pcm_writei. I haven't modified the read function yet, but the process would simply be the reverse.
I tried with 11025 Hz and 48000 Hz sample rates, but the problem is that I just could not push data to the sound card fast enough and ALSA would report an overrun. Part of the problem is that the modem_process function doesn't always return a full 2048 samples (output data size can vary quite a bit depending on what the code is doing) and I obviously have to wait for it to finish processing before I can write or read new data. The function itself SHOULD be quite fast (the readme states the whole thing can run on a P1 MMX @ 233 MHz and I'm running this on a Ryzen 5 3500U) but I can't seem to get it to work.
Edit: I thought that maybe the overrun was on the read side (since I didn't modify that function and it's only reading 2048 samples maximum instead of 2048*5*2) but quickly turning on debug mode it appears that it gets an xrun only on write...