Open nopnop2002 opened 4 years ago
I don't think it needs to be fixed.
It works fine without any changes.
Please close after reading this issue.
Hi @nopnop2002! Thank you. The community delivered the radio example. The author's idea was to provide a simple example. While people can extend it according to their needs, I think it's important to emphasise what are the potential issues to handle. I will add a comment to the example pointing to this thread as well as the other one regarding buffer.
Yes I think it's important to provide a simple example.
Yup, metadata while streaming are disabled by default on most servers. You can control this by "Icy-MetaData: 0" header. Unhandled metadata will cause clicking. But support for metadata is not simple, you need additional buffer or ringbuffer, grap icy-metaint, skip metadata chunks, parse icy-* headers...
Hi, I made several tries and I understand now why sometime the sound is brassy, and sometime it is clicking. Sorry but for my experience ring buffer does not solve my problem.
First: For some radios the sound is brassy. This is solve by increasing the buffer size : the brassy effect seems to be the routine is too low compare to the streaming. By increasing the buffer the client.read function is done less time, so it is faster.
Second: For some stations that make many clicking effect after a moment (few seconds to few minutes) the VS1053 crash, I must reboot to come back to make it running again. To solve this problem, I add some delays: the SPI.writeBytes seems to need a while between 2 calls. So I modify the VS1053.cpp to the following:
void VS1053::sdi_send_buffer(uint8_t *data, size_t len) { size_t chunk_length; // Length of chunk 32 byte or shorter
data_mode_on();
while (len >= vs1053_chunk_size ) // More to do?
{
await_data_request(); // Wait for space available
len -= vs1053_chunk_size;
SPI.writeBytes(data, vs1053_chunk_size);
delay(1);
data += vs1053_chunk_size;
}
data_mode_off();
}
Third: I have told in another thread that when I compare a radio reception from the device and a PC, I noticed that the streaming from this web radio is much faster that on the PC. After a while the web radio either looses the signal, either crashes. Depending of the signal bitrate, the client.read should be cadenced at the right time. I do not know how to do, because for the moment I do not know how to automatically define how long client.read takes to fill its buffer. However I test this code that makes to web radio working much better:
static byte tempo = 0; if( tempo %2 == 0 ) { // it is not use to run each time ArduinoOTA.handle(); // for code update available from wifi server.handleClient(); // call to web server }
// if signal is lost if( !client.connected() ) { WiFi.status(); // wifi connexion checkup Serial.println("Tentative de reconnexion..."); if( client.connect(urlStation, portStation.toInt()) ) { client.print(String("GET ") + pathStation + " HTTP/1.1\r\n" + "Host: " + urlStation + "\r\n" + "Connection: close\r\n\r\n"); } return; } // end of !client.connected() test
// if connected to the radio station :) //if( client.available() > 0 ) { // not usefull if( !pause && tempo%10 == 0 ) { if( client.read(mp3buff, 256) == 256 ) { delay(1); player.playChunk(mp3buff, 256); } else player.playChunk(sampleMp3, sizeof(sampleMp3)); // for debugging if buffer is not full } tempo++; } // end of loop
This code uses very short time of 'pause' that synchronize the streaming. To improve this code, tempo%10 == 0 should be define automatically depending of the data flow speed.
Whey you send 256 buffer to VS1053 then sdi_send_buffer will split that buffer to 32 (vs1053_chunk_size) and will send to VS1053 in loop. sdi_send_buffer already have proper delay in await_data_request() function. When Delay(1) in sdi_send_buffer helps you then I don't understand why... await_data_request checking dreq pin, in other words asking vs1053 if we can send new data. Hm... it looks like something is not making proper clock speed. Can you test only mono output ?
write_register(0x07, 0x1e09);
write_register(0x06, 0x0001);
@fabitom include now in the VS1053::begin() function, however I don't notice significant improvement.
Ok, you can try this:
if( client.available() > 0 ) {
...
} else {
Serial.print('.');
}
and watch if problems occour when client don't have data.
I did similar yet:
// if connected to the radio station :)
if( client.available() > 0 ) {
if( !pause && tempo == 0 ) {
bytesread = client.read(mp3buff, 512);
delay(1);
player.playChunk(mp3buff, bytesread);
}
}
else player.playChunk(sampleMp3, sizeof(sampleMp3)); // for debugging if buffer is not full
tempo++;
if( tempo > 10 ) tempo=0;
I never hear the specific sampleMp3 when a radio is listened. So the client.available is always true, and in fact I do not understand this test must be performed each loop. However tempo is required for these clicking radios can play for more than 10 minutes. I improve duration with 30, 40, 50 instead of 10, but in this case most of other radios become brassy....
.... I cannot see the way Edzelf has coded the equivalent of the client.read in its Esp-radio....
@philippedc Thanks for this analysis.
To solve this problem, I add some delays: the SPI.writeBytes seems to need a while between 2 calls. So I modify the VS1053.cpp
Are you using ESP8266? Right?
I wonder whether instead of adding delay(1)
, the yield()
would do the job?
Would you please check and adjust your VS1053.cpp
modification?
AFIK the "yield" is designed to solve such issues (As described here, the reason for Yielding is preventing from various issues. The ESP8266 runs a lot of utility functions in the background – keeping WiFi connected, managing the TCP/IP stack, and performing other duties. Blocking these functions from running can cause the ESP8266 to crash and reset itself).
If the yield works fine, I would add it to VS1053.cpp
before SPI.writeBytes
like you did.
.... I cannot see the way Edzelf has coded the equivalent of the client.read in its Esp-radio....
@baldram it sounds much better !
If the yield works fine, I would add it to
VS1053.cpp
beforeSPI.writeBytes
like you did.
il is after. I've also had a yield in the loop: if( client.available() > 0 ) { bytesread = client.read(mp3buff, 256); yield(); player.playChunk(mp3buff, bytesread); }
It make twenty minutes the web radio did not crash. I have a remark: most of the time the crash consists of the infinite repetition of the a noise that could be the playChunk buffer. Why in this case the ESP8266 does not perform a watchdog reset as the loop is stopped ?
.... there is no WD reset because of the yield() in await_data_request(); I suppose ?
I will release the version corresponding to ESP-IDF.
https://github.com/nopnop2002/esp-idf-vs1053
It use RingBuffer.
But sometimes it lose network connection.
I don't know why.
Your modifications are welcome.
@philippedc
it sounds much better!
I'm not sure I follow. Does this yield
help when it's put after SPI.writeBytes(...)
?
I've also had a yield in the loop It makes twenty minutes the web radio did not crash.
Do I understand correct?
It crashes after 20 minutes when putting yield
in the loop. Right?
But when putting after SPI.writeBytes
, everything is fine like with dealy(1)
. Right?
I try to clarify whether to add yield
or delay
after SPI.writeBytes
to the library's VS1053.cpp
.
I have a remark: most of the time the crash consists of the infinite repetition of the a noise that could be the playChunk buffer. Why in this case the ESP8266 does not perform a watchdog reset > as the loop is stopped ? .... there is no WD reset because of the yield() in await_data_request(); I suppose ?
To be honest I don't have an answer to this question, unfortunately.
But I guess the indirect yield
might help too.
@baldram I have 3 of these web radios at home. So it is easy to compare different code version. I had the idea of a delay(1) after the SPI.writeBytes just like it is for an anlogRead(), just to let the time for the device to settle... In fact I did not test with the yield() before SPI.writeBytes , I will test this afternoon.
When I compare the new version of web radio with these yield() with the original code - they are identical except the yield(), I have less clicks - but there are - with the use of yield(), and if the streaming still takes some advance, this advance is very less than with the original version.
More over the clicking effect - the couiiiik should be the best expression - happens neither at the same streaming moment, nor at the same time. So I suppose it is a internal problem of the radio.
@philippedc
I had the idea of a delay(1) after the SPI.writeBytes just like it is for an anlogRead(), just to let the time for the device to settle... In fact I did not test with the yield() before SPI.writeBytes , I will test this afternoon.
I mean using yield after the SPI.writeBytes
only. Not before.
So I would like to clarify only whether modifying your code snippet with yield()
like showed below is better?
Or maybe it's better to keep it as it is with delay(1)?
I mean your modification to VS1053.cpp
.
I will add the final solution to the library as it should not harm, but help in some cases, like yours.
So I suppose it is an internal problem of the radio.
It could be too, indeed.
If you are developing an ESP32 application in an Arduino environment, it will be built with a single task and usually scheduled on Core 1, unless you use xTaskCreate ().
delay () returns control to the scheduler and grants execution rights to other tasks waiting to run, but has no effect if core1 has no other tasks.
On the other hand, SPI transfer requests are temporarily stored in the system ring buffer and processed by the system task, but the system task is executed by the core 0.
In the case of ESP32, Delay () is not effective in a single task environment.
This is my personal opinion.
IMHO putting Delay() between SPI.BeginTransaction and SPI.EndTransaction is quite risky. From what I see esp8266 need yield in main loop Adafruit VS1053 as example
bytesread = client.read(mp3buff, 32);
while (!player.data_request()) {
yield();
}
player.playChunk(mp3buff, bytesread);
or after playChunk like here: frokats-project
But sometimes it lose network connection.
I don't know why.
Your modifications are welcome.
Maybe wifi power save mode. I saw some similar problems. esp_wifi_set_ps
@fabitom Thank you. I'll try.
I added esp_wifi_set_ps, but still sometimes lose network connection.
There are other causes.
@fabitom
IMHO putting Delay() between SPI.BeginTransaction and SPI.EndTransaction is quite risky. From what I see esp8266 need yield in the main loop Adafruit VS1053 as example
Thanks. I see something similar in Edzelf's radio: https://github.com/Edzelf/Esp-radio/blob/e1639010a80a6516191cc15a900599f8a6794dd4/Esp_radio.ino#L369-L375
Now, looking at the ESP_VS1053_Library it was correctly extracted and has this part too: https://github.com/baldram/ESP_VS1053_Library/blob/master/src/VS1053.h#L71-L74
I wonder whether anything else is needed or just the client code might deal with yield
additionally if required? I would put then comment to web radio example that in case of any issues it's worth to experiment in different ways, like @philippedc in own source code.
@nopnop2002 does it lose the signal by the same way with all stations?
@baldram I have left the idea of a yield or a delay in the library. I'm sure now the problem of clicking comes from client.read for some radio stations, unfortunately it happens for the one I listen the most. It is not a question of speed, this station is 64k, therefore some 128k reception are ok. The strangest thing is that reception is good at the beginning, the clicking effect grows slowly after a while (about 10 seconds)
@philippedc
I have left the idea of a yield or a delay in the library problem of clicking comes from client.read for some radio stations,
Thank you for clarification.
unfortunately, it happens for the one I listen the most
Sadly to hear that.
PS: On the other hand, looking at Edzelf's main radio loop, he is yielding a lot in the method mentioned below. So it's worth to keep this ESP feature in mind for some cases. https://github.com/Edzelf/Esp-radio/blob/e1639010a80a6516191cc15a900599f8a6794dd4/Esp_radio.ino#L2069-L2070
@philippedc please send me address of that 64k station. I will check on my radio.
@fabitom here is the clicking station: http://icecast.radiofrance.fr/franceculture-lofi.mp3 -> 64k or http://icecast.radiofrance.fr/franceculture-midfi.mp3 -> the same in 128K, worst reception, crash after few minutes
This one is loosing signal from time to time, to get it back I change of station then I come back to it: http://live02.rfi.fr/rfiafrique-64.mp3 or http://live-reflector.ice.infomaniak.ch/rfiafrique-64.mp3 -> the same radio station with the same loosing signal.
I have not yet studied in detail how Edzelf get the streaming, may be its method is more accurate.
@philippedc All good here. Streams are ok.
That does not help me.... :(
in this case:
' if( client.available() && !pause ) {
for( byte i=0; i<32; i++ ) {
mp3buff[i] = client.read();
delayMicroseconds(1);
}
player.playChunk(mp3buff, 32); '
the return value of client.read() is a byte.
In this case:
'uint32_t maxfilechunk = client.available();
if(maxfilechunk > 0) {
if( maxfilechunk > 1024 ) maxfilechunk = 1024;
while( ringspace() && maxfilechunk-- ) putring(client.read());
while(rcount) {
while(!player.data_request()) delay(1);
playRing(getring());'
}
}
the return value of client.available() is a long. On the documentation I read "data available" but it consists of what ?
Can you provide your full source ? and please use 4x -> ```` before and after code. At first you can't read in for loop 32 bytes if you don't konw if 32 bytes available, you need check client.available() >= 32. Idk rest of your code, what is rcount etc. please attach full source. client.available() return how much you can read at this moment.
@fabitom it is the code you provide for a ring buffer: https://github.com/baldram/ESP_VS1053_Library/issues/44#issuecomment-576849568
@philippedc But further you modified it slightly I guess. So I think @fabitom asks about the version you use right now. Or is it exactly like in the mentioned comment? Also, @fabitom mentioned that streams "are ok". However, if I remember you said that the clicking effect or rebooting shows up after some time of listening (not immediately). I'm not sure whether @fabitom did a quick check only.
I checked first three station for about 10-15 minutes and 5 minutes for the last one. There was 0 (breaks or lost packages), client.available() always was at >0.
Please check exactly that code: and try to test with: CLIENT_BUFF from 256 to 8192 RING_BUF_SIZE from 10000 to 30000 VS_BUFF_SIZE only 32 or 64
of course adjust VS1053 PINS :)
#include <Arduino.h>
#include <VS1053.h>
#include <WiFi.h>
#define VS1053_CS 5
#define VS1053_DCS 16
#define VS1053_DREQ 4
#define VOLUME 80
#define VS_BUFF_SIZE 32
#define RING_BUF_SIZE 20000
#define CLIENT_BUFF 2048
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);
WiFiClient client;
const char* ssid = "TP-Link";
const char* password = "xxxxxxxx";
const char *host = "icecast.radiofrance.fr";
const char *path = "/franceculture-midfi.mp3";
int httpPort = 80;
uint16_t rcount = 0;
uint8_t* ringbuf;
uint16_t rbwindex = 0;
uint8_t* mp3buff;
uint16_t rbrindex = RING_BUF_SIZE - 1;
inline bool ringspace() {
return ( rcount < RING_BUF_SIZE );
}
void putring(uint8_t b ) {
*(ringbuf + rbwindex) = b;
if ( ++rbwindex == RING_BUF_SIZE ) {
rbwindex = 0;
}
rcount++;
}
uint8_t getring() {
if ( ++rbrindex == RING_BUF_SIZE ) {
rbrindex = 0;
}
rcount--;
return *(ringbuf + rbrindex);
}
void playRing(uint8_t b) {
static int bufcnt = 0;
mp3buff[bufcnt++] = b;
if (bufcnt == sizeof(mp3buff)) {
player.playChunk(mp3buff, bufcnt);
bufcnt = 0;
}
}
void setup() {
Serial.begin(115200);
mp3buff = (uint8_t *) malloc (VS_BUFF_SIZE);
ringbuf = (uint8_t *) malloc (RING_BUF_SIZE);
SPI.begin();
player.begin();
player.switchToMp3Mode();
player.setVolume(VOLUME);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
if (!client.connect(host, httpPort)) {
Serial.println("Connection failed");
return;
}
client.print(String("GET ") + path + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Icy-MetaData: 1" + "\r\n" +
"Connection: close\r\n\r\n");
}
void loop() {
uint32_t maxfilechunk;
if(!client.connected()){
Serial.println("Reconnecting...");
if(client.connect(host, httpPort)){
client.print(String("GET ") + path + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Icy-MetaData: 1" + "\r\n" +
"Connection: close\r\n\r\n");
}
}
maxfilechunk = client.available();
if(maxfilechunk > 0){
if ( maxfilechunk > CLIENT_BUFF ) {
maxfilechunk = CLIENT_BUFF;
}
while ( ringspace() && maxfilechunk-- ) {
putring(client.read());
}
yield();
while (rcount && (player.data_request())) {
playRing(getring());
}
}
}
edited: please modify Icy-MetaData: 1 to Icy-MetaData: 0
@baldram yes I make many tries, however the main code I use is still your example.
@fabitom I test your program. I replace #include
If you remember few months ago I opened a thread because the code did not run with updated ESP8266 core. Since this time the version grows up from 2.4.2 to 2.63, I've tried this last one but it still aborts for the same wire.h problem.
May be I do not have a good reception for a few particular radio stations because of the compiling environment ? I mean may be the Arduino IDE 1.8.10 with 2.4.2 ESP8266 core only gives a result not optimized ? Must I install platformIO to get a better use of the ESP ?
Latest 8266 package for platformio is 2.3.3 Did you try some old versions (entry in platformio.ini)?
platform = espressif8266@2.2.3
or
platform = espressif8266@2.3.1
or
platform = espressif8266@2.3.3
I've d1 mini here but no free vs1053 for test. Maybe on Friday.
@fabitom I tested your code using my esp32 + ArduinoIDE after modify Icy-MetaData: 1 to Icy-MetaData: 0.
The ringbuffer works well and plays smoothly. But sometimes loses network connection.
I have added errno indication to my esp-idf code. errno is 128 when an error occurs.
W (1826146) CLIENT: read_len = -1
W (1826146) CLIENT: errno = 128
I (1826146) CLIENT: Finish
There is some information about errno 128. But there is no solution.
@nopnop2002 What is your RSSI value ? WiFi.RSSI()
@fabitom
void setup() {
Serial.begin(115200);
mp3buff = (uint8_t *) malloc (VS_BUFF_SIZE);
ringbuf = (uint8_t *) malloc (RING_BUF_SIZE);
SPI.begin();
player.begin();
player.switchToMp3Mode();
player.setVolume(VOLUME);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
for(int i=0;i<10;i++) {
Serial.print("RSSI=");
Serial.println(WiFi.RSSI());
delay(1000);
}
Serial.print("ESP-IDF version:");
Serial.println(esp_get_idf_version());
if (!client.connect(host, httpPort)) {
Serial.println("Connection failed");
return;
}
client.print(String("GET ") + path + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Icy-MetaData: 0" + "\r\n" +
"Connection: close\r\n\r\n");
}
void loop() {
uint32_t maxfilechunk;
if(!client.connected()){
Serial.println("Reconnecting...");
for(int i=0;i<10;i++) {
Serial.print("RSSI=");
Serial.println(WiFi.RSSI());
delay(1000);
}
if(client.connect(host, httpPort)){
client.print(String("GET ") + path + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Icy-MetaData: 0" + "\r\n" +
"Connection: close\r\n\r\n");
}
}
maxfilechunk = client.available();
if(maxfilechunk > 0){
if ( maxfilechunk > CLIENT_BUFF ) {
maxfilechunk = CLIENT_BUFF;
}
while ( ringspace() && maxfilechunk-- ) {
putring(client.read());
}
yield();
while (rcount && (player.data_request())) {
playRing(getring());
}
}
}
RSSI=-47
RSSI=-48
RSSI=-49
RSSI=-47
RSSI=-48
RSSI=-49
RSSI=-49
RSSI=-49
RSSI=-49
RSSI=-51
ESP-IDF version:v3.2.3-14-gd3e562907
Reconnecting...
RSSI=-52
RSSI=-53
RSSI=-53
RSSI=-51
RSSI=-53
RSSI=-51
RSSI=-52
RSSI=-51
RSSI=-51
RSSI=-51
My Environment: Arduino 1.8.12
ESP-IDF included in Arduino-Core is very old. https://github.com/espressif/esp-idf/releases/tag/v3.2.3
Your RSSI are verry good. Can you remove that client.connected{} block in loop function and test it ? Try only with connection in setup function. Put some logs if maxfilechunk < 1
if(maxfilechunk > 0){
...
} else {
Serial.println('no data');
Delay(100);
}
maxfilechunk = client.available();
if(maxfilechunk > 0){
if ( maxfilechunk > CLIENT_BUFF ) {
maxfilechunk = CLIENT_BUFF;
}
while ( ringspace() && maxfilechunk-- ) {
putring(client.read());
}
yield();
while (rcount && (player.data_request())) {
playRing(getring());
}
} else {
Serial.print("maxfilechunk=");
Serial.println(maxfilechunk);
//Serial.println("no data");
delay(100);
}
Immediately after startup, maxfilechunk = 0 continues for a while. After that, it will play normally.
RSSI=-46
RSSI=-49
RSSI=-48
RSSI=-49
RSSI=-49
RSSI=-51
RSSI=-48
RSSI=-49
RSSI=-49
RSSI=-49
ESP-IDF version:v3.2.3-14-gd3e562907
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
maxfilechunk=0
or just count about 5-10sec when client.available = 0 and then reconnect. Hm... need to test this leter.
I changed my code a bit:
maxfilechunk = client.available();
if(maxfilechunk > 0){
if ( maxfilechunk > CLIENT_BUFF ) {
maxfilechunk = CLIENT_BUFF;
}
while ( ringspace() && maxfilechunk-- ) {
putring(client.read());
}
yield();
while (rcount && (player.data_request())) {
playRing(getring());
}
} else {
Serial.print(millis());
Serial.print(" ");
Serial.print("maxfilechunk=");
Serial.println(maxfilechunk);
//Serial.println('no data');
delay(100);
}
Immediately after startup, maxfilechunk = 0 continues for a while. After that, it will play normally for a while. (Between 26153 and 916683) Then again maxfilechunk = 0 forever.
RSSI=-53
RSSI=-53
RSSI=-52
RSSI=-52
RSSI=-52
RSSI=-53
RSSI=-53
RSSI=-52
RSSI=-53
RSSI=-51
ESP-IDF version:v3.2.3-14-gd3e562907
24635 maxfilechunk=0
24736 maxfilechunk=0
24836 maxfilechunk=0
24960 maxfilechunk=0
25060 maxfilechunk=0
25175 maxfilechunk=0
25275 maxfilechunk=0
25390 maxfilechunk=0
25490 maxfilechunk=0
25605 maxfilechunk=0
25705 maxfilechunk=0
25820 maxfilechunk=0
25920 maxfilechunk=0
26052 maxfilechunk=0
26153 maxfilechunk=0
916683 maxfilechunk=0
916783 maxfilechunk=0
916883 maxfilechunk=0
916983 maxfilechunk=0
917083 maxfilechunk=0
917183 maxfilechunk=0
917283 maxfilechunk=0
917383 maxfilechunk=0
917483 maxfilechunk=0
917583 maxfilechunk=0
917683 maxfilechunk=0
917783 maxfilechunk=0
917883 maxfilechunk=0
917983 maxfilechunk=0
918083 maxfilechunk=0
918183 maxfilechunk=0
918283 maxfilechunk=0
918383 maxfilechunk=0
918483 maxfilechunk=0
918583 maxfilechunk=0
918683 maxfilechunk=0
918783 maxfilechunk=0
918883 maxfilechunk=0
918983 maxfilechunk=0
919083 maxfilechunk=0
919183 maxfilechunk=0
919283 maxfilechunk=0
919383 maxfilechunk=0
919483 maxfilechunk=0
919583 maxfilechunk=0
919683 maxfilechunk=0
919783 maxfilechunk=0
919883 maxfilechunk=0
919983 maxfilechunk=0
920083 maxfilechunk=0
920183 maxfilechunk=0
Hi guys, I have also did some tests in this case. I have used the code from https://github.com/baldram/ESP_VS1053_Library/issues/47#issuecomment-599659073
My settings are:
#define VS_BUFF_SIZE 32
#define RING_BUF_SIZE 20000
#define CLIENT_BUFF 2048
My hardware is: NodeMCU v0.9 (which uses ESP8266) with VS1053 board. My software is: esp8266-2.3.0
First URL under test: ice3.somafm.com/u80s-64-aac it plays perfect, no sound clicks or glitches.
Second URL under test: icecast.radiofrance.fr/franceculture-lofi.mp3 it plays but not perfect. I heard some "clicks" or mostly some kind of short glitches (like in duration of 100ms?). Those glitches took place every few seconds. Sometimes I heard like I was under water or something. Those glitches are a bit annoying.
I have found a difference between those two streams: the first one is aac and the second is mpeg. Maybe it is related? I didn't do further tests.
I have used curl to get the stream informations: For the first stream:
$ curl -H "Icy-MetaData: 1" -v "ice3.somafm.com/u80s-64-aac" >/dev/null
* STATE: INIT => CONNECT handle 0x6000830c8; line 1491 (connection #-5000)
* Added connection 0. The cache now contains 1 members
* STATE: CONNECT => WAITRESOLVE handle 0x6000830c8; line 1532 (connection #0)
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 198.24.44.210:80...
* TCP_NODELAY set
* STATE: WAITRESOLVE => WAITCONNECT handle 0x6000830c8; line 1611 (connection #0)
* Connected to ice3.somafm.com (198.24.44.210) port 80 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x6000830c8; line 1667 (connection #0)
* Marked for [keep alive]: HTTP default
* STATE: SENDPROTOCONNECT => DO handle 0x6000830c8; line 1685 (connection #0)
> GET /u80s-64-aac HTTP/1.1
> Host: ice3.somafm.com
> User-Agent: curl/7.66.0
> Accept: */*
> Icy-MetaData: 1
>
* STATE: DO => DO_DONE handle 0x6000830c8; line 1756 (connection #0)
* STATE: DO_DONE => PERFORM handle 0x6000830c8; line 1877 (connection #0)
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
* Marked for [closure]: HTTP/1.0 close after body
< HTTP/1.0 200 OK
< Content-Type: audio/aacp
< Date: Tue, 17 Mar 2020 21:59:03 GMT
< icy-br:64
< icy-genre:80s Synthpop
< icy-name:Underground 80s [SomaFM]
< icy-notice1:<BR>This stream requires <a href="http://www.winamp.com/">Winamp</a><BR>
< icy-notice2:SHOUTcast Distributed Network Audio Server/Linux v1.9.5<BR>
< icy-pub:0
< icy-url:http://somafm.com
< Server: Icecast 2.4.0-kh10
< Cache-Control: no-cache, no-store
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type
< Access-Control-Allow-Methods: GET, OPTIONS, HEAD
< Connection: Close
< Expires: Mon, 26 Jul 1997 05:00:00 GMT
< icy-metaint:16000
<
{ [2822 bytes data]
100 308k 0 308k 0 0 36411 0 --:--:-- 0:00:08 --:--:-- 7993
and for the second
$ curl -H "Icy-MetaData: 1" -v "icecast.radiofrance.fr/franceculture-lofi.mp3" >/dev/null
* STATE: INIT => CONNECT handle 0x6000830c8; line 1491 (connection #-5000)
* Added connection 0. The cache now contains 1 members
* STATE: CONNECT => WAITRESOLVE handle 0x6000830c8; line 1532 (connection #0)
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 143.204.233.75:80...
* TCP_NODELAY set
* STATE: WAITRESOLVE => WAITCONNECT handle 0x6000830c8; line 1611 (connection #0)
* Connected to icecast.radiofrance.fr (143.204.233.75) port 80 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x6000830c8; line 1667 (connection #0)
* Marked for [keep alive]: HTTP default
* STATE: SENDPROTOCONNECT => DO handle 0x6000830c8; line 1685 (connection #0)
> GET /franceculture-lofi.mp3 HTTP/1.1
> Host: icecast.radiofrance.fr
> User-Agent: curl/7.66.0
> Accept: */*
> Icy-MetaData: 1
>
* STATE: DO => DO_DONE handle 0x6000830c8; line 1756 (connection #0)
* STATE: DO_DONE => PERFORM handle 0x6000830c8; line 1877 (connection #0)
* Mark bundle as not supporting multiuse
* HTTP 1.1 or later with persistent connection
< HTTP/1.1 200 OK
< Content-Type: audio/mpeg
< Transfer-Encoding: chunked
< Connection: keep-alive
< Date: Tue, 17 Mar 2020 22:00:03 GMT
< icy-br: 32
< ice-audio-info: channels=1;samplerate=48000;bitrate=32
< icy-br: 32
< icy-name: franceculture-lofi.mp3
< icy-pub: 1
< Server: Icecast 2.4.0-kh13
< Cache-Control: no-cache, no-store
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type, Icy-MetaData
< Access-Control-Allow-Methods: GET, OPTIONS, HEAD
< Expires: Mon, 26 Jul 1997 05:00:00 GMT
< X-Cache: Miss from cloudfront
< Via: 1.1 c2c75215aa2ab067e062055fa68a3fdf.cloudfront.net (CloudFront)
< X-Amz-Cf-Pop: CPH50-C1
< X-Amz-Cf-Id: SX5KCxOVfP1YruXaagwqvvyJ6fb7nTc6jWCkzJmKDaIF-BGL-0K0-g==
<
{ [2403 bytes data]
100 103k 0 103k 0 0 35869 0 --:--:-- 0:00:02 --:--:-- 36100
Maybe it is harder for VS1053 to play mpeg than aac?
Thanks @wmarkow I'm feeling less alone :)
My working radio is much more complicated then code I send you guys so I've some more code for vs1053. The main question, do you guys tested on vs1053 latest patch ? I've included that patch. Maybe thats diffirence... especially for aac.
@fabitom I've tested several Arduino IDE version (1.8.5, 1.8.7, 1.8.10) and several ESP8266 core (2.3.0, 2.4.0, 2.4.1, 2.4.2, 2.6.3) from arduino.esp8266.com/stable/package_esp8266com_index.json only the 2.4.2 package allows the baldram web radio example to work as I described, with some clicks and lost signal. Your ring buffer version is not giving sound. I have not tested compilation from platformio yet, it looks much more complicated to set....
@wmarkow would you mind to test with RFI http://live02.rfi.fr/rfiafrique-64.mp3 if you have the signal lost after a while ( like me ) ? The signal can disappear after few seconds to more than half an hour.
Hello.
client.read() also reads the HTTP header.
There is no fatal problem, but you can exclude the HTTP header as follows.
My Code:
Test result: