Tuesday, April 11, 2017

Raspberry PI - I2S-HATs @ 384k

Today I'd like to share how to introduce 352k8/384k upsampling 
via LogitechMediaServer as server and squeezelite as a client.

This post, from a hardware perspective,  pretty much relates to my 

RPI I2S HAT DAC projects I've been running over at DIY-Audio.

Some DACs (TI PCM51xx family) have shown a slightly better performance 

when running upsampled material. That's the main reason for writing all this up. 







To begin with: The experienced differences havn't been earth-shattering IMO. 


By running these high samplerates the internal filters of the widely used TI PCM51xx DAC family get bypassed, which is very nice. A bit of that advantage might get eaten up by the higher processing load though. 


I still think this exercise is worth a try.


Afaik, there's no guideline elsewhere.



###############################################################

Note: Before you start

Your OS needs to support 352k8/384k samplerates for I2S HATs. 
If you do not run e.g. Moode or PiCorePlayer with the advanced audio kernels, 
this exercise will fail!


By default the Raspberry PI I2S is limited to 192kHz.
There are afaik just a very few distributions that offer full 384k I2S support.
The kernel and drivers need certain non-standard patches to support
these high samplerates through I2S. (USB-DACs just work at these rates !) 

And then not every I2S (HAT) DAC can handle from a HW perspective these high samplerates!
There were even cases where different DACs from the very same brand
some worked and others not!?!? 
Make sure your DAC theoretically supports it, before you start your journey!

What I do know is, that my Allo Boss DAC works rock solid on up2 384KHz.


I did also experience that these high samplerates do not cause any advantages 

on certain DACs, such as the Sabre ES9023.  For these this exercise would IMO be 
waste of time. 
You might still want to continue to read  this article, since I also added some side 
information that might be of interest.


Why the upsampling fuss at all?


1. Your external resampler might deliver a better quality than the internal ON-DAC
    resampler. 

2. Then there are certain DAC chips e.g. the TI PC51xx family, which bypass
     the internal filters altogether at 384k/352,8k samplerates. 


The OnDac filters and DSP functions usually have (quality) limitations due to HW limitations.

Bypassing or replacing them seems to be a feasible option to squeeze a bit more out of these DACs.

On the other hand: 


Every data manipulation causes losses! 

Upsampling is not a lossless process either.
Hmmh. Then why upsampling at all?? 
There are cases where upsampling might be the lesser of two evils!
The "losses" equation in our case would be :

On-Dac filters VS. sox upsampling incl. level reduction! + higher processing load 


Can I predict the outcome???


Nope.


Just try it and find out yourself. 

The results most probably will differ from setup to setup - as usual.

###############################################################


Let see how far we'll get with below:


The example relates to LogitechMediaServer (LMS ) on a Linux platform 

such as Ubuntu.


I'd assume that you have installed the just (Apr.2017) released LMS 7.9.0 version.


Note: 

I would not recommend to run CPU consuming upsampling neither on a RPI -
using squeezelite, nor a NAS  nor on any other low performance platform. 

That 's why I do not cover these scenarios!


I'm using a x86_64 platform - an Intel Core5 Broadwell NUC as LMS server (I use this machine for multiple tasks, incl. my everyday desktop work).



We'll be  using the excellent sox tool to do the upsampling. 




###############################################################
Preparations:

Make a backup of your server first! You do everything at your own risk!


First, we setup the environment.


Ok. Ok.  Wait a minute!!!


Before you go any further, and perhaps waste several hours, run a simple test first! 

Just offline-convert and play some of your favorite flacs
That's rather simple to accomplish.

Examples:


sox  -D test.flac -t flac -C 0 -b 24 test352k8.flac rate -v -s -L 352800 

or
sox  -D test.flac -t flac -C 0 -b 24 test384k.flac rate -v -s -L 384000 

(replace filenames according to your filenames)

if you experience clipping try below:


sox  -D test.flac -t flac -C 0 -b 24 test352k8v092.flac vol 0.92 amplitude rate -v -s -L 352800 


However. The last example will lower the signal level before conversion.
Keep in mind that you should also run that volume adjustment over the original without
samplerate conversion, otherwise your comparison might be misleading!  

Example: sox  -D test.flac -t flac -C 0 -b 24 testv092.flac vol 0.92 amplitude 


And then there's another one, which can make these files perform different!


The compression level!

You probably don't know what compression level's been used while generating your flac.
You can't figure it out later on!!!!

I always use compression level 0 !

Just to mention it. Even below example, which just potentially applies a new compression level can already make a difference:


sox  -D test.flac -t flac -C 0 -b 24 testC0.flac

The samples are the same, but the compression level might differ. The decoding process usually is slightly higher with higher compression levels. Decoded in realtime, a decoded 

stream will have even more impact!  

###

If you're happy with above test results you might want to continue here:


We better use the latest sox, since the LMS delivered sox is about 10 years old!

You run (just copy/paste - block by block ) following commands:

sudo su



/etc/init.d/squeezeboxserver stop



apt-get -y install sox 

cd /usr/share/squeezeboxserver/Bin/x86_64-linux/ 
cp sox sox.orig
cp $(which sox) sox
cp $(which sox) sox2
chmod 770 sox*
chown squeezeboxserver.nogroup sox*


apt-get -y install flac 

cd /usr/share/squeezeboxserver/Bin/x86_64-linux/ 
cp flac flac.orig
cp $(which flac) flac
cp $(which flac) flac2
chmod 770 flac*
chown squeezeboxserver.nogroup flac*


Note: 

By using the Linux/Ubuntu platform flac instead of using the LMS supplied flac, we'll loose the fast forward and rewind functionality. The LMS supplied flac is a patched version of the original. It's outdated though!

cd /etc/squeezeboxserver
test -f custom-convert.conf && mv custom-convert.concustom-convert.conf.orig
touch custom-convert.conf
chmod 644 * 
chown squeezeboxserver.nogroup * 



###############################################################

Now we look at the actual conversion rules.
Below are two of them including my preferred upsampling settings .

1. The first rule reads flacs,  upsamples them at highest quality with linear filters and outputs flacs again.
2. The 2nd reads flacs upsamples them and outputs .wav format.

Note: I do not use level adjustment below! There will be some clipping ( a couple of hundred clipped samples is nothing unusual) !


Both rules you can enable /disable under LMS server/settings/advanced settings/file types



The conversion rules would like this:


flc flc * *

# F
[sox] -D -q -t flac $FILE$ -t flac -C 0 -b 24 - rate -v -s -L 384000 

flc pcm * * 

   # F
   [sox] -D -q -t flac $FILE$ -t wavpcm -e signed  -b 24 - rate -v -s -L 352800 


Note: We leave the result at 24Bit (-b 24) and we disable dithering (-D).


Below I added an example of how to configure MAC based routing on LMS.

You basically have to replace the 2nd wildcard with the MAC address of e.g. your RPI 
to run the upsampling just for a single specific client - identified by MAC. 
All other clients would run  the default conversion rule (no resampling).


flc flc * b4:27:eb:dd:04:de

# F
[sox2] -D -q -t flac $FILE$ -t flac -C 0 -b 24 - rate -v -s -L 384000 

flc pcm * b4:27:eb:dd:04:de 

   # F
   [sox2] -D -q -t flac $FILE$ -t wavpcm -e signed  -b 24 - rate -v -s -L 352800 



You might have noticed that I used "sox2" as binary here. I actually made a 2nd copy of the

sox binary during the prep phase.
This trick I use to differentiate the different rules inside the LMS advanced settings/file types
menu! There won't be any other differentiator than this!

You probably run mainly 44.1kHz samplerates. I'd say go for a 352800 setting in

above examples. Just replace the 384000.


I do also have a wrapper-script that does synchronous upsampling. E.g. 44.1 to 352k8 and 48 to 384k. T
hat's worth a different article though!




Let's start setting up the resampling rule for all of your clients at once:

Let's assume you're still logged it.


Now we run:


sudo su


cat  > /etc/squeezeboxserver/custom-convert.conf << 'EOT'

flc flc * *
# F
[sox] -q -t flac $FILE$ -t flac -C 0 -b 24 - rate -v -s -L 384000 

flc pcm * * 

   # F
   [sox] -D -q -t flac $FILE$ -t wavpcm -e signed  -b 24 - rate -v -s -L 352800 

EOT



Now we can restart the server.


/etc/init.d/squeezeboxserver start


or just reboot the machine.



The difficult part is done!



Two more steps:

1.
Under LMS/setup/advanced configs/filetypes we need to enable above custom rules "flc flc" and "flc pcm" .
Don't forget to push the "save" button. 

2.

squeezelite config requires a slight adjustment.

To allow "server based upsampled PCM" support, you need to add "-W" to the optional parameters.

This setting allows to extract the samplerate from the PCM header, since the server can't tell squeezelite what samplerate you're upsampling to.   
For "flc flc" conversions this (-W) is not required. 
However. Just leave  "-W" in as default setting. It won't hurt.

Now the final step - another hidden squeezelite feature.


You can define or limit  supported codecs with  "-c" for squeezelite. 

By default all supported codecs (flac,pcm,mp3,ogg,aac,dsd, mad+mpg for specific mp3 codec) are enabled.
If you now have several conversion rules activated at the same time on LMS - e.g. "flc flc" and "flc pcm" which conversion rule will be taken??? 
The server will communicate with squeezelite about it. The process basically follows the rule "first come, first serve". 
Unfortunately by using the squeezelite default codec setting (all enabled), 
we don't really know and we can't change the sequence, because that's hardcoded. 
That's why we make use of the "-c" option for our squeezelite setup.

Examples:


-c pcm,flac,mp3


would mean that the "flc pcm" rule would be taken to convert the stream from flacs.

Because - yep - "pcm" is the first on the list.

-c flac,pcm,mp3


would mean that the "flc flc" rule would be taken to convert the stream. I guess u figured 

out why!?!?

Note: Above feature had been introduced not that long ago  - at the beginning of the year 2017If you run an older squeezelite version make sure you get the newest.

After that you just restart squeezelite and hope nothing went wrong.



Finally:


Once you ended up being unhappy with all above,   just run a restore.

To restore the original situation below should do:

sudo su


/etc/init.d/squeezeboxserver stop

rm /etc/squeezeboxserver/custom-convert.conf
test -f /etc/squeezeboxserver/custom-convert.conf.orig && {
mv /etc/squeezeboxserver/custom-convert.conf.orig /etc/squeezeboxserver/custom-convert.conf
}
cp /usr/share/squeezeboxserver/Bin/x86_64-linux/flac.orig /usr/share/squeezeboxserver/Bin/x86_64-linux/flac  
cp /usr/share/squeezeboxserver/Bin/x86_64-linux/sox.orig /usr/share/squeezeboxserver/Bin/x86_64-linux/sox  
/etc/init.d/squeezeboxserver start

###############################################################


There's one more option. I don't like it, but I'm pretty sure  many of you would 

like to try it.  Because this setup is most easy to accomplish. 
Your PI will have to be able to manage it though.
If your PI locks up and causes this or that issue, don't blame me!

Below an example of squeezelite doing highest quality resampling.


squeezelite autodetects the maximum available samplerate that your device/driver supports.


If you add below options to your squeezelite config you'll run a highest quality resampling, with  0.5db attenuation ( squeezelite default is attenuation is 1db! - you  also could disable the attenuation by inserting  "0" instaed of "0.5", which will - as discussed earlier - generate  certain clipped samples).

-R -u vLs::0.5:28:::

Then restart the player and enjoy.

Above example would resample (sync-mode) e.g. 44k1 to 352k8

You could also add an "X". This will resample everything (async-mode) to the highest available rate.



-R -u vLsX::0.5:28:::

Above example would resample e.g. 44k1 to 384k


###############################################################


That'll be it. 
Now, after writing all of this up, I kind of realized that the whole thing is actually not 
that simple. It'll take quite some enthusiasm, especially for someone with limited Linux 
background, to get going. 

If you stepped over flaws in above or if you have any questions - just let me know. 


Enjoy.

1 comment:

  1. I saw you suggestion on upsample on the kali/piano 2.1 combo so I did some sperimenting. I'm on windows and found the realy nice LMS plugin C-3PO that help to configure SOX.exe.
    With standard setting I get this string: sox.exe -q -t flac $FILE$ -t wav -b 24 --buffer 32768 --multi-threaded - gain -h rate -v -I -b 90.7 384000
    Like you, I quite like the sound i get out of it. thank you for the nice article and way to improve the sound, if you have time you should write up your finding for getting the beast out of the Allo Kali/Piano 2.1 ;-)

    ReplyDelete