New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve WM8960 sound quality #298
Comments
So I am wondering whether the following could work?
|
Not quite... stays silent... why? |
Because I do not have WM8960-based sound card, I would need a tested patch to include it in Circle. |
Note to self: Bisect this... |
Hello @probonopd So I just started poking around and comparing whatever is going on between circle and waveshare linux driver (from https://github.com/waveshare/WM8960-Audio-HAT/blob/master/wm8960.c) , and found some quite interesing things:
For 34h-37h linux defaults (and whatever I was able to dump right after boot-up sequence) are 100% consistent with the datasheet defaults. So basically we have totally different clock source and clock divider settings – I don't really have experience in DAC, but I suspect that clock base mismatch can be source of some extra noise. I am leaving this comment here because I am starting to become a bit dizzy, I will try to verify if setting any of the above to defaults from Waveshare driver helps as soon as I'll be able to build working MiniDexed – when I tried to do so, it crashed during boot up sequence. |
Thank you for your investigation @gdaszuta. I have since moved on to another DAC, but I am sure this will be helpful in case someone would like to revisit this topic. |
Ok, so I was able to test a build and I think that it's doing something:
But to be honest I cannot be 100% sure that it isn't the placebo effect, in couple days I'll try to dig up oscilloscope and do some tests to make sure that this change makes any sense (or if it doesn't, it the issue isn't some ratio of volume levels between internal amps in the chip). |
@gdaszuta It would be great, if you can provide a patch, which reliable solves this issue. Unfortunately I cannot test this here, because I do not have this DAC, so I have to rely on your judgement. |
I am experimenting using circle with a Pi Zero 2 W and a keyestudio WM8960 Hat for a SDR receiver project. The datasheet of the WM8960 states that setup of the clock depends (1) on external clocking and (2) on the desired sample rate. The WM8960 boards from Adafruit, Waveshare, Seedstudio and the likes are using 24 MHz external crystals. I understand that for 48 KHz sample rate we have to derive an internal clock of 12.288 MHz. For 44.1 KHz a clock of 11.2896 MHz has to be used. To get this internal clock from the external 24 MHz clock, we have to use the PLL with different register setups (see examples in the datasheet Rev 4.4, Page 64/65, Table 45 PLL Frequency Examples). I don't see any provisions in the circle driver for changing the WM8960-setup in runtime, so we have to decide on a fixed sample rate. I am using 48 KHz for bidirectional I2S with this register setup for clocking (just started, no longtime experience): SHIFT_BIT( 4, 0x005), // CLOCKING_1: select PLL, SYSCLKDIV=2, ADCDIV=0, DACDIV=0 A 44.1 KHz setup is used in the very good documented WM8960 Arduino library and the examples from SPARKFUN (see: https://github.com/sparkfun/SparkFun_WM8960_Arduino_Library, especially Example_8). So all in all looking at Linux register dumps helps understanding what has to be done but cannot be copied without exact knowledge of the used hardware (external clock) or the current use case (sample rate). By the way: A big "Thank You" to the developers of the fantastic circle / circle-stdlib environment! |
Thanks for bringing light into this and for appreciating our projects! How it seems the sound driver for the WM8960 codec needs some additional configuration information (sample rate, internal/external clocking), which is currently not available in the class |
I think this is not an easy task, as there are at least two abstraction levels:
To minimize the effort and be flexible at the same time, only a minium standard setup with a given sample rate and hardware implementation in mind could be offered - like the one already implemented. To enable even "esoteric" use cases, a deviation from this standard could be offered via a "WriteRegister" method in CSoundController. Like a "Toolkit" for the knowledgeable user. This could be reached on application level using the CSoundController::GetController method. The user then has the flexibility (and responsibility) to implement what ever is on his mind in "user space". See the examples in the above mentioned SPARKFUN lib for all the interesting use cases and register manipulations of a WM8960. For me the special charm of circle lies in direct hardware access with near realtime response. So a little tinkering is OK. |
I think, I understand, what you want to say. This is not a perfect solution,
but it seems, a perfect solution does not exist. There are so many different
audio interfaces out there, and I cannot expect, someone will write Circle
drivers for them. There was already an attempt to do so for a few interfaces
and it was not completed. Thus for WM8960-based sound cards, if there would
be a default setup, which works in most cases and the possibility to set user
parameters with CSoundController::WriteRegister(), it could be a good
compromise. Give me until Tuesday to build an opinion on this.
|
No hurry, I get along. And there doesn't seem to be that much interest in this subject anyway. |
I think, with your info above it should be possible to modify the WM8960 sound controller driver and the Circle sound library so that WM8960 sound cards work with the supported sample rates and in master or slave mode without adding much overhead. Perhaps I will order a WM8960 sound card to implement this. Having a On the other hand you already can directly write the device registers from your application, if you need this, by using the I2C master object and the known I2C address 0x1A of the WM8960. Adding |
Thank you for the information that there is no need for the WriteRegister() method. I did not see how to get to the device I2C from application level. I still have to work on my object oriented programing skills. I am from the team "you can write FORTRAN programs in any language" ;-) |
You are welcome. ;-)
|
I noticed that when using Circle, the WM8960 sounds a lot noisier than when using Linux.
Possibly we can improve things by tweaking the default configuration of the i2c registers?
https://github.com/matemaciek/circle/blob/14a120ad68ca668b01bc24cff15afff4e841fc07/lib/i2ssoundbasedevice.cpp#L473-L515
This is a dump from a pristine (no config changes made) Raspberry Pi OS installation with the WM8960 driver from https://github.com/waveshare/WM8960-Audio-HAT:
When one unmutes Noise Gate Switch (by default it is muted) in alsamixer and sets Noise Gate Threshold to ~80%, then the following changes:
https://github.com/waveshare/WM8960-Audio-HAT/blob/master/wm8960_asound.state defines no less than 58 controls that could theoretically be tweaked for this codec. But possibly using the default Linux driver configuration could already improve sound quality over what we currently have?
cc @matemaciek
The text was updated successfully, but these errors were encountered: