Skip to content

Conversation

@h4yn0nnym0u5e
Copy link
Contributor

Although AudioInputSPDIF3 is rightly documented as being incompatible with most other audio I/O, it's possible to use its sample clock to drive the AudioOutputSPDIF3 and Audio.*putI2S[2]? objects, making a workable S/PDIF pass-through possible without the need to resample.

In addition to the required code changes, the design GUI has been updated so it doesn't show a conflict between the two SPDIF3 objects, and the info pane text has been edited to give a little more information on usable combinations of I/O objects with these two.

This supersedes the previous PR, as it overcomes some issues with insane clock rates if the S/PDIF input loses lock, at the expense of having to put code in the sketch to monitor this and swap clock source and (possibly) grab update responsibility. It also has a code example in HardwareTesting/SPDIFsync.

Tested at 32, 44.1, 44.117, 48 and 96kHz - the update rate changes to match, so anything frequency-related will be more-or-less wrong, depending on how different the S/PDIF rate is from the compiled-in AUDIO_SAMPLE_RATE_EXACT.
However, for some reason there's an extra or dropped sample on I2S every so often, despite the shared clock source. I can't find this to fix it... I've toggled an output pin in both the I2S and SPDIF ISRs, and they're definitely locked together. On this basis, I've updated the Design Tool to permit use of I2S / I2S2 with AudioInputSPDIF3 without flagging incompatibility, and put some comments in the info pane relating to "minor degradation" of the I2S audio quality.

h4yn0nnym0u5e and others added 30 commits September 18, 2022 23:11
AudioOutputSPDIF3 can use the Teensy audio clock at 44.1kHz, OR, if an AudioInputSPDIF3 object (which derives its clock from the incoming audio stream) is instantiated, it can and must be synchronised to that. This approach allows a glitch-free system using SPDIF I/O only.

The design GUI has been modified to allow this combination to pass conflict checks; a better implementation may be required.
Was just passing audio through, which was not what was wanted at all!

This update feeds the Rx clock back through SAI1 MCLK[3], which seems to be the valid way to do it; SAI2 or SAI3 would also work. As yet untested is the concept that this will sync the entire audio system to the S/PDIF Rx clock, so it becomes possible to use the audio shield too. More clock trickery is probably needed...
Also copy across code which removes need for a dummy I²S object
I²S on SAI1 will now work with S/PDIF input as master clock
Add offset to clock used by output_spdif3.cpp, which changes the interference rate
It looks like it's slipping 1 sample every so often, so if the SPDIF and PLL4 clocks
are e.g. 77Hz different then clicks occur at 77Hz

But why?!
Note the comment above the assignment of fs in AudioOutputSPDIF3::config_spdif3() (lines 231-236). For some reason the internal (PLL4-derived) clock has an audible effect, even if the system sample rate is supposedly being derived from the S/PDIF input. The effect seems fairly minor, with the occasional missing or extra samples rather than huge glitches, but it's not hi-fi, and I can't figure out the root cause!
Currently only between SPDIF3 and I2S output. Needs
extending to other I2S masters - inputs and channel
counts. Not relevant to TDM as the S/PDIF clock
is too slow to be clack master, but it might be
relevant to ADC, MQS, PWM etc.
With an unreliable S/PDIF input, the PLL goes crazy
and runs at weird speeds. This can result in the
DMA blocks being used and not replaced, so the
update() was trying to transmit a NULL pointer,
which the Audio library does not catch, causing a
crash.
I²C and MQS can use this, as they're controlled
by SAI hardware, which in turn can use the
recovered S/PDIF input clock.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants