bastibe / SoundCard

A Pure-Python Real-Time Audio Library
https://soundcard.readthedocs.io
BSD 3-Clause "New" or "Revised" License
680 stars 69 forks source link

Playback latency #109

Open Lawmate opened 4 years ago

Lawmate commented 4 years ago

I am trying to play 4 channels of audio and am having issues with the time between calling the play() function and hearing sound. My code is like this:

with speakers.player(samplerate=48000, channels=[0,1,2,3], blocksize=64) as sp:
    sp.play(dataBMC)

The numpy array dataBMC has 4 columns and 48,289,920 rows, which is about 1000 seconds of audio. No matter how big the blocksize is, there is always a delay of a few seconds (around 8) between calling the function and hearing the sound.

I have used another method, where I split the numpy array into smaller chunks like so:

dataBMC = np.array_split(dataBMCFull,numChunks)
with speakers.player(samplerate=48000, channels=[0,1,2,3] ) as sp:
    for chunk in range(numChunksIntBMC):
        sp.play(dataBMC[chunk])

This way I can get nearly instant starting times, but over the course of 1000s, the audio slows down by a number of seconds, so this is no use either. I have tried various combinations of chunk sizes and values for the blocksize parameter.

I am guessing that the delay for playback is the time it takes for the 200mB+ to load into RAM, but i was wondering if there is a way to get some sort of feedback to signal that it is loaded and ready to start playing?

Thanks

bastibe commented 4 years ago

What do you mean by

the audio slows down by a number of second

Your second version should work without issue. If it doesn't, that would be a bug.

Lawmate commented 4 years ago

Thanks for the help.

I followed the code in your other post and reduced the sample size right down. I found 512 samples gave pretty reliable results. I am running it from a pretty underpowered mac mini that seems to struggle with loading up arrays much larger than that. It will insert slight gaps in the audio if the sample size is too large. They produce audible clicks and elongate the overall playback time.

Thanks

bastibe commented 4 years ago

Gaps and clicks are usually caused by your code taking too long. It is usually not related to SoundCard.

That said, you would want to split your dataBMCfull into blocksize-length chunks. numpy.array_split instead splits into chunks of equal length, but not necessarily blocksize-length, which could trip up SoundCard if you are computationally constrained.