I've been working on this problem for the past few days. I bought a cheapo logic analyzer ($12 on Amazon) and it has been amazingly helpful in working out exactly what is going on!
Here are my conclusions:
1) With the resistors the unit is rock solid with the Wire library (with the exception below). I have run it for 24+ hours without error on its own with a Teensy 3.2 and a Teensy 3.6, and also when it was sharing the I2C bus with a SI5131A clock generator that was continuously generating a frequency sweep from 10 to 15 MHz - thus keeping the bus busy. No problems.
BUT
2) with the Audio library I2S functions
AudioInputI2S and/or
AudioInputI2S active the results were a very mixed bag. With a simple sketch of an audio I2S pass-through, such as I posted in the first post of the thread, there were occasional NACK errors. Now the AudioControlWM8731 control does not recognize the I2C status reported by Wire.endTransmission, and any hard error can cause failure. So I modified and included the BALibrary, which repeats a I2C writes until the transmission is error free. This can repair occasional errors, and with this the pass-through code works most of the time.
However, with a more complex Audio library based program (such as my SDR and music software) the WM8731 code generates NACK errors on EVERY transmission!!! This is where the logic analyzer became invaluable. You can see the lack of ACK in each data packet. Go back to a simpler program and the problem disappears. So I removed Audio blocks one at a time and found that inclusion of objects
AudioInputI2S or
AudioOutputI2S caused the problems when the codec.enable() function is called.
Then I stumbled on another thread in the forum about exactly the same problem with the AK4558 codec here
here. They also found the
AudioInputI2S and
AudioOutputI2S objects to cause problems with I2C. The conjecture there is that the fact that both include a call to begin() function in the class constructor is the culprit, and Blackaddr suggested taking the begin() function out of the constructor and forcing the user to call begin() after all initialization is complete. Unfortunately the thread stopped at that point.
So I made my own version of those two Audio objects with empty constructors. The begin() function in each is already declare public. I modified my code to call codec.enable() near the begining of setup() and at the very end called myInput.begin() and myOutput.begin() at the very end of setup(). And that fixed it!!! The logic analyzer showed all NACK errors disappeared and the system worked.
I have no idea what the interference between the I2C and the audio blocks is, or why the SGTL5000 is robust to the problem. Apparently it's not unique to the WM8731, it seems that the AK4558 has the same problem!