Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 16 of 16

Thread: Teensy 4 SPDIF input + ASRC

Hybrid View

  1. #1
    Junior Member
    Join Date
    Aug 2019
    Posts
    12

    Teensy 4 SPDIF input + ASRC

    Hi,

    since this is my first post here, I would like to tell something about me. Regarding the teensy I am mainly interested in its audio capabilities. About one year ago I started my first DIY-DSP project. I build a freeDsp which I conrolled with an Arduino via I2C (the first time I came in contact with mirco-controller programming). This setup is also still in use in my hifi-system. However
    I am not completely content with it. A few month ago I came across the Teensy 4 with its SPDIF-in and out and the powerful audio library and I decided to give it a try. But I needed the SPDIF input...
    After spending some time with the imxrt reference manual, learnig about DMA, how the Teensy audio library works, which additianal hardware is required,... I got it finally working.

    What I implemented is:

    - A SPDIF input class which receives the audio data and is compatible with the audio library/ inherits from the AudioStream class.
    - The SPDIF input class also contains an ASRC algorithm (I implemented this algoritm: https://ccrma.stanford.edu/~jos/resample/resample.pdf)
    and also a noise shaping + dithering algorithm. To get noise shaping filter coefficients, I implemented the following algorithm in Python: https://pdfs.semanticscholar.org/ea9...ae63eb410a.pdf
    I used the same weighting function as in the paper to get the filter coefficients.

    For now I am using a AudioOutputSPDIF3 object to output the audio signal. This object also has the 'update responsisbility'. On the other hand the spdif input receives audio samples at an arbitrary rate (e.g. 48kHz). The signal pipline is as follows:

    spdif input (24bit samples) -> ASRC (32bit float computation) -> quantize to 16bit (+ triangular dither + noiseshaping) -> (via blocks/ audio library) spdif output

    I am now wondering if there is interest to integrate the spdif input into the audio library? If so, the just let me know how to proceed.

    Best regards
    Alex

  2. #2
    If it works and you're happy for anybody to use your code then doesn't really matter if it's in the library or not - just publish it on Github and know that everyone is grateful that SPDIF is at last available. Paul can always then incorporate it at his leisure.

  3. #3
    Junior Member
    Join Date
    Aug 2019
    Posts
    12
    Ok, I'll publish the code on Github tomorrow.

  4. #4
    Quote Originally Posted by alex6679 View Post
    Ok, I'll publish the code on Github tomorrow.
    Please post a link - I've an unused Teensy4 here I'll give it a go with if I've time.

  5. #5
    Junior Member
    Join Date
    Aug 2019
    Posts
    12
    Hi, today I planned to make some final test with the spdif input. I especially had a look at the behavior at different input frequency from 44,1 to 192kHz. I ended up with making various changes and I am still not completely content. The main issue is the buffer that is filled by the spdif isr and from which the resampler gets the data. I try to keep that buffer as small as possible to minimize the latency. On the other hand, the resampler should never run out of samples.
    I think I still need some days to optimize that part.

    Regarding your Teensy: Is it already ready to receive a spdif signal? Are you using a toslink receiver?

    Best regards
    Alex

  6. #6
    Quote Originally Posted by alex6679 View Post
    Hi, today I planned to make some final test with the spdif input. I especially had a look at the behavior at different input frequency from 44,1 to 192kHz. I ended up with making various changes and I am still not completely content. The main issue is the buffer that is filled by the spdif isr and from which the resampler gets the data. I try to keep that buffer as small as possible to minimize the latency. On the other hand, the resampler should never run out of samples.
    I think I still need some days to optimize that part.

    Regarding your Teensy: Is it already ready to receive a spdif signal? Are you using a toslink receiver?

    Best regards
    Alex
    If you need low latency (as I always do for live sound) but are sourcing data from a variable time dependent source such as a PC, the usual way is once you've written to the buffer, if the buffer is almost empty write the same sample again. As it only tends to occur very rarely it's not noticeable and is better than outputing something random when the buffer is empty.

    My Teensy's not set up but I can do. I bought it for a project but there's no way of syncing it to a master clock so I had to go back to a STMicroelectronics based board. But I'll have a play with your code when you publish it anyway as it will make a good interoperability test for that board.

  7. #7
    Junior Member
    Join Date
    Aug 2019
    Posts
    12
    Hi,

    I finally published the code for the spdif input on github:
    https://github.com/alex6679/teensy-4-spdifIn
    There are also two very simple examples (example0.cpp and example1.cpp) that show how to use the spdif input class.

    It works reliably with my setup, but let's see if it works for you.
    There are still some issues that I would like to mention:
    - As suggested in the resampling paper, the sinc- resampling filter is also used as anti-aliasing low pass filter. However I restricted the maximum filter length to 161 and depending on the input frequency the attenuation of high frequency is restricted. Maybe an additional anti-aliasing filter should be added.
    - The code is not optimized and the processor usage is quite high. At 48kHz input frequency the processor usage of the spdif input is 9%.

    The code is not well documented yet and I think there are lots things to explain. Since I don't know if people are interested in my code, I will add some explanations if needed.

    Best regards
    Alex

  8. #8
    Junior Member
    Join Date
    Aug 2019
    Posts
    12
    Since my last post in December, I improve the asynchronous spdif input. Especially the PID controller, that adjusts the sampling distance to the current input frequency. I also added a short documentation and some results of the resampling and noise-shaping algorithms.
    Best regards
    Alex

  9. #9
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,546
    Additional question: Hopefully, it does not change the Audio-PLL frequency? (->Is it compatible with I2s?)

    edit: this
    Code:
    static int32_t spdif_rx_buffer[SPDIF_RX_BUFFER_LENGTH];
    is not good.
    Please use DMAMEM (which unfortuately needs added cache handling)

  10. #10
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,546
    The spdif input is working since early last year...
    Any filters (biquad?) should be optional and handled by the audio library. The resampling sounds interesting.
    Maybe you can do a pullrequest for Paul?

  11. #11
    Junior Member
    Join Date
    Aug 2019
    Posts
    12
    I noticed that you already implemented a spdif input some weeks ago, when Paul added it to the audio library. At that point I also already finished my implementation. However, as you mentioned: Since my implementation is resampling the input to Teensy Audio sample frequency, it is still usefull in some use cases.
    Regarding the biquad file that you found: No filters are applied to the input signal. I only needed a lowpass filter internally for the adjustment of resampling step width. For that purpose it's unfortunately not possible to use the AudioFilterBiquad class of the audio library.
    Regarding the Audio-PLL: It is not changed. Currently I am using i2s inputs/outputs together with spdif in- and output in in one project without any problems.

  12. #12
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,546
    Quote Originally Posted by alex6679 View Post
    I noticed that you already implemented a spdif input some weeks ago, when Paul added it to the audio library. At that point I also already finished my implementation. However, as you mentioned: Since my implementation is resampling the input to Teensy Audio sample frequency, it is still usefull in some use cases.
    Regarding the biquad file that you found: No filters are applied to the input signal. I only needed a lowpass filter internally for the adjustment of resampling step width. For that purpose it's unfortunately not possible to use the AudioFilterBiquad class of the audio library.
    Regarding the Audio-PLL: It is not changed. Currently I am using i2s inputs/outputs together with spdif in- and output in in one project without any problems.
    Great!
    can you fix the DMAMEM )(+cache handling) issue and do a PR?
    It can replace my version (my PR was almost a year old when it got merged...) , no problem (but it would be good if it used the same names, so that no code change by the users will be needed)

  13. #13
    Junior Member
    Join Date
    Aug 2019
    Posts
    12
    Thanks for pointing out, that I should use DMAMEM. I'll fix that tomorrow. If you really want to replace your version, then I can change the name. But resampling needs quite some ressourcen (Mostly because of the anti-aliasing filter) and some people maybe prefer a version without resampling. I could also rename to something like AsyncAudioInputSPDIF3?

  14. #14
    Junior Member
    Join Date
    Aug 2019
    Posts
    12
    Ok, I am using now DMAMEM for the input buffer (+arm_dcache_delete((void*)src, sizeof(spdif_rx_buffer) / 2) in the isr) Also, I added the anti-aliasing attenuation + the minimum filter length of the resampling filter to the arguments of the spdif input constructor. In that way the user can lower the processor usage by decreasing the attenuation and filter length. Do you still think the async input should replace the synchronous input? I could also add a parameter to turn the resampling off in order to keep the current synchronous input?

  15. #15
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    6,546
    Quote Originally Posted by alex6679 View Post
    Do you still think the async input should replace the synchronous input?
    Hm, I think you're right.
    Can you do a pullrequest?
    Would be great to have in the next Beta (I hope Paul adds it)

  16. #16
    Junior Member
    Join Date
    Aug 2019
    Posts
    12
    I had a brief look at the current spdif input to check if it makes sense to make a combined class that could be configured as synchronous and asynchronous input. But I think that would make things quite complex. I'll rename my input to AsyncAudioInputSPDIF3 and make a pull request. Let's see if Paul thinks that it makes sense to integrate it into the audio library.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •