davidjo / snd_hda_macbookpro

Kernel audio driver for Macs with 8409 HDA chip + MAX98706/SSM3515 amps
GNU General Public License v2.0
286 stars 61 forks source link

Blown out "pop" sound everytime a new sound comes from any app #109

Open AbrahamR176 opened 11 months ago

AbrahamR176 commented 11 months ago

Installed on Arch, Kernel 6.6.2. Every time a new audio source plays a sound (ex. tabbing on terminal, discord opening, youtube video), there is a "pop" sound in a significantly higher volume.

Specs: Imac 19,1 CPU: i5-9600K GPU: RX 580X

AbrahamR176 commented 11 months ago

To add further context, the sound is roughly 1/10 of a second long or so, and it seems like it happens whenever a new source shows up on "pw-top". I also use pipewire.

davidjo commented 11 months ago

Im not surprised - I discovered some strange stuff in the way OSX drives the speakers/headphones - often OSX sets up to play, then unsets to play, then redoes the setup to play (which I mainly ignored). Currently Im assuming this may be some attempt to clear buffer remnants. As all this is completely opaque its difficult to figure what really needs to be done (strangely the cs408_xx.inf file found on the Bootcamp CD which Windows uses to drive the audio system doesnt seem to do this double setup - it seems to have a simple turn on amps/turn off amps for speakers at least). Also its not clear what the higher level audio is doing on OSX (CoreAudio) - it could be turning down volume before sources switch etc. and Im totally unclear as to what the linux sound drivers do on source changes. Did you have it working with pulse audio? Just wondering if theres been a change behaviour between pulse audio and pipewire (when I started there was only pulse audio on Ubuntu). If you get sound on the terminal does the pop happen between terminal sounds with no intervening audio switch?

Im guessing theres at least a few buffering points, buffering from the audio source to the PCI bus, buffering in the 8409 chip for the bus transformation from PCI bus to TDM for the I2c bus then buffering on the amps themselves (for speakers).

AbrahamR176 commented 11 months ago

I get a pop sound from any source, including the terminal. That being said it only happens when the source is created and thats why I pointed out pw-top, since it looks like when the audio source takes some time off, it just disappears entirely. So if I start a youtube video it will only pop once and work perfectly right after that. Same with the terminal, it will pop once and then play the sound as many times just fine as long as I don't let that audio source dissapear.

Yesterday night I also tested some other scenarios just to see how it would work, and I played a youtube video whilst also tying to open a game. The resulting audio is straight up nightmare fuel, if you are interested on listening to it I can send the recording here.

As for trying with vanilla pulseaudio, I haven't tried just yet, but I will put that on the list of things to try. I also was going to try using debian bookworm LTS instead to see if kernel 6.1 makes it work better.

davidjo commented 11 months ago

I dont know pw-top - only just started using pure pipewire Ubuntu versions.

So it does seem as though once the initial terminal sound goes, new sounds dont cause a pop - suggesting it is something to do with changing audio streams.

I have no idea how the linux higher level driver handles multiple streams - in particular if different formats are being used - each stream has to be transformed then the two streams mixed together.

Just had a thought - Im now wondering if its something to do maybe with audio transformations. The Apple audio system only accepts one audio format, 44.1 kHz, 24 bit (!!!) (although its actually 32 bit (has to be for the PCI stream as I understand it) so the 24 bits just mapped into the 32 bits - no scaling). I rely on the higher level linux audio driver to transform the various input formats to this single format (this happens automatically for the plughw device). Maybe theres some buffering issue when the transform has to switch - but is this at the pipewire level or the ALSA level??

The test would be to try and create two different high level audio sources but give them audio in the correct format (S32_LE) and see what happens if you switch between the sources.

But this is way beyond my knowledge of the linux audio system.

AbrahamR176 commented 11 months ago

Yeah this is far beyond me as well, I will try installing Debian and test pipe/pulse to see what performs best.

Yesterday I also realise that pipewise is suing the F32LE format instead of S24 or S32, I thought that was an issue, and I also made sure the sample rate was 44100 since it was at 48000 which I believed would have caused issues, yet nothing seemed to remove the pop from the audio.

davidjo commented 11 months ago

My testing was done with aplay - aplay needs a .wav file. Now just using aplay file.wav uses the current sound device plus the volume controls work. aplay -D plughw uses the direct plughw device - this will skip any pulse/pipewire but can convert formats. BE CAREFUL - the volume control does NOT work - but it seems like it uses the last volume setting. aplay -D hw uses the direct hardware device - no format conversion and NO VOLUME CONTROL AT ALL so will be loud. (see the 2 test audio waveforms under tests for a sample one full volume, one scaled by -24 dB). I use audacity to scale (if wanted) and convert to wav - you can also play directly from audacity.

On my macbook pro there are no pops using this method - Id be curious as to what you find.

AbrahamR176 commented 10 months ago

Pardon for taking so long to respond, while trying to install new ssd on my imac, I broke the display cable and I had to wait for post-thanksgiving amazon delivery to get a replacement.

I installed a fresh copy of Debian with the 6.1.0-13 kernel, and the exact same issue persists in the exact same way. A loud beep for every audio source that starts.

davidjo commented 10 months ago

Try using aplay and see what happens.

My suspicion is its to do with switching sound sources - as Ive noted there are a lot of HDA verbs sent to start/stop sound under OSX (but not apparently using the Windows coding - but the Windows coding seems to be completely independent of the OSX coding - the setup commands seem to be completely different).

Ive not tracked exactly what happens when sources are switched - if you look at the coding you can see the functions cs_8409_play_real and cs_8409_playstop_real - these are functions which are called to start/stop streaming. Might want to activate the logging prints for these functions and see what is being sent when you switch sources - just add some printks at the beginning and end of these functions rather than activating all the debug prints - Id be looking for overlap between the stop stream end of function and the start stream start of function. (Im assuming you are just using speakers here).

What may be happening is that the higher level can send the start streaming before the hda verbs to stop streaming have finished and apparently this isnt locked by the linux kernel ie both sets of HDA verbs can be sent which obviously messes things up (Im assuming under OSX the OSX kernel does do locking so only one set of HDA verbs is being sent at a time). (This was a big problem with headphone plugin while streaming so implemented a quick and dirty blocking protocol - unfortunately I dont really understand the linux kernel locking mechanisms but know I didnt want to hard lock the kernel ie prevent the kernel from doing anything while waiting).

(Ive noticed that the new cs8409 module for Dell laptops does include some locking which may be the way to solve these issues - but getting locking right is a big pain).

AbrahamR176 commented 10 months ago

Didn't quite get to test what you have told me because I had to install Windows to get some stuff done.

That being said, I installed Linux again, and this time I used just pulseaudio. And it seems to work perfectly on my end, suggesting that this might be a pipewire issue, in which case im at a loss when it comes to fixing it because I have no idea what separates pipewire vs. pulseaudio.

Perhaps this information gives you some insight of the problem.

davidjo commented 10 months ago

Thanks for the info - I didnt expect that. I think this may also suggest its a simultaneous HDA command issue.

My very limited knowledge (ie googling) is that one of the big problems with pulse was that it doesnt do audio timings very well - for pro audio other sound daemons are used eg Jack - pipewire from what Ive seen is supposed to improve audio timings eg if you expect audio sounds to be 10ms apart they are under pipewire but not necessarily under pulse.

The tighter timing constraints under pipewire may have a problem with the long delays caused by sending so many HDA commands to start/stop streaming.

112cxyz commented 10 months ago

I am also facing a similar issue on my MacBook Pro 14,1 (2017 no Touch Bar), I keep getting occasionally a high pitched pop noise when using headphones, Its at a extremely high volume. I was using pipewire but when any audio played it was just a high pitched loud deafening screech. On pulse I get the same screech but only for a 10th of a second when going to play audio. If no audio is played for a while I just loose audio altogether and have to reboot.

EDIT: After testing it again after the pop/screech audio just stops.

EDIT 2: I now have audio but its severely distorted. Ill post a comparison in a min.

EDIT 3: I have made the comparison. Using a pair of stereo headphones you can listen to the difference. The left channel is MacOS, the right channel is Arch Linux running the latest kernel and pulseaudio on gnome.

https://github.com/davidjo/snd_hda_macbookpro/assets/78795456/4f7b5bf8-d3a1-4523-8202-3a379f5ccea9

davidjo commented 10 months ago

There are a number of issues still.

If you really want to use headphones Id suggest using bluetooth/usb versions - these should work out of the box - if you want to use audio jack headphones try a usb DAC box.

Are your issues mainly with headphones??

Im now using a pipewire based Ubuntu (23.04) (which is mainly using the pulse-pipewire bridge I believe) and sound seems to be working for me - at least on the speakers - but again I dont really try switching between multiple audio sources.

There is an issue with sleeping - if youve set your laptop to sleep after a while it will screw the audio - maybe this is whats happening when audio stops (see no audio after suspend issue - plus pull request #90).

For jack headsets/headphones things need to be done slowly - there are some timing issues which I havent sorted out. so eg always plug in/out the headphones in a nice smooth single motion - no half way in then out. wait up to 5-10 secs after stopping all playing before removing/adding headphones also there was an issue with leaving headphones in over reboot - it didnt used to work - I think I may have tried to fix this but its still better to only plugin headphones after booting.

(note that there are issues under OSX with headphones - it used to be near instantaneous the switch from speakers to headphones after plugin - if you try with these 8409 laptops there is an up to 1/2 second delay after plugging in till sound actually switches - try it out - this is due to the massive number of HDA verbs being sent - which is why things under linux need to be done slowly).

As to the quality - I know this is an issue as it appears Apple applies some DSP processing which Im assuming is applied at the CoreAudio level - I know its not at the HDA chip level - see the layout...xml files under AudioHDA.kext (OSX) under Contents/Resources - your machine is likely layout54.xml - theres multiple mentions of Dsp processing eg DspMozartCompressor but who knows what the numbers mean. (Likely you would need to try some FFT spectrum analysis and figure out some possible DSP filters). Such audio processing could be done in Linux at the pulse/pipewire level to be the equivalent of the CoreAudio OSX level - its not a function of the HDA driver module.

davidjo commented 8 months ago

I may have fixed this. Was this with headphones/headsets or speakers?? I just re-installed Ubuntu mantic on my macbook pro and with headphones was reliably getting a glitch when a sound was started (but not with speakers) although not if new audio was started soon after the previous sound. However debugging this glitch I noticed that it appears the primary Alsa device pcm stream (as seen on pw-top plus my MYSOUNDDEBUG logging to syslog) closes after something like a 2.5 second delay with no sound playing - then re-opens when a new sound plays which is when I get the glitch. I also noticed that it appears the PREPARE code section was being duplicated each time the primary Alsa device pcm stream was opened - which I didnt realise could happen - I had assumed the PREPARE op was done once. Turns out the PREPARE op can be sent multiple times for a single PCM stream open - which I did not expect - I also found the documentation page which verifies this (maybe the pulse audio implementation doesnt do this so it seemed to work). So I have fixed the code to only do the setup once for multiple PREPARES within the same open - this fixed my headphone glitches. Note the multiple PREPARES was done for speakers also but didnt seem to glitch the audio on my macbook pro - but still its wrong - now only 1 setup is done per pcm open for speakers or headphones/headsets. Ive uploaded the new commits. (PS Ive also possibly fixed booting with headphones plugged in).

112cxyz commented 8 months ago

I'll reinstall arch and try again

112cxyz commented 8 months ago

So, I reinstalled arch. Fantastic news. Headphones work perfectly! Bluetooth has issues but that's not because of your audio patch.

112cxyz commented 8 months ago

Just to notify you, even better good news. It even works after being suspended.