bastibe / SoundCard

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

Choppy sound on Win10, buffersize has strange value #111

Open throni3git opened 4 years ago

throni3git commented 4 years ago

Hi, i'm trying to find a reliable library to play sound cross platform, so i stumbled upon this nice lib. It works better than PyAudio on Linux, but sadly my Win10 machines don't play nice with it.

I need to give audio snippets of a certain size to the speakers (powers of two, like 256). The audio output is choppy and i don't know how to set up the Player object. Here is some sample code:

import numpy as np
import soundcard as sc

mic = sc.default_microphone()
spk = sc.default_speaker()
print(mic)
print(spk)

block_size = 256
cosinus = np.cos(np.linspace(0, 2*np.pi, block_size, endpoint=False))
cosinus = np.tile(cosinus, (2, 1)).T

with spk.player(samplerate=48000, blocksize=block_size) as sp:
    print(sp.buffersize)
    while True:
        sp.play(cosinus * 0.1)

My system prints 1056, as sc.buffersize. The recorded loopback looks like this:

py-soundcard-win-choppy

Here are my specs:

Do you have any clue?

bastibe commented 4 years ago

Looks like your code does not provide audio data quickly enough, and stalls between plays. This can happen if your code does not get enough computation time because of tasks in the background, or because of code you haven't included in the example, or some internal thing within Windows, who knows.

It sounds like low latency is not important for your use case, so either use the top-level soundcard.play to play the entire audio signal in one call, or a much longer blocksize, maybe 4096 or thereabouts.

throni3git commented 4 years ago

Indeed i would like to process some data including convolution operations reacting as fast as possible to user input. This of course is not represented in the code example above, it's just a super basic down version of processing audio output. But even with this basic example the output has artifacts, while on Linux it works fine.

I tried to increase the block_size but even with 8192 samples there are artifacts. I even tried to create white noise with np.random.random like this, but this produces phasing artifacts:

import numpy as np
import soundcard as sc

mic = sc.default_microphone()
spk = sc.default_speaker()
print(mic)
print(spk)

block_size = 1024

with spk.player(samplerate=48000, blocksize=block_size) as sp:
    print(sp.buffersize)
    while True:
        snippet = np.random.random((block_size, 2)) * 2 - 1
        sp.play(snippet * 0.1)

Have you tested the code i provided on a Windows system? Can you please provide a basic example generating some noise or a sine tone, that definitely works on a Win10 PC? Thanks for your help :)

bastibe commented 4 years ago

At the moment, I don't have access to my Windows machine, so I can't try on my own computer. However, I have of course tested SoundCard with examples just like yours in the past and it works fine on Windows. So my hunch is that there is something peculiar about your setup, and we'd learn more about your problem once we figure out what part of your setup is causing it. Otherwise, your code example looks perfectly normal, and should work just fine. (You generate white noise with np.random.randn)

Is perhaps your sound card configured in some special way, or are you running a lot of other tasks in the background?

I will probably be able to look on my own Windows computer next week, but I don't suspect to find anything useful there. Or maybe I'm wrong, and this is a glaring bug in SoundCard. I'm not trying to assign blame to you, merely talking from experience about debugging issues like this many times.

throni3git commented 4 years ago

That would be nice. I don't see others having problems with this, so maybe it's just me ^^ I got no heavy load on my machine in the background. Realtek onboard, Yamaha AG06 and Focusrite Scarlett Solo soundcards are just configured with 48000Hz samplerate (as in the code).

bastibe commented 4 years ago

so maybe it's just me ^^

Not you, but something about your computer. I have seen audio drivers and audio hardware doing all kinds of crazy things on all platforms. Sometimes a reboot help, sometimes plugging in or out one device or another helps. It can be very frustrating.

throni3git commented 4 years ago

Do you have the opportunity to run the code above on a Windows machine by now? I'm still interested :)

bastibe commented 4 years ago

Yes, I did play some audio with SoundCard, and it behaved normally. As I said, this is probably related to some curiosity on your machine. I'm sure we can find a solution to it, but only once we figure out what that curiosity is.

throni3git commented 4 years ago

May i ask you to provide an example with blockwise processing of a defined tone (like a sine)? Edit: what configuration did you use?

bastibe commented 4 years ago

Your example code should work:

import soundcard
import numpy
with soundcard.default_speaker().player(samplerate=48000, blocksize=1024) as speaker:
   for _ in range(48): # roughly one second of audio
     speaker.play(numpy.random.randn(1024,2)*0.1)

should output plain white noise on both channels.

(Did you check that your sound card indeed has two channels?)

throni3git commented 4 years ago

Thanks. I got the default speaker <Speaker Lautsprecher (Realtek(R) Audio) (2 channels)> on my laptop. Works on Linux, has phasing on Windows. I will try on a different sound card later on.

Zeftow commented 1 year ago

Hi, I was experiencing a similar issue on my win10 machine and after a bit of digging it appears that a "Barco ClickShare" app that was running in the background was creating the issue. After shutting the app down the audio is back to playing normally. So it can indeed be a weird app in the system that creates some sort of playback delay causing the choppy sound.