Too high latency while trying to manipulate sound arrays using sounddevice in python
<p>Few days ago, I have installed <a href="http://python-sounddevice.readthedocs.io/en/0.3.5/" rel="nofollow">a sounddevice</a> library in Python 2.7.5. I'm trying to make a sound array and add some effects to it immediately after I push a key on my MIDI controller. But I get a huge delay of 0.1 to 0.2 second which makes my code useless:</p>

<pre><code>import numpy as np
import sounddevice as sd
import time
import math

#we're making a sound array with a 5 seconds length noisy sound and playing it:
duration=5
framerate = 44100
array=0.02*np.random.uniform(-1, 1, framerate*duration)
sd.play(array, framerate)

t=time.time()
while(True):
    signal=raw_input("push ENTER to hear a beep")
    start_iter=int(framerate*(time.time()-t))
    end_iter=min(start_iter+framerate/4, len(array))

    #we're trying to change our data array and play a beep signal of 0.25 second after each ENTER press instantly
    for i in range(start_iter, end_iter):
        array[i]=0.05*math.sin(440*2*math.pi*i/44100.)
    if end_iter==len(array): break #safe exit of a process after 5 seconds has passed
</code></pre>

<p>To keep it simple, my sound array is just a noisy sound and my effect consists of a 440Hz beep. I used raw_input() here (type "input()" in Python 3.x) instead of MIDI inputs which could be possible using Pygame library. My code works but each time we press ENTER we will hear a short delay before beep signal.
Is it possible to eliminate it? If not, any other libraries allowing to play a sound stream with no delays live?</p>

<p>You can specify the desired latency with <a href="http://python-sounddevice.readthedocs.io/en/latest/#sounddevice.default.latency" rel="nofollow">sounddevice.default.latency</a>. Note however, that this is a <em>suggested</em> latency, the actual latency may be different, depending on the hardware and probably also on the host API. You can get an estimate of the actual latency with <a href="http://python-sounddevice.readthedocs.io/en/latest/#sounddevice.Stream.latency" rel="nofollow">sounddevice.Stream.latency</a>.</p>

<p>By default, the <code>sounddevice</code> module uses PortAudio's <em>high</em> latency setting in the hope to provide more robust behavior. You can switch it to PortAudio's <em>low</em> setting, or you can try whatever numeric value (in seconds) you want.</p>

<pre><code>import sounddevice as sd
sd.default.latency = 'low'
</code></pre>

<p>Alternatively, you can of course also use the <code>latency</code> argument of <code>play()</code> etc.</p>

<p>If you want to have more control over the time, you might want to write your own custom callback function. There you can use the <code>time</code> argument, and outside of the callback function you can use <a href="http://python-sounddevice.readthedocs.io/en/latest/#sounddevice.Stream.time" rel="nofollow">sounddevice.Stream.time</a>.</p>

<p>You can also try to start a stream without using the <code>callback</code> argument and then use <a href="http://python-sounddevice.readthedocs.io/en/latest/#sounddevice.Stream.write" rel="nofollow">sounddevice.Stream.write()</a> on it. I don't know what that will do to the latency, but it might be worth a try.</p>

<p>Regarding other libraries, since you seem to be using PyGame already, you might also use it for the audio output. It might or might not have a different latency.</p>

<p>BTW, I don't know if your code is thread-safe since you are manipulating the array while the callback gives the memory addresses to PortAudio. It's probably not a good idea to implement it like this.</p>

python numpy low-latency python-sounddevice