Native FLAC via iRadio?

This is not (by coincidence) a specific implementation in the App. Note also the recent app updates due to Tidal issues. So, Tidal is not considered as a standard stream.
Obviously, for Naim it’s more important to provide Tidal integration, than listening to a minority complaining about lack of HD support on Gen 1 devices.

Hi @Kurt , yes & there’s a subtle point I have just realized:

If indeed Muso 1 is receiving Tidal FLAC 44.1Khz (aka lossless), and if so then all the arguments about gen 1 not capable of supporting higher rates streams over Internet + short memory buffers are kinda odd.

@aboulfad, I never thought about it that way, but that’s a very valid point. If Naim claims Gen 1 devices are not suited/capable to support flac over the internet due to hardware limitations, how does it come they support the flacs coming from Tidal on Gen 1 devices? @Stevesky, can you please clarify?

“Let’s not go down that :rat: :hole::wink: marketing strategy, priorities, requests and new product development usually eclipse previous generation. You said it above focus on Tidal vs the few who use free HD iRadio… I don’t think there’s a technical reason, IMO.

PS: for the record, I/we are happy with Naim product(s) and their support :heart:

1 Like

Hi @Kurt

Tidal have local CDN’s per country so the latency from data centre to customer is typically 20ms or so. Local ISP network congestion may increase delivery times at some times of the day to the point where a 6KByte TCP window cannot achieve the approx 850kbit/sec rate needed for 16/44.1 FLAC. That is why Tidal is on the edge on the older Bridgeco platform for some customers. A network device that can handle a larger tcp window (64K+) is far less sensitive to network latency.

In your radio proxy your service is acting like a local CDN, so the server uses a large tcp window to read the data and then assuming the listener is not 1000’s of miles away from the data centre proxying the data, the latency from streamer to proxy is relatively low. Network latency vs distance are dictated by the speed of light. Some examples here:

So if I used your proxy in New Zealand to listen to JB Radio2 on an NDX1 and the proxy is in USA, it would just be constantly dropping out due to approx 350ms of network latency.

Best regards

Steve Harris
Software Director
Naim Audio Ltd.

Fair & we are learning a bunch - surprised to see extremely fast round trip ping times for the local Tidal CDN (QC): (avg values)

  • Ping Kurt’s EU host: 105ms
  • Ping Kurt’s US host: 85ms
  • Ping Tidal CDN host: 15ms

But even at 105ms, I did use Kurt’s EU host for 15mns with 16/44.1 FLAC & had no dropouts whatsoever reaching many stations in EU. So I wonder how many of Naim’s gen1 customers fit within a radius of 150ms avg round trip time. That’s west coast US to EU (Paris, Frankfurt, Amsterdam)

But let’s say Naim releases a firmware update to enable FLAC/iRadio for Gen1 devices, pretty sure that the support team would be hit with complaints that HD radio doesn’t work for gen1 devices. totally understandable :bowing_man:

thank you for your continued support and patience !

Tx @Stevesky for the good clarification. This indeed explains why Tidal doesn’t cause issues. The ping from Belgium to Frankfurt where the proxy is running is in my case (wireless, multiple users on the home router) 19ms.

Salut aussi, Kurt ! :wave:

I have never been to Kortrijk (Courtai in french) although not so far away from home.
I visited lots of times Tournai, much closer.
My wife and I did have some nice food in main place and we brought back home some chocolates !

Your challenge seems fine indeed !
You also are right, depending on the day, some radios don’t run and, some minutes/hours/days after, back again !
My favorite is Hi On Line, number 1, followed by Radio Paradise.
I like Naim Radio but sometimes I don’t enjoy the music they stream. That’s life !

Thanks again and, for sure, I will let you know if some good WAV radio I discover is not under your site …

Sincerly yours,
BD

:100: thanks to @Kurt for an amazing package and docs. Finally managed to (compile) install and successfully use the utility on my rpi4 :grinning_face_with_smiling_eyes: I had trouble getting a jdk17 on rpi4 but finally managed. Next is to setup a VLAN on my managed switch so those “special” iRadio stations show up under iRadio and not in Upnp.

The utility during “transcoding” is really lightweight on resources < 1% CPU on a rpi4, and negligible memory footprint. (check screenshot for some benchmarks)

PS: oh its /fwp/status not /fwphealth (as per docs), it took me a while to figure out what "evil request is " !

Hi @aboulfad,
That’s great! Congratulations! :slight_smile:

  • Regarding Java on the PI4, for me this was the easiest part. The way I do it is to wget the .tar.gz (or the format in comes with) file (from Azul for example), extract it and than create a symbolic link (ln -snf …) to the extracted folder and call the sym link “jdk”. This allows me quicky replacing the Java runtime without the need to adapt the scripts. The sym link approach also allows quick testing with other JDKs and it’s not linked to the Debian package manager. This is also the way I run different Java version on Windows.

  • fwp/health > fwp/status change. Yes, this happened in version 4.4.190621 according the history.txt. I admit, I didn’t update the docs. To be honest, typing the docs took me an awful amount of time. Apologies for this.

  • “Evil request” :slight_smile: :slight_smile: Well, as I initially wrote this to run in my private network, I hadn’t taken into consideration people with “evil”, or malicious, intentions. The day I put it on the public cloud, I had something like +90 open connections, cause people were trying to hack the system by sending whatever “evil” request to the proxy. This forced me to add additional firewall rules, but also to add some logic in the software to intercept asap requests being not in the expected format. Those get blocked and logged as “Evil requests”. So, basically, an “evil request” is any request not being accepted by the proxy.

  • Transcoding from FLAC > WAV is indeed light weight. This is related to the design of the Flac format where compressing is quite CPU intensive, but decompressing is light weight, making it possible to run the decompression on less performant hardware.
    If you choose the MP3 transcoding, you’ll notice a higher CPU utilization due to the MP3 compression taking place after the Flac decompression. Same applies to AAC for example.

  • You indeed need to run it in a vlan other than the network where you’ve the Naim devices. If it’s in the same network, the Naim app considers it as an UPnP source. It works, but is clumsy.

Enjoy!

1 Like

no worries, awesome job. I couldn’t find jdk17 for rpi, it took me time to locate a source as I haven’t used java in years !!! finally got it from adoptium. The evil requests were because I was trying to reach a non existing path : ) having the source code/history helped to trace it .

fyi another *nix friendly solution is using alternatives:

sudo update-alternatives --install "/usr/bin/java" "java" "/home/pi/bin/jdk-17/bin/java" 1

I haven’t configured too many stations, but this is awesome, thank you again.

Darn… my netgear r7000 doesn’t support VLAN for LAN separation (802.1q VLAN). I can create VLANs on my managed switch (small 8port netgear GS308T) but that’s the end of the road.

Creating multiple subnets and routing between them on plain stock routers is not possible neither. Time for for a new toy :grinning_face_with_smiling_eyes:

I’ve the telco operator’s router in the garage and a wired connection from that router to my router in my living room. Both have different subnets. The PI running FWP is attached to the router in the garage, so it looks like a real radio station to the Naim that’s in the subnet of my router in the living room. This works fine.

Next to that, I use the AAC/MP3 streams from the Frankfurt FWP instance for my SONOS PLAY:1 when I need some background music when working and to feed a Soundcast outdoor speaker.

I should invest some time and gear into my network infra at home. It all started small, but when it growed, I added some routers and switches left and right to end-up with something almost unmanageable. What managed switch do you’ve or recommend?

I have one router that I’ll soon flash with dd-wrt for fun so I can do subnetting on any LAN port. I have a netgear GS308T managed switch.

Added “Radio Sing SIng” and “Free Music Radio” to the list.
Full station list here:
EU: http://158.101.168.33:9001/fwp/stations
US: http://129.146.133.23:9001/fwp/stations

1 Like

When going through the source code, I came across a bug dealing with the memory allocation of the play buffer. This could led in some rare cases (slow internet) to dropouts. This is fixed in the current running 7.2 version. Enjoy :slight_smile:

1 Like

Thank you for the updates! I’ll pick up 7.2 once you upload to GH : ) in the end I got a fun Mikrotik RB5009UG+S+IN router (overkill) and will use it to separate subnets for FWP/rpi4.

Outstanding work! I have only recently discovered this thread, wondering how to bring hires radio to my 272 and the solution provided by Kurt works just flawlessly :slightly_smiling_face:. So huge thanks for that!
I only have one question, maybe it was covered before and I missed it: any chance of displaying the real stream metadata instead of Forwarding proxy text string?

Search metadata in this topic and you’ll find the answer, post 220. As to the author including his name/tool in the station string, well he wrote and maintains the code, documents it, updates it & hosts the cloud based service,… credit goes to him :slight_smile:

The station string is easily changed in the code if one hosts the proxy in their own local network or cloud service. It would be nice to have the original metadata, IMO I focus more on enjoying the music than knowing which song is playing.

Ah… the metadata topic :slight_smile:
Well, basically there’s metadata on two levels: station metadata and track metadata.

The station metadata is retrieved during the handshake process. The handshake process takes place before the actual (music) bit stream starts. I’ve described this process in the section “Architecture and design” of this document (< click).

The protocol used during the handshake process is pretty open, or free format. I rely on the “icy-name” tag in the music service response to get the station metadata. If the tag is not present I use the station name mentioned in the configuration file. Afterwards, I indeed add the FWP version and my name. This happens in the following bit of source code:

        int startPos=Utils.indexOfIgnoreCase(inputBytes, 0, offset, "icy-name");
        if(startPos!=-1) {
            startPos+=9; // len icy-name:
            endPos=Utils.indexOf(inputBytes, startPos, offset, "\r");
            icyName = new String(inputBytes, startPos, endPos-startPos);
        } else icyName=proxyUrl.getFriendlyName();
        ......
        sb.append("HTTP/1.0 200 OK\nContent-Type: audio/").append(proxyUrl.getContentType()).
            append("\nicy-name:").append(icyName).
            append(" - ").append(APP_VERSION).append(" - kurt.lefevre@gmail.com\nicy-pub:0\r\n\r\n");

The track metadata is another story. I rely on ffmpeg to transcode the OggFlac to WAV. Fact is that ffmpeg does not pass the track metadata amongst those two formats. Also, WAV is not the most suitable format for tagging. As from the moment the handshake process went ok, I start the ffmpeg transcoding process and keep on reading from the stream to send it in fixed size chunks (io_buffer_size_kb) to the streamer. So, I don’t control the actual transcode process.

1 Like