Controller synchronization
I've done a little investigation over the last couple of days.
There is one basic problem with audio playback on the Controller: there does not seem to be a clock, or clocks, available to allow audio to be played back at the sample rate a particular stream may mandate. Audio is transferred to the audio codec over an I2S interface, and it seems that the clock rate applied to that transfer drives the rate at which audio samples are pumped out to the speaker/earphone/etc. The SOC uses a master clock at 50MHz from which to derive the I2S rates. There are distinctly limited "divide down" capabilities, so we can't get that close to the transfer rate needed.
Happily the kernel tells us what it is doing:
Translation: "A 48,000 Hz stream will be played out at 48,828 Hz, because that's the closest I can manage, and a 44,100 Hz stream will be played out at 43,402 Hz, because that's also the closest I can manage."
This becomes quite apparent if you simply compare the audio output for, say, a 500 Hz tone, against that produced by a "good" player. It will be clearly sharp or flat. You could also generate two sample test tracks, one at 44.1kHz and one at 48kHz, and compare them against each other. A 44.1kHz stream is played out too slowly, and a 48kHz stream is played out too quickly.
My untested hypothesis is that the synchronization code in LMS is unable to successfully cope with such a large deviation in the actual play out rates. Note that a 44.1kHz stream will consistently lag by about 16ms per second, and a 48kHz stream will consistently gain by about 17ms per second. This would require pause/skip commands to be continually issued at, say, half second intervals to prevent them from becoming audible.
In the context of the Controller, whose prime purpose is to issue audible beeps when its buttons are pressed, well I think it's fine. And also sufficiently fine for casual stand alone playback through earphones. But not "hi-fi".
My guess is that two Controllers will stay perfectly synchronized with each other. But I only have one Controller, so I can't verify the point.
Possibly LMS could be tweaked to accommodate matters. It's also possible that a specially tweaked 'jive_alsa' might be able to work around the issue. But that would require constant resampling by the Controller. At this point I don't know whether that is viable, but our current Covid-19 "lockdown" arrangements might just deliver up the time to find out.
While I was there, I also took the opportunity to check the accuracy of the system clock, and the RTC clock:
I checked the system clock by firing up an ntpd daemon, and letting it run. After settling down, it indicated that the system clock was running slow as compared with the world outside, by about 50ppm.
I then tested the RTC clock against that "correct" time using 'adjtimex'. The result surprised me. The RTC clock (which has its own 32kHz crystal, according to the Controller wiki page) appeared to be ticking within 1ppm of real time. Which seems rather good to me. Perhaps I should repeat the experiment in a refrigerator.
I've done a little investigation over the last couple of days.
There is one basic problem with audio playback on the Controller: there does not seem to be a clock, or clocks, available to allow audio to be played back at the sample rate a particular stream may mandate. Audio is transferred to the audio codec over an I2S interface, and it seems that the clock rate applied to that transfer drives the rate at which audio samples are pumped out to the speaker/earphone/etc. The SOC uses a master clock at 50MHz from which to derive the I2S rates. There are distinctly limited "divide down" capabilities, so we can't get that close to the transfer rate needed.
Happily the kernel tells us what it is doing:
Code:
48khz stream Jan 4 15:36:05 kernel: 256fs: div 4 => result 48828, deviation 828 Jan 4 15:36:05 kernel: 512fs: div 2 => result 48828, deviation 828 Jan 4 15:36:05 kernel: 384fs: div 3 => result 43402, deviation -4598 Jan 4 15:36:05 kernel: best: fs=256, div=4, rate=48828 Jan 4 15:36:05 kernel: mapped channel 10 to 2 44.1kHz stream Jan 4 15:37:27 kernel: 256fs: div 4 => result 48828, deviation 4728 Jan 4 15:37:27 kernel: 512fs: div 2 => result 48828, deviation 4728 Jan 4 15:37:27 kernel: 384fs: div 3 => result 43402, deviation -698 Jan 4 15:37:27 kernel: best: fs=384, div=3, rate=43402 Jan 4 15:37:27 kernel: mapped channel 10 to 2
This becomes quite apparent if you simply compare the audio output for, say, a 500 Hz tone, against that produced by a "good" player. It will be clearly sharp or flat. You could also generate two sample test tracks, one at 44.1kHz and one at 48kHz, and compare them against each other. A 44.1kHz stream is played out too slowly, and a 48kHz stream is played out too quickly.
My untested hypothesis is that the synchronization code in LMS is unable to successfully cope with such a large deviation in the actual play out rates. Note that a 44.1kHz stream will consistently lag by about 16ms per second, and a 48kHz stream will consistently gain by about 17ms per second. This would require pause/skip commands to be continually issued at, say, half second intervals to prevent them from becoming audible.
In the context of the Controller, whose prime purpose is to issue audible beeps when its buttons are pressed, well I think it's fine. And also sufficiently fine for casual stand alone playback through earphones. But not "hi-fi".
My guess is that two Controllers will stay perfectly synchronized with each other. But I only have one Controller, so I can't verify the point.
Possibly LMS could be tweaked to accommodate matters. It's also possible that a specially tweaked 'jive_alsa' might be able to work around the issue. But that would require constant resampling by the Controller. At this point I don't know whether that is viable, but our current Covid-19 "lockdown" arrangements might just deliver up the time to find out.
While I was there, I also took the opportunity to check the accuracy of the system clock, and the RTC clock:
I checked the system clock by firing up an ntpd daemon, and letting it run. After settling down, it indicated that the system clock was running slow as compared with the world outside, by about 50ppm.
I then tested the RTC clock against that "correct" time using 'adjtimex'. The result surprised me. The RTC clock (which has its own 32kHz crystal, according to the Controller wiki page) appeared to be ticking within 1ppm of real time. Which seems rather good to me. Perhaps I should repeat the experiment in a refrigerator.
Comment