0

I'm trying to use Python to 'mic-monitor', i.e., to playback the mic signal through the headphones in real-time, in addition to any other output signal from the PC.

I can accomplish this by amending my PC's playback settings, but I want to do it with Python, so that I can program a Raspberry Pi to mic-monitor my cheap headset for the PS4.

I can almost accomplish this with PyAudio or sounddevice, but there is a small but significant delay. So:

  • Is there a way to eradicate that latency with Python, for example by somehow accessing my PC's inputs more directly?
  • Otherwise, why is it not possible with Python?
  • Can I somehow configure the Raspberry Pi to mic monitor in the same way as my PC?

Sounddevice code is shown below for reference:

import sounddevice as sd
duration = 5.5  # seconds

def callback(indata, outdata, frames, time, status):
    if status:
        print(status)
    outdata[:] = indata

with sd.Stream(channels=2, callback=callback):
    sd.sleep(int(duration * 1000))
  • What latency would you like to achieve? What happens if you use that value as the `latency` argument? Did you try all relevant devices from the device list? – Matthias Nov 23 '20 at 20:40

1 Answers1

2

There will always be latency with a computer in-between. Professional audio gear is usually custom built for minimal latency (or it's just analog). To reduce latency you need to record smaller chunks at a time before sending them to the output which does introduce more processing overhead. Using smaller chunks can also at some point introduce more jitter in the signal because the inter-frame latency might not keep up with the sample rate. PortAudio is probably likely able to be configured to have a bit less latency, but you're probably getting a lot of the delay from the OS and audio drivers as well. Here's a page discussing how you can optimize the OS and audio drivers for minimal latency on a Raspberry Pi. PortAudio (the driver behind most python audio libraries), also has a discussion on audio driver latency based on your operating system.

looking at the documentation for sd.Stream, it looks like even if you specify a smaller blocksize, due to the implementation, it may make latency even worse.

There is however an option to specify an exact latency (if a particular delay is desirable) or to achieve a best effort "as fast as possible" by specifying latency = "low" This attempts to take into account the specific hardware you're using, and go as fast as possible.

Aaron
  • 10,133
  • 1
  • 24
  • 40
  • Thanks for your answer, I will have a read through that RPi documentation. I can appreciate that using the computer in-between will always result in some latency, but this is extremely minimal when I simply amend the playback options in the sound settings of my computer. Any thoughts as to why the increased latency creeps in when using the Python modules to process the mic input? – Robbie-Scotland Nov 22 '20 at 20:38
  • 1
    @Robbie-Scotland Neither PyAudio nor `sounddevice` add any latency compared to PortAudio itself. As mentioned in the answer above, you can use the `latency` parameter to suggest a latency value to be used by PortAudio. You should also make sure to keep the `blocksize` at its default value of `0`. Given the same settings, the latency will always be identical between PyAudio, `sounddevice` and PortAudio itself. – Matthias Nov 22 '20 at 20:58
  • 1
    @Robbie-Scotland regarding portaudio specifically: http://www.portaudio.com/docs/latency.html basically you'll have to figure out what your audio drivers are, and how to optimize them – Aaron Nov 22 '20 at 21:07
  • @Aaron Thank you, I have made these changes but it has not produced a noticeable effect on the latency. From what we have discussed here I suspect that using PortAudio introduces a certain unavoidable latency when it converts the digital signal to an analogue one, then back again for output. Thank you for your help. I have asked a follow up question about rerouting analogue signals: [link] (https://stackoverflow.com/questions/64964997/reroute-analogue-audio-signal-using-python) – Robbie-Scotland Nov 23 '20 at 08:44