Edzelf / ESP32-Radio

Internet radio based on ESP32, VS1053 and a TFT screen.
GNU General Public License v3.0
985 stars 229 forks source link

320kbps playback issues #96

Open jgrulich opened 6 years ago

jgrulich commented 6 years ago

I'm quite surprised that this ESP32 version has issues with playing 320kbps MP3 and AAC streams. I like to play 149.255.57.97:8148 A1Radio 320Kbps MP3 and 45.43.200.66:25858 GOLD INST HD 320Kbps AAC The first one plays on the older ESP Radio smoothly and the second one with only some occasional gaps, but at the ESP32 player both of them have periodical significant gaps. On the PC connected via wifi both of them are playing smoothly with the 100% full buffer. Any idea what may be wrong?

Edzelf commented 6 years ago

149.255.57.97:8148 plays well here. The queue is constantly filled up to 380 or more chunks. 45.43.200.66:25858 has difficulties. The queue becomes empty now and then. It looks that the sender provide less than 320 kbps most of the time.

jgrulich commented 6 years ago

Test both of them on the PC and see the buffer. In my case they have full bitrate.

DaniloSakovic commented 6 years ago

Same problem here... glitches glitches on all streams above 128k... Tried everything... Maybe chip is bad...

Everything else PERFECT!!!

Edzelf commented 6 years ago

149.255.57.97:8148 plays well here. 178.79.158.160:8424/stream plays well here. 45.43.200.66:25858 has still difficulties, because the real bitrate is about 304 bps and my software is not capable to cope with that. PC software is capable to adapt to the real bitrate.

Uksa007 commented 6 years ago

I too have issues with anything over 128k stream. eg: http://85.214.231.253:8080/stream 192k stream They work fine on the PC, but playback on the ESP is very bad, plays 0.25 sec then pause 0.25sec repeat. I suspect there are somethings that have changed with the Wifi stack in recent with Arduino-esp32 related to internal buffers.

Using V1.0.0 of the ESP32 for Boards manager (finally!) https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/boards_manager.md

Any thoughts?

Edzelf commented 6 years ago

85.214.231.253:8080/stream (without "http://" of course) plays well here. Dubug output:

D: Connect to new host 85.214.231.253:8080/stream
D: Connect to 85.214.231.253 on port 8080, extension /stream
D: Connected to server
D: Switch to HEADER
D: Headerline: Accept-Ranges:none
D: Headerline: Access-Control-Allow-Origin:*
D: Headerline: Cache-Control:no-cache,no-store,must-revalidate,max-age=0
D: Headerline: Pragma:no-cache,no-store
D: Headerline: Expires:-1
D: Headerline: Connection:close
D: Headerline: icy-name:Dolfijn FM
D: Headerline: icy-genre:Pop, Top 40
D: Headerline: icy-br:192
D: Headerline: icy-sr:44100
D: Headerline: icy-url:http://www.dolfijnfm.com
D: Headerline: icy-pub:1
D: Headerline: content-type:audio/mpeg
D: audio/mpeg seen.
D: Headerline: icy-metaint:16384
D: Headerline: X-Clacks-Overhead:GNU Terry Pratchett
D: Switch to DATA, bitrate is 192, metaint is 16384
D: Metadata block 64 bytes
D: Streamtitle found, 48 bytes
D: StreamTitle='La Bilirrubina - Juan Luis Guerra';
**D: Command: test with parameter 0**
D: Stack maintask is 4876
D: Stack playtask is 1048
D: Stack spftask  is 820
D: ADC reading is 34
D: scaniocount is 10
D: Max. mp3_loop duration is 62
D: Free memory is 136592, chunks in queue 389, stream 6964, bitrate 192 kbps
D: Duration mp3loop 14
D: Duration mp3loop 25
D: Duration mp3loop 26

Can you try it on a different WiFi network?

Uksa007 commented 6 years ago

Don't have access to any other wifi at the moment, but PC works fine using same wifi and same stream.

Have you tried using the latest version V1.0.0 of the arduino-esp32 code??? https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/boards_manager.md

my output D: Connect to new host 85.214.231.253:8080/stream D: Connect to 85.214.231.253 on port 8080, extension /stream D: Connected to server D: Switch to HEADER D: Headerline: Accept-Ranges:none D: Headerline: Access-Control-Allow-Origin:* D: Headerline: Cache-Control:no-cache,no-store,must-revalidate,max-age=0 D: Headerline: Pragma:no-cache,no-store D: Headerline: Expires:-1 D: Headerline: Connection:close D: Headerline: icy-name:Dolfijn FM D: Headerline: icy-genre:Pop, Top 40 D: Headerline: icy-br:192 D: Headerline: icy-sr:44100 D: Headerline: icy-url:http://www.dolfijnfm.com D: Headerline: icy-pub:1 D: Headerline: content-type:audio/mpeg D: audio/mpeg seen. D: Headerline: icy-metaint:16384 D: Headerline: X-Clacks-Overhead:GNU Terry Pratchett D: Switch to DATA, bitrate is 192, metaint is 16384 D: Metadata block 48 bytes D: Streamtitle found, 36 bytes D: StreamTitle='Shotgun - George Ezra'; D: Command: test with parameter 0 D: Stack maintask is 5900 D: Stack playtask is 1048 D: Stack spftask is 676 D: ADC reading is 0 D: scaniocount is 10 D: Max. mp3_loop duration is 49 D: Free memory is 175016, chunks in queue 0, stream 0, bitrate 114 kbps D: Duration mp3loop 1 D: Duration mp3loop 2 D: Duration mp3loop 4 D: Duration mp3loop 5

Edzelf commented 6 years ago

Queue is 0. That means: not enough input from the network. I'm using the latest versions of toolchain and libraries.

Uksa007 commented 6 years ago

Yep, but I suspect that is due to network latency and insufficient RX buffers in the network stack. I tried another wifi (my mobile phone hotspot, same issues)

Whats you latency like to this host, my latancy on ADSL is below?

Pinging 85.214.231.253 with 32 bytes of data: Reply from 85.214.231.253: bytes=32 time=381ms TTL=112 Reply from 85.214.231.253: bytes=32 time=368ms TTL=112 Reply from 85.214.231.253: bytes=32 time=368ms TTL=112 Reply from 85.214.231.253: bytes=32 time=369ms TTL=112

Ping statistics for 85.214.231.253: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 368ms, Maximum = 381ms, Average = 371ms

Edzelf commented 6 years ago
Pinging 85.214.231.253 with 32 bytes of data:
Reply from 85.214.231.253: bytes=32 time=18ms TTL=122
Reply from 85.214.231.253: bytes=32 time=17ms TTL=122
Reply from 85.214.231.253: bytes=32 time=18ms TTL=122
Reply from 85.214.231.253: bytes=32 time=18ms TTL=122

Ping statistics for 85.214.231.253:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 17ms, Maximum = 18ms, Average = 17ms
Uksa007 commented 6 years ago

Holly cow, that's basiclly siting on your lan!

You might need to find a high bitrate with high latency +300ms, and then you will see the issues,

Not all of live in europe!

Uksa007 commented 6 years ago

Maybe try this one it's about 200ms from me, and should be similar for you! http://162.211.86.137:8000/stream 320k

Edzelf commented 6 years ago

121 msec from here and it's BAD. I will try it with increased buffersize, but I cannot change the internal buffers.

Uksa007 commented 6 years ago

Well that good that you can replicate the issuse!

This sounds lnteresting, Implement RX buffer for WiFi client to speed up small reads https://github.com/espressif/arduino-esp32/commit/9efecc1be03a7f319df1d86b58f56ae73a6ae510

I haven't figured out how to call WiFiClientRxBuffer(10240); yet, keep getting error invalid use of incomplete type 'class WiFiClientRxBuffer'

Edzelf commented 6 years ago

There are no "small reads" in the radio, it's always trying to read as much as possible. I checked it with the new version, but the result is the same. WiFiClientRxBuffer is called internally. No way (and no need) to call it from a sketch.

Uksa007 commented 6 years ago

I think the issues are related to how TCP works, once the internal WIFI stack buffer is full it starts dropping packets to reduce the window size of the packet so less data gets sent. When the stream starts I'm guessing there is more data sent than the internal buffer can handel and it all slows down, the more latency the slower it recovers. I think the internal buffers are small only 2*1468 bytes from memory.

Thoughts on how to resolve?

Edzelf commented 6 years ago

I think there is no solution for this. The code and the primary buffers are part of the ROM program.

Uksa007 commented 6 years ago

Are you sure they are in the ROM? Lots of mention of buffers in here C:\Users\Username\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.0\tools\sdk\include\lwip

lwipopts.h lwip/opt.h

xP373Rx commented 3 years ago

I fixed it like this .. you should not read the buffer every time something is available cuz u may read 1 byte and execute butt load of code. do it every 1k bytes . if ( maxchunk > 1000 )

My problem was with this station. preset_1 = 192.95.18.39:5784 # 1 ChroniX | AGGRESSION

av = mp3client.available() ; // Available from stream if ( av < maxchunk ) // Limit read size { maxchunk = av ; } if ( maxchunk > qspace ) // Enough space in queue? { maxchunk = qspace ; // No, limit to free queue space } if ( maxchunk > 1000 ) // Anything to read? { res = mp3client.read ( tmpbuff, maxchunk ) ; // Read a number of bytes from the stream }

Edzelf commented 3 years ago

It is a good idea, tested it, but it did not work out here for your station. To aggressive I assume :)

xP373Rx commented 3 years ago

Yes it worked a while dont know why but then started again to cut out . Then i googled again and i think i found it ;D

I added those 2 lines but the power saving mode did it i think. Buffer is now always at 400 esp_wifi_set_ps(WIFI_PS_NONE);//turn power saving off esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B); // better range

add extern "C" {

include

}
to the include section. then in connectwifi()

bool connectwifi() { char pfs ; // Pointer to formatted string char pfs2 ; // Pointer to formatted string bool localAP = false ; // True if only local AP is left

WifiInfo_t winfo ; // Entry from wifilist

WiFi.disconnect(true) ; // After restart the router could WiFi.softAPdisconnect(true) ; // still keep the old connection if ( wifilist.size() ) // Any AP defined? { if ( wifilist.size() == 1 ) // Just one AP defined in preferences? { winfo = wifilist[0] ; // Get this entry esp_wifi_set_ps(WIFI_PS_NONE); esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B); WiFi.begin ( winfo.ssid, winfo.passphrase ) ; // Connect to single SSID found in wifi_xx dbgprint ( "Try WiFi %s", winfo.ssid ) ; // Message to show during WiFi connect }

xP373Rx commented 3 years ago

Tested like 20 radios now seems to work with the original code with just those 2 lines changed. Found just one that had issues but could be server releated.

xP373Rx commented 3 years ago

Old Pioneer TX 6500 II gets a new life;>

http://gsgrid.net/harb/harb/PitsIphone/PhotoSync/IMG_7165.JPG http://gsgrid.net/harb/harb/PitsIphone/PhotoSync/IMG_7164.JPG

utw3v0 commented 3 years ago

Yes it worked a while dont know why but then started again to cut out . Then i googled again and i think i found it ;D

I added those 2 lines but the power saving mode did it i think. Buffer is now always at 400 esp_wifi_set_ps(WIFI_PS_NONE);//turn power saving off esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B); // better range

add extern "C" {

include

} to the include section. then in connectwifi()

bool connectwifi() { char pfs ; // Pointer to formatted string char pfs2 ; // Pointer to formatted string bool localAP = false ; // True if only local AP is left

WifiInfo_t winfo ; // Entry from wifilist

WiFi.disconnect(true) ; // After restart the router could WiFi.softAPdisconnect(true) ; // still keep the old connection if ( wifilist.size() ) // Any AP defined? { if ( wifilist.size() == 1 ) // Just one AP defined in preferences? { winfo = wifilist[0] ; // Get this entry esp_wifi_set_ps(WIFI_PS_NONE); esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B); WiFi.begin ( winfo.ssid, winfo.passphrase ) ; // Connect to single SSID found in wifi_xx dbgprint ( "Try WiFi %s", winfo.ssid ) ; // Message to show during WiFi connect }

Great Job, i adopted your 3 lines of code and enjoy 320kbit@48kHz :) Greets

xP373Rx commented 3 years ago

The HTTP requests do not lag anymore the pages of the esp32 are faster.