How to fix buzzing sounds and pops on RG35XX Plus (possibly others) in Canada Goose

Hi folks!

I recently posted an issue about frequent buzzes/pops/farting noises that now occur after upgrading to Canada Goose when launching/exiting any game or app, which were not present in Goose. (Canada Goose - Buzzing/popping sounds)

This might not be an issue for everyone, or on all devices, but it certainly occurs on my RG35XX Plus and I suspect other similar Ambernic devices will be similarly affected.

I intended for that original issue/post to serve as a starting point for discussion for an investigation/fix, but it was immediately closed. Fair enough, I’m new here, and the first thing I do is ā€˜complain’ with an issue, which has seemingly already caused headaches! However, as this leaves me with nowhere to follow up with my workaround and proposal for a simple system-wide fix, I’m doing it in ā€œgeneralā€. Apologies if this is the wrong place for it!

I’ve done some research into what’s causing these buzzes and eliminated 99% of them (on my device at least). As xonglebongle rightly pointed out, it’s not likely we can eliminate all of them on all devices and in all software, but I think the fixes below should eliminate the worst offenders for most devices, and I think it’s worth addressing for the bread-and-butter stock applications like RetroArch.

I’ll start with a simple workaround for end users, then discuss further fixes in increasing technical detail, explain what’s going on, and how the fixes could be included in muOS (if appropriate).

A few simple config tweaks below result in a nice buzz-free and stable audio output on my RG35XX Plus, with no buzzes/popping (except at power on and power off), with minimal battery drain/performance overhead.

I’d be grateful if people with different devices and software collections could test these fixes and let me know if they work on other systems too. If so, I’ll create a Pull Request on github with the fixes and scripts required to build them into muOS.

And some of you with devices not affected by this are probably wondering WTF I’m talking about – lucky you, you can probably ignore this post, although testing anyway would be helpful if you are able to lend a hand.

Simple Partial Fix for End-Users

Change the audio sample rate in affected apps to match the muOS front-end standard rate of 48000 Hz. (The switching between playback rates is one of the main culprits causing the buzzes.)

In particular in RetroArch, which defaults to 44100 Hz in muOS. You can do this as an override per core, OR enable RetroArch Config Freedom in Config→General Settings→Advanced Settings, then save the change to your global RetroArch config file.

You can find the playback rate in RetroArch Settings→Audio→Output→Output Rate (Hz). Set it to 48000 and save your core override (or main configuration file, if you have RetroArch Config Freedom enabled.)

This will fix the buzzes that plague RetroArch launches and exits (provided your core launches within a few seconds), but other apps will still suffer if they use different playback rates (many use CD Audio at 44100 Hz as a default).

Still, if you primarily use your device for retroarch, you now no longer have to suffer the embarrassing farting noises every time you switch games! :smiley:

If your other affected apps have sample rate config setting, try setting them to 48000 too and see if that fixes things.

A Better Solution if You’re Feeling Brave

If you don’t mind editing some behind-the-scenes config files, we can lock our pipewire audio backend to 48000 Hz, so all system audio will be output at a consistent playback rate. (Pipewire will resample application audio produced at other sample rates, without locking applications to that fixed system rate.)

To do this, edit the file /opt/muos/share/conf/pipewire.conf. Change the line for ā€œdefault.clock.allowed-ratesā€ to be as follows:

    default.clock.allowed-rates = [ 48000 ]

(i.e. remove the other allowed rates, leaving only 48000)

Save, and then restart your device. This should eliminate the vast majority of buzzes in most applications and games, regardless of what sample rate they are using. For optimum sound quality and performance you should still try to stick to 48000 Hz wherever possible in apps and cores, but the difference is usually imperceptible.

A Complete Fix(?)

OK, we got pretty far, but we can do better!

The last troublesome apps will be those without audio. e.g. Dingux Commander, those which are slow to load, or stall audio in other ways. You’ll notice they emit a their fart noises a few seconds after launch, and again at exit. This is due to wireplumber shutting off idle audio paths after a few seconds, and re-enabling them when the muOS front-end restarts.

To fix this we need to tell wireplumber not to suspend when idle. Unfortunately, we can’t tell it to disable the shut off mechanism altogether (a timeout value of zero), as this doesn’t work correctly on some systems (including, as it happens, my ambernic), so we set it to a very large value instead.

This can be done with a little more work, but is easily doable if you’re confident manipulating system config files and symbolic links through a shell, e.g. the virtual terminal provided with muOS.

  • Create a new text file in /opt/muos/share/conf/wireplumber.lua
  • Give it the following contents:
rule = {
    matches = {
        {
            { "node.name", "matches", "alsa_output.*" },
        },
    },
    apply_properties = {
        ["session.suspend-timeout-seconds"] = 86400
    },
}
table.insert(alsa_monitor.rules, rule)

  • Make this file executable with: chmod ugo+x $MUOS_SHARE_DIR/conf/wireplumber.lua
  • Create a symbolic link for wireplumber that links to the file we created above with: ln -s $MUOS_SHARE_DIR/conf/wireplumber.lua /usr/share/wireplumber/main.lua.d/60-muos-wireplumber.lua
  • Restart your device.

Voila, no more farting noises! :raising_hands:

Well, there will inevitably be some when powering on the system, and shutting it down. This can likely be solved too, but these sorts of buzzes are very hardware specific, and solutions may vary between both models of device, and potentially even individual devices produced at different times. I may investigate this further if I have time, but currently I have limited access to devices, and we’re talking diminishing returns at this point I think.

So… Fixed?

I’d be grateful if others could try the above and let me know if any apps/ports, etc. misbehave. Unlike holding open a background alsa audio connection, this approach shouldn’t (in theory) cause timing issues in apps/games, because they all see what looks like an alsa device running at whatever rate they requested, and pipwire/wireplumber resamples all their audio to the system rate of 48000 Hz. But perhaps there are other improvements necessary to get pipewire working seamlessly across the board, and I’ve not checked all the possibilities. Only time and testing can tell!

Including these fixes in muOS

Should the above be deemed an acceptable solution for inclusion within muOS itself, I suggest we modify /opt/share/muos/script/system/pipewire.sh to create the wireplumber link if it doesn’t exist, and keep the muOS wireplumber.lua override code in /opt/share/muos/conf as I’ve done above. This keeps the muOS config almost entirely separate (apart from that one symlink) from the stock library config, which would seem (to my newbie eyes) to be the convention currently used by muOS, and alongside the related pipewire.conf that’s already there. The rest is just simple tweaks to existing files.

An optional nice-to-have might be a user config option to choose between fast-and-dirty resampling (less CPU), standard balanced resampling, or high quality resampling (more CPU). But tbh, these aren’t exactly hi-fi devices, and the stock resampling rate should be perfectly fine.

After making these tweaks, I think it should also be possible to remove the always-on audio channel in the muOS front-end (in golden.c if memory serves), as audio should now remain up regardless of what applications may be doing, but I haven’t tested this.

A More Detailed Explanation of Problems and Proposed Fix

The buzzes/farts/pops introduced in Canada Goose are the result of DAC hardware state changes, which occur when playback rates are changed, and when audio streams go idle/hardware is powered down. The above fixes work by minimizing such state changes and keeping all output at 48 kHz. Audio hardware isn’t supposed to make noises during such state changes, but hey, these are gaming handhelds, not professional audio equipment! We have to work with what we’ve got.

These state changes are primarily triggered by:

  • most notably: a mismatch between muOS front-end always-on audio stream playback rate (48 kHz) and the RetroArch default value (in muOS at least: 44.1 kHz)
  • other similar playback rate mismatches/changes in other apps/ports
  • idle audio streams causing sample rate drop-downs
  • audio back-end switching rates to match requested application audio rates (not necessary, and unwanted if we want a stable audio output)
  • idle audio suspending audio stream processing after a timeout of 5 s (wireplumber default) in applications with no audio, and when there are delays switching between apps or loading cores/ports, or other audio interruptions when apps are busy doing other stuff.

Although it seems muOS devs have gone to some lengths to stick to a standard audio rate of 48000 Hz in the front-end and many config files, this has not been consistently applied everywhere, so there are frequent DAC state changes during normal operation.

The above fixes work by eliminating unnecessary DAC state changes by:

  1. locking the pipewire/wireplumber output audio path to a fixed 48000 Hz, even when idle, and even when apps/games request different rates. Apps and games will still process audio at their requested rates, but pipewire will invisibly resample audio seamlessly to match the system output. So this should not affect any app that outputs audio through pipewire. If pipewire is correctly configured, it should process all audio output through ALSA, pulse, and OSS (if set up). It’s possible some ports might bypass pipewire (shouldn’t but, hey, ports are a crazy mixed bag!). I haven’t checked all the available configurations/software (I don’t have the time nor resources) so any assistance here by willing testers gratefully received!
  2. setting commonly-used applications (i.e. RetroArch+cores) to an audio playback rate 48000 Hz, consistent with other parts of the system. Not strictly necessary with the other fixes in place, but technically it will give an optimal audio path.
  3. Preventing sample rate drop-off when idle, and preventing idle shutdown. This occurs after launching an app that uses no audio, and sometimes between exiting one app and launching another as audio is dropped for brief moments.

There is potentially more we can do to further eliminate all buzzes and pops, but i) it’s quite a bit more work, and ii) the above changes are pretty easy and quick to implement and fix 99% of the buzzes and pops that occur during everyday use (on my system at least. YMMV). It also gives a handy place that devs and users can override wireplumber settings, if necessary, without having to compile anything or include a Lua interpreter with muOS.

It’s possible my proposed fixes have knock-on effects elsewhere. I can only test on my device and software setup. However, in theory, this approach should provide a consistent stable audio path for all programs running under muOS, provided their audio is routed through the standard ALSA/pipewire routing. (It’s similar to the approach used by modern Windows audio apps and Mac CoreAudio, so if we can get it configured correctly it should solve the majority of such audio annoyances.)

It’s likely this buzzing issue isn’t being experienced by everyone – it might affect only certain models or even specific manufacturing batches – or just not deemed an important enough issue – and so it might not be worth rolling into muOS itself and risk negatively affecting others with config changes. But if this post stays up, hopefully someone reading this at least gets some benefit from it if they are plagued by a farting device after upgrading to Canada Goose!

If, after testing and/or discussion, people are happy for me to go ahead, I’ll put together a Pull Request on github with my proposed fixes, when I get some more time to work on this and set up a proper dev environment instead of poking around live on my device. (Otherwise, it shouldn’t be too much work for someone who already has a proper muOS dev/build/test environment if they have the time/inclination before me.)

The effects of always-on audio on battery/performance are negligible, and having a nice quiet stable audio output would be worth it anyway. Most games/apps will be playing audio anyway, and the muOS front-end currently keep audio fired up continuously anway. Powering down the DAC is not worth the audio quality issues it causes, IMO.

Even if the fixes above aren’t adopted in muOS, I would humbly request that the default audio rate in the standard muOS config be changed back to 48000 Hz (to match the front-end always-on audio channel, and also the stock RetroArch default value), so at RetroArch least RetroArch can launch/exit silently on affected devices. Maybe there’s a good reason why this was changed, but it wasn’t clear to me when I was poking around in the commit log, or I missed it.

Hopefully the above is clear and I haven’t waffled on too much… I’m tired, and I always write too much when I’m tired… (apologies in advance for the inevitable typos/mistakes).

Anyway, hope this is useful to somebody!

guzzloid

5 Likes

The problem with those changes is the fact that a lot of different applications source different frequencies. Especially with PortMaster games (i.e. GTA 3 using the re3 engine). Frequency switching is required in those cases, and locking everything to 48 kHz can sometimes introduce subtle artefacts or increased CPU usage depending on how PipeWire handles resampling.

That said, I appreciate the level of detail you’ve put into investigating this. For most everyday use cases (particularly RetroArch and other cores), your approach of standardising to 48 kHz does make sense and would eliminate the worst of the stupid device state change noises you’re describing. The challenge for us at the system level is balancing consistency (fixed 48 kHz for clean transitions) with compatibility (allowing apps to run at their native or expected sample rates without issues).

That’s why the current setup allows multiple ā€œallowed-ratesā€ā€¦ it keeps things more flexible for edge cases. The workaround is still very valuable for users who are mostly RetroArch only focused and want quieter operation. It might make sense for us to document this as an advanced option (or even expose it as a toggle in settings, like ā€œForce 48 kHz outputā€), rather than enforcing it globally.

That way, people with affected devices can enable it, while others who need broader compatibility won’t run into unexpected side effects. If you’re still up for opening a PR, maybe it could start as a user selectable configuration path rather than a default system wide change. That would make it easier for the community to test across different devices and application, or whatever, combinations, and we’d have more confidence before considering it for defaults.

2 Likes

would be great if you add such a toggle
experiencing described behavior, but not sure if can correctly apply suggested fix…

Thanks for the reply! Yes a ā€˜force 48kHz output’ config option sounds like a great approach.

Regarding compatibility: ā€œin theoryā€, if pipewire is correctly configured most applications should be unaware that their output is being resampled, and just operate at their requested output rates. The only visible impact should be the CPU overhead of the resampling, which is pretty low.

In practice… I can see how situations might arise with tricksy timing-sensitive code, audio clock dependencies in some older games, and so on where things could get a little glitchy.

I’ll definitely take a look at GTA 3/re3 and see if I can work out what’s causing it to not play nicely with pipewire/fixed frequency. I found your earlier post where you detailed removing muspeaker, so I’ll work through that as a starting point.

Do you know of any other problematic examples I could take a look at? It would be good to examine a few, so I don’t just end up with a GTA3-specific fix. (If I can find a fix!)

For the PR, I’ll need to learn a bit more about the muOS front-end and config etc. and figure out a clean way to dynamically change the setting (unless a reboot is acceptable). I should hopefully have some more time to look into it next week.

Thanks again, and of course thanks for muOS – it’s fab!

Yeah, sorry if my instructions aren’t clear. I really shouldn’t write this stuff tired! :smiley:

If I get time at the weekend, I’ll see if I can come up with some simpler instructions, or a script of some kind to apply/remove the fix automatically. That could work as a temp fix until I can implement xonglebongle’s neater suggestion above.

This is fine I can help with this. The changes required would most likely include restarting PipeWire itself via the script ā€œserviceā€. We can start of with a simple ā€œresampleā€ and ā€œfrequencyā€ option points and go from there.

1 Like

I was experiencing farting noises on my RG35XXSP when using muOS since day one, so I tried to set the pipewire config to always use 48000 kHz as you suggested and it has worked well so far. Surprisingly, even Dingux stopped making noises when exiting, but I’ll have to use the device a little bit more to see if the issue is truly solved for me. Will keep you posted if anything comes up

1 Like

Amazing detective work. The pipewire fix worked great for me. I’m using only Retroarch cores plus ScummVM, which also worked fine.

1 Like

Thanks so much for posting this. I’ve only done the ā€œsimple partial fixā€, but as someone who uses RetroArch 99% of the time that’s probably all I need. The noises objectively aren’t a big thing, but in practice it’s sooooo nice to be rid of them! :grinning_face_with_smiling_eyes:

1 Like

I took a look at GTA3 at the weekend. With the above fixes in place, there is obvious audio lag in cutscenes, although most game timing/audio doesn’t seem to be affected.

I poked around a bit in the re3 code to see where this lag is happening, and it seems to me that the problem is not the fixed pipewire sample rate or resampling per se but that the audio in the cutscene engine in re3 is at least partially dependent on the sample playback position. There are several functions that query the playback sample offset through OpenAL when calculating time. (The rest of the engine uses a separate timer system, which is why most of the game is unaffected.)

I suspect that somewhere in the chain from re3 → OpenAL → ALSA → pipewire, buffer size differences, timing, actual hardware playback position, or something is being leaked, miscalculated, or misreported back to re3, causing drift between the main re3 clock and the audio engine.

The main animation timing is not affected, nor is the sample playback rate or audio quality once the samples/streams are triggered. There is plenty of CPU headroom for resampling, and there are no buffer underruns, so it’s not the system getting swamped. But whatever is cueing up those audio events is suffering a timing skew. The longer the cutscene plays the more skewed it gets. If you force ALSA to use tiny audio buffers, this ruins the audio quality as its constantly spamming IRQs and buffer processing, but suddenly the clock drift disappears or is much reduced, presumably as the sample playback position now more closely reflects the actual hardware playback position.

I haven’t pinned down exactly what part of re3 is most directly affected to confirm this 100%, but I suspect the problem is somewhere in the buffer processing between OpenAL and pipewire. I know back in the day the audio clock/sample position was sometimes used in preference to system clocks as it was sometimes the most reliable clock available, so I wouldn’t be surprised if there are other ports affected too, although this could also be a quirk of re3 using a mix of clocks. That’s about as far as I got so far.

Looking at the changelog and history for pipewire I note there are several entries/commits related to timing feedback, sample offsets, and tick rate calculations in newer versions of pipewire. Also, the fact that nobody else seems to be reporting this outside of muOS (even though other systems are undoubtedly using OS mixers at a fixed rate) makes me wonder if this might be related to the version of pipewire we’re using in muOS. I haven’t dug through the actual commits yet to see what was changed.

Rather than digging around in re3 and audio library code, I think the next thing I’ll do is try out a later pipewire version and see if that fixes things, and go from there.

If anyone knows of any other specific ports that have similar timing issues, I’d be grateful if you could point them out to me. A smaller or simpler codebase might allow me to more quickly figure out what’s happening.

Also, thanks for the positive feedback, everyone. I’m glad my investigations and tweaks have helped people!

This sounds great! I’d love a toggle in the Advanced section for this. I would certainly give it a shot.

1 Like

Ended up doing quite a lot of testing and went with 44.1 in the end and kept the frequency options for both 32 and 48. Most if not all squelching has disappeared except for the boot and shutdown sequences. As well as the odd PortMaster game, like re3, that wants to switch frequency.

Added to contributor list as well.

These changes will be in an upcoming 2508.2 Patch. Although people will have the option to download the full image as well.

Thank you! :slight_smile:

1 Like