[GH-ISSUE #235] Sound Is Cracking When CPU Is Under Load #172

Open
opened 2026-02-28 14:31:08 +03:00 by kerem · 7 comments
Owner

Originally created by @ghost on GitHub (Dec 18, 2021).
Original GitHub issue: https://github.com/jpochyla/psst/issues/235

Describe the bug
Sound is cracking when computer is under load.

To Reproduce
Spin up some heavy load.

Expected behavior
Sound should not be cracking.

Screenshots
Not applicable.

Environment

  • OS: Windows 10 Pro
  • Version: 10.0.19043 Build 19043

Additional context
Solution: Start psst with higher priority automatically. This has proven to work in the past couple days I've used psst.
Probable enchancement: Make the audio buffer larger. I guess this might help. Not sure though.

Originally created by @ghost on GitHub (Dec 18, 2021). Original GitHub issue: https://github.com/jpochyla/psst/issues/235 **Describe the bug** Sound is cracking when computer is under load. **To Reproduce** Spin up some heavy load. **Expected behavior** Sound should not be cracking. **Screenshots** Not applicable. **Environment** - OS: Windows 10 Pro - Version: 10.0.19043 Build 19043 **Additional context** Solution: Start psst with higher priority automatically. This has proven to work in the past couple days I've used psst. Probable enchancement: Make the audio buffer larger. I guess this might help. Not sure though.
Author
Owner

@jpochyla commented on GitHub (Dec 21, 2021):

Yes I've noticed this as well. We use audio buffer of 128KB, but I guess that increasing this would just help with some short spikes? There's also a couple of crates for raising the thread priority.

<!-- gh-comment-id:999050912 --> @jpochyla commented on GitHub (Dec 21, 2021): Yes I've noticed this as well. We use audio buffer of 128KB, but I guess that increasing this would just help with some short spikes? There's also a couple of crates for raising the thread priority.
Author
Owner

@jpochyla commented on GitHub (Dec 21, 2021):

@myphs can you try the latest master please?

<!-- gh-comment-id:999086174 --> @jpochyla commented on GitHub (Dec 21, 2021): @myphs can you try the latest master please?
Author
Owner

@ghost commented on GitHub (Dec 22, 2021):

I just tried and it still was cracking.

<!-- gh-comment-id:999706259 --> @ghost commented on GitHub (Dec 22, 2021): I just tried and it still was cracking.
Author
Owner

@ghost commented on GitHub (Dec 30, 2021):

Ok, I "fixed" this.
It was an issue with my mouse and my headset, which were both connected via USB 3. When I moved the mouse the sound started crackling.
I didn't realize this earlier, but it happens with other software, too. It just happend, that I switched USB ports for my mouse and headset just after I got psst and I was listening to music via psst when doing CPU intensive work. But just a few minutes ago I listened music with foobar2000 and it happened, too, for some reason. Of course it would never happen, when I was watching movies, because I wouldn't move the mouse.
So.
When both, mouse and headset, are connected to USB 3 on my docking station, the bandwidth is apparently diminished as such, that the USB soundcard for my headset won't get enough data and hence the crackling sound.
Connecting the mouse to a USB 2 port instead fixed the issue, because afaik USB 2 and 3 use different controllers.

<!-- gh-comment-id:1003202264 --> @ghost commented on GitHub (Dec 30, 2021): Ok, I "fixed" this. It was an issue with my mouse and my headset, which were both connected via USB 3. When I moved the mouse the sound started crackling. I didn't realize this earlier, but it happens with other software, too. It just happend, that I switched USB ports for my mouse and headset just after I got psst and I was listening to music via psst when doing CPU intensive work. But just a few minutes ago I listened music with foobar2000 and it happened, too, for some reason. Of course it would never happen, when I was watching movies, because I wouldn't move the mouse. So. When both, mouse and headset, are connected to USB 3 on my docking station, the bandwidth is apparently diminished as such, that the USB soundcard for my headset won't get enough data and hence the crackling sound. Connecting the mouse to a USB 2 port instead fixed the issue, because afaik USB 2 and 3 use different controllers.
Author
Owner

@jpochyla commented on GitHub (Dec 31, 2021):

Haha, wow 😅 Happy you worked it out and thanks for letting me know!

<!-- gh-comment-id:1003365232 --> @jpochyla commented on GitHub (Dec 31, 2021): Haha, wow 😅 Happy you worked it out and thanks for letting me know!
Author
Owner

@ghost commented on GitHub (Jan 6, 2022):

Sadly I have to reopen this because apparently it's both: the mouse but also when under load (or something else? 🤔).

The crackling happens when I e. g. open up a few tabs in Firefox at the same time.
Zero crackling with Foobar2000.
Also I ran a stress test assuming the crackling should be constant and actually it wasn't that bad but still happening every few seconds.

When setting the priority in Task Manager to 'higher than normal' it's working fine no matter what.

<!-- gh-comment-id:1006583510 --> @ghost commented on GitHub (Jan 6, 2022): Sadly I have to reopen this because apparently it's both: the mouse but also when under load (or something else? 🤔). The crackling happens when I e. g. open up a few tabs in Firefox at the same time. Zero crackling with Foobar2000. Also I ran a stress test assuming the crackling should be constant and actually it wasn't that bad but still happening every few seconds. When setting the priority in Task Manager to 'higher than normal' it's working fine no matter what.
Author
Owner

@alcore commented on GitHub (Mar 7, 2022):

For the record, the issue lies in cpal, which does not set a high/real-time priority on its playback thread on Windows.
(Was part of the reason why I decided to drop cpal in my projects and roll my own)

A possible fix using the winapi crate looks roughly like this:

use winapi::um::processthreadsapi::{
    GetCurrentProcessorNumber, GetCurrentThread, SetThreadIdealProcessor, SetThreadPriority,
};
use winapi::um::winbase;

// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadpriority
#[repr(u32)]
pub enum Priority {
    // BackgroundModeBegin = winbase::THREAD_MODE_BACKGROUND_BEGIN,
    // BackgroundModeEnd   = winbase::THREAD_MODE_BACKGROUND_END,
    //
    // Idle         = winbase::THREAD_PRIORITY_IDLE,
    // Lowest       = winbase::THREAD_PRIORITY_LOWEST,
    // BelowNormal  = winbase::THREAD_PRIORITY_BELOW_NORMAL,
    // Normal       = winbase::THREAD_PRIORITY_NORMAL,
    // AboveNormal  = winbase::THREAD_PRIORITY_ABOVE_NORMAL,
    // Highest      = winbase::THREAD_PRIORITY_HIGHEST,
    TimeCritical = winbase::THREAD_PRIORITY_TIME_CRITICAL,
}

pub fn pin(priority: Priority) {
    unsafe {
        let cpu = GetCurrentProcessorNumber();
        let thread = GetCurrentThread();

        SetThreadIdealProcessor(thread, cpu);
        SetThreadPriority(thread, priority as i32);
    }
}

But I'm fairly certain that needs to be applied in cpal which does not give its user ownership over the actual thread. A hackaround would be to invoke that (once) in the buffer filling callback you give to cpal - since that's run in the relevant thread - but that's obviously far from optimal.

<!-- gh-comment-id:1060659789 --> @alcore commented on GitHub (Mar 7, 2022): For the record, the issue lies in `cpal`, which does not set a high/real-time priority on its playback thread on Windows. (Was part of the reason why I decided to drop cpal in my projects and roll my own) A possible fix using the `winapi` crate looks roughly like this: ```rust use winapi::um::processthreadsapi::{ GetCurrentProcessorNumber, GetCurrentThread, SetThreadIdealProcessor, SetThreadPriority, }; use winapi::um::winbase; // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadpriority #[repr(u32)] pub enum Priority { // BackgroundModeBegin = winbase::THREAD_MODE_BACKGROUND_BEGIN, // BackgroundModeEnd = winbase::THREAD_MODE_BACKGROUND_END, // // Idle = winbase::THREAD_PRIORITY_IDLE, // Lowest = winbase::THREAD_PRIORITY_LOWEST, // BelowNormal = winbase::THREAD_PRIORITY_BELOW_NORMAL, // Normal = winbase::THREAD_PRIORITY_NORMAL, // AboveNormal = winbase::THREAD_PRIORITY_ABOVE_NORMAL, // Highest = winbase::THREAD_PRIORITY_HIGHEST, TimeCritical = winbase::THREAD_PRIORITY_TIME_CRITICAL, } pub fn pin(priority: Priority) { unsafe { let cpu = GetCurrentProcessorNumber(); let thread = GetCurrentThread(); SetThreadIdealProcessor(thread, cpu); SetThreadPriority(thread, priority as i32); } } ``` But I'm fairly certain that needs to be applied in `cpal` which does not give its user ownership over the actual thread. A hackaround would be to invoke that (once) in the buffer filling callback you give to `cpal` - since that's run in the relevant thread - but that's obviously far from optimal.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/psst#172
No description provided.