Finally! A reliable data stream!
I decided to ditch the efforts I had given into a bit stream (i.e. infinite length packet) and tried to squeeze as much data into a stream of packets.
The packet system in the RFM69HCW allows for a packet length of 64 bytes, where 3 bytes are overhead. So this is effectively 61 bytes per packet. If I want to transmit at an audio Bandwidth of 8kHz (transmission rate of 16kBps) I need to send a packet about every 62 us.
This means that I need to send a full 64-byte packet faster than 61bytes * 62us/byte = 3782us (don't forget we need the time to load the packet into the FIFO via SPI). So, if we run the bit-rate of the transmitter at 100kbps that means we transmit 64 Bytes in 640 us. Plenty fast.
The SPI transactions now need to run as fast as possible to load the fifo in 3782us - 640us = 3142us. We have to transmit at a fast rate for this. This means overloading the base RFM69 class to run at the full SPI clock rate instead of 1/4. So if we can get the SPI running at 5MHz, we can send:
This leaves us with plenty of time (3ms) to do ADC conversions (which can be slow), read interrupts, etc. So sending 8-bit audio at a reasonable bit-rate is totally achievable.
In practice I have found that for human voice we can drop the bit rate to 10kBps. This allows us to push some of the deterministic tonal noise out of the human audible range and has no effect on Bandwidth quality.
Here's a demo for you to try yourself: https://cdn.hackaday.io/files/19700842844800/PacketStreamDemo.zip