baldram / ESP_VS1053_Library

A library for VS1053 MP3 Codec Breakout adapted for Espressif ESP8266 and ESP32 boards.
https://platformio.org/lib/show/1744/ESP_VS1053_Library
GNU General Public License v3.0
113 stars 37 forks source link

A way to suppress the glitches and other streaming troubles #52

Closed philippedc closed 3 years ago

philippedc commented 4 years ago

Hi, I love the baldam exemple web radio. I built 3 of them. Unfortunately I have 2 problems with this code, especially with French radio station:

I have spent may be an hundred of hours to try to solve this problem. I thank wmarkow and fabitom for their help. In https://github.com/baldram/ESP_VS1053_Library/issues/51 they tried several workarounds like round buffer, but are mostly incomprehensible for my basic level of programming. But I learnt the following: The glitches are due to \r\nX\r\n sequences, and then it looks like the streaming is chunked. Works had been done to suppress these chunk messages, see https://github.com/baldram/ESP_VS1053_Library/pull/48, but I still have glitches for these particular French radios. Moreover, wmarkow and fabitom confirm that their codes are working well for themselves, but not for me :(

There is not many information about chunked transfer data, except this https://en.wikipedia.org/wiki/Chunked_transfer_encoding When you read in detail, follow the links, you will find that chunked data stream is mostly for video transfer, here it is sound only, so I'm wondering if these chunks are not fake.... AND chunked transfer is only supported for HTTP1.1. Not in HTTP1.0

EUREKA !

@baldram I suggest to replace:

client.print(String("GET ") + path + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n\r\n");

with:

client.print(String("GET ") + path + " HTTP/1.0\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n\r\n");

It is a miracle: no more glitches, no lost stations, everything is fine now :)

fabitom commented 4 years ago

Probably with http/1.0 server sending not chunked stream because 1.0 doesn't support chunked transfer encoding.

baldram commented 4 years ago

I love the baldam exemple web radio.

In fact, the radio example was delivered by vincegellar based on his hardware+software project (using this vS1053 library).

Moreover, wmarkow and fabitom confirm that their codes are working well for themselves, but not for me :(

Maybe it's also about the hardware. There is a number of different boards. I will try also with one of my boards for mentioned radio stations.

I'm wondering if these chunks are not fake.... AND chunked transfer is only supported for HTTP1.1. Not in HTTP1.0 EUREKA !

Ok, this is also the way to work around the problem. I had a look to Edzelf and he is using HTTP/1.1. So maybe I will just add a comment to the radio example code to suggest experimenting also with HTTP/1.0. I will also add a reference to this issue and other issues where additional solutions were discussed.

Probably http/1.0 doesn't support chunked transfer encoding.

Hmm, this might be the thing. The good is that workaround works.

ewbarnes53 commented 4 years ago

I ran the WebRadioChunked sketch, and to my ear, it sounds much better. My wife is a trained professional musician, and she reported that it sounded worse than the original, non-chunked radio.

I say it sounds better, because there is less of the clicking going on. I found that very annoying.

But my wife may have a point. It may be that the chirping and burbling on this version is more frequent. I am not sure how to best describe the sound, I don't know how to make a recording.

I would say that the audio has a watery sound, some times. Like a singer trying to sing with a mouth full of water.

So thanks for the updated code. It sounds better to me.

philippedc commented 4 years ago

the watering effect may be due by a part of the streaming is lost. I made tests to listen a stream with few lost bytes, and I get this effect.

fabitom commented 4 years ago

@ewbarnes53 did you add build_flags = -D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH ? please look at RingBufferDemo.cpp https://github.com/baldram/ESP_VS1053_Library/pull/54/commits

ewbarnes53 commented 4 years ago

I saw this, but did not understand what it was, or how it worked, so I removed it. I am using the ESP32 from Adafruit, so I don't know if any changes are needed. Sorry. I do not have a clue here.

Suddenly, a couple of nights ago, my Web Radio Player started working. For most stations now, the worst I am seeing is occasional drop outs. One channel has watery sounding audio still.

Update: Ok, now I see some references to platformIO. I don't think I am going to install and learn a new tool. Sorry about that.

fabitom commented 4 years ago

@ewbarnes53 nwm, that option is for esp8266. But my pull request can help with proper buffering stream.

baldram commented 4 years ago

@ewbarnes53 Would you willing to test this RingBufferDemo.cpp whether it works any better with your stations? I see @fabitom did this example great for both ESP8266 and ESP32 boards. So without any additional effort, it should simply run with your set up.

ewbarnes53 commented 4 years ago

I am now running the RingBufferDemo sketch. I am connected to a 320 kbps station. It seems to be working very well. The print statement doesn't tell me much. It always prints 0.

fabitom commented 4 years ago

I am now running the RingBufferDemo sketch. I am connected to a 320 kbps station. It seems to be working very well. The print statement doesn't tell me much. It always prints 0.

hm... you should see 0-100%, its percent of used buffer space. 100% means full buffer with ready data to play. But in your case it can be problem with display terminal, at 320kbps with 0 buffer you should hear problems with audio. I will check again my demo.

ewbarnes53 commented 4 years ago

How strange. The only change I made was moving from one room to another (my amplified speakers are in a different room). Anyhow... most of the time it is now showing 100%. Once in a while, I see it change to a different value, but the audio sounds fine. I have tried playing both my 320 kbps stream, and the one you were using.

baldram commented 4 years ago

the audio sounds fine

@ewbarnes53 That's good news! Does it mean that stations making issues earlier are now okay?

to my ear, it sounds much better. My wife is a trained professional musician, and she reported that it sounded worse than the original, non-chunked radio

Did it also help to get rid of this other issue now?

baldram commented 4 years ago

Ping @ewbarnes53 ;-)

ewbarnes53 commented 4 years ago

Sorry, I really wasn't ignoring you. I have been playing with the radios, trying to figure out what might have happened. I really am not sure. I will say that the radio I prefer is the Ring Buffer radio. Most stations sound very good. There may be occasional dropouts when the stream is interrupted for an extended period. I have seen the buffer % go down to 0, and some times, it keeps playing.

I am puzzled about my earlier problems. They seem to have disappeared. I am wondering if I had some problem with my connection to the internet, that has now somehow been corrected.

fabitom commented 4 years ago

@ewbarnes53 when you see 0% and radio keeps playing that means stream is directly sent to vs0153 without buffering, then every package drop will case clicking. You can try to adjust RING_BUF_SIZE, if you have enough free heep try to increase (Im working on 34000 with esp32).

fabitom commented 4 years ago

@ewbarnes53 there is some problem with network speed on esp32 when you use 320kbps or more. I see where is the problem. Testing....

ewbarnes53 commented 4 years ago

I do not seem to have any problem with 320 kbps streams. I have tuned 2 or 3 in without problem. At first, I did not change any of your buffer sizes, and it seemed to work fine. I have now increased the ring buffer size to 36,000 bytes, just to see if it would compile and run. I suppose there is some performance improvement, but I really cannot see any difference.

fabitom commented 4 years ago

that depends, when you have more other services (like me, web server, display, etc.) you can see diffirence. I tested on flac ~1000kbps and I see big diffirence now. The problem was with reading byte by byte from network. My esp32 get fresh air now with reading 1024 at onces, it matters a lot. New version here: https://github.com/fabitom/ESP_VS1053_Library/blob/ring-buffer-demo-v2/examples/WebRadioDemo/RingBufferDemo.cpp

zeredbox commented 3 years ago

Hello @baldram,

I just wanted to write to thank you and I even created an account on GitHub especially for this :-)

I just wanted to thank you for the ESP_VS1053_Library. I have spent hours reading web pages, making projects, looking for information and making montages that don't work or work very badly. With ESP_VS1053_Library I could finally hear for the first time a "hello" from an MP3 file and then an online radio.

What I'm writing to you for is mainly to find solutions to the sound glitches that we hear on some French radio stations. My wife listens to these stations (France Inter for esample) and... all my beautiful montages are useless if you can't listen to these stations :-\ Thanks to the sketch found on your page : https://github.com/baldram/ESP_VS1053_Library/pull/48/files the gliches have finally disappeared !!!

This evening I'll just try to simply change the

client.print(String("GET") + path + "HTTP/1.1\r\n")

in

client.print(String("GET") + path + "HTTP/1.0\r\n")

but even if it doesn't work, I know your file works fine.

Really, thank you again. Now that everything works, I can finally get down to the heart of the project: writing the HTML pages of the stations' choice, etc.

Bye

fabitom commented 3 years ago

right, generally, a pure mp3 audio stream can have non-audio data only in two cases: chunked encoding and metadata. First is used mainly for dynamically generated content, not important for audio stream. You can work around this by using http verson 1.0 The second is used to send additional information like title, author, etc. You can disable this with header Icy-MetaData = 0

baldram commented 3 years ago

Great news! Thank you @DindonCurieux for sharing your results. We have it tested now by someone else. Do we need @fabitom any adjustments in the mentioned PR then?

PS: @DindonCurieux do you have a possibility to test this code too? Or have you tested it already? https://github.com/baldram/ESP_VS1053_Library/pull/54

fabitom commented 3 years ago

@baldram it was quite a long time ago and I don't remember the details, but for sure to avoid misunderstanding all examples should have Icy-MetaData=0 header in order to disable sending metadata in stream. Handling metadata is not supported by this library. As example:

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");  
zeredbox commented 3 years ago

@baldram Yesterday I first did the test from the sketch on this page https://github.com/baldram/ESP_VS1053_Library/pull/48/files It works fine without glitches.

Tonight I did the test from https://github.com/fabitom/ESP_VS1053_Library/blob/ring-buffer-demo/examples/WebRadioDemo/RingBufferDemo.cpp The modification of

define HTTPVER "HTTP/1.1

to

define HTTPVER "HTTP/1.0

removes glitches on streams that were causing problems (Radio France).

Was that the meaning of your question?

baldram commented 3 years ago

@DindonCurieux Yes, thanks. So it looks like both codes are solving mentioned glitched issue. Excellent 🥳

Dr-Dawg commented 3 years ago

Hi all, just like @DindonCurieux I just created a GitHub account in order to leave a comment here.

First of all, thanks a lot to @baldram, @vincegellar, @fabitom @maniacbug @edzelf ,..., for sharing your experience, the WebRadioDemo is a great starting point for creating your own Inernet Radio project.

I hope you guys can give me a hint, I happen to have streamig issues with one particular radio station, which unfortunately is my favourite one over the past years: Double J, http://live-radio01.mediahubaustralia.com/DJDW/mp3 or http://live-radio02.mediahubaustralia.com/4DJW/mp3/

The stream seems to stop for a millisec every one or two seconds. However, VLC, Mozilla and the 2003 Version of Winamp do not seem to have any problems. So far I was not able to solve this issue. What I tried so far( and reading your comments was a great source of inspiration ) ( my first idea was the playback speed, because some problems on other stations vanished after setting the ESP8266 clock to 160 )

What I encountered is that the value of bytesread is pretty often lower (about five times per mp3 frame) than the requested size for mp3buff. However, the Byte Count at the next Sync Bytes shows, that all bytes seem to be tranferred correctly, i.e. no meta data seems to be sent(even requesting meta data and not passing it to the ringbuffer doesn't help)

The header of the stream is:

ICY 200 OK icy-notice1:
This stream requires Winamp
icy-notice2:SHOUTcast DNAS/posix(linux x64) v2.4.7.256
icy-name:Double J NSW icy-genre:Misc icy-br:96 icy-url:http://www.abc.net.au/radio icy-pub:0 content-type:audio/mpeg X-Clacks-Overhead:GNU Terry Pratchett

I'm slowly running out of ideas, maybe one of you could test whether the stream produces microbreaks on your hard/software, too?

One last idea I have is again the playback speed at bitrate 96, I remember, that my Bose used to sound terrible playing Double J with varying playback speed, until one or two years ago, maybe due to an update, now everything sounds fine.

Which brings me to the question: Has anyone ever tried to add the following line to the VS1053.h ?

const uint8_t SM_STREAM = 6; // Bitnumber in SCI_MODE for Streaming Mode

and play around with this setting? The VS1003 data sheet says: "SM STREAM activates VS1003’s stream mode. In this mode, data should be sent with as even intervals as possible (and preferable with data blocks of less than 512 bytes), and VS1003 makes every attempt to keep its input buffer half full by changing its playback speed upto 5%. For best quality sound, the average speed error should be within 0.5%, the bitrate should not exceed 160 kbit/s and VBR should not be used. For details, see Application Notes for VS10XX. This mode does not work with WMA files."

Thanks again for your great work! :-)

Edzelf commented 3 years ago

I tested this station (live-radio02.mediahubaustralia.com/4DJW/mp3/) on my ESP32 Radio. It does not sound too bad, but what I see is that the input stream (96 kbps) is empty most of the time: Free memory is 203204, chunks in queue 39, stream 0, bitrate 96 kbps Other station: Free memory is 196388, chunks in queue 377, stream 6796, bitrate 192 kbps This means that the sender transmits a bit slower than 96 kbps. So maybe it would be a good idea to check the stream mode. I also tested this station on my ESP8266 radio, and it did not play....

Dr-Dawg commented 3 years ago

@Edzelf

Thanks a lot! This probably corresponds with the VLC media info/statistics, while the data bitrate is announced with 96, the input bitrate switches between 94 and 97, sometimes 89...

zeredbox commented 3 years ago

@Dr-Dawg

I fully associate myself with your thanks to @baldram, @vincegellar, @fabitom @maniacbug @Edzelf for the great work they make available to everyone.

I did the test of the http://live-radio02.mediahubaustralia.com/4DJW/mp3/ feed. on an ESP32. Unfortunately, like you, I have a sound that stops about every second and is very jerky. I don't see what I can do about it.

But maybe something could put us on the way to a solution : when you listen to the radio station on ESP and at the same time you are connected to the station on a web page, the two streams gradually go out of sync. After a few minutes, the ESP "lags" and no longer broadcasts the same content as the web page at all. This means that a song may already be finished on the web page while it continues to be played on the ESP for many seconds. Unfortunately, this is all I can do to help :-\

baldram commented 3 years ago

Unfortunately, no additional hints from my side apart from earlier mentioned in this and the other thread (#47). However, I would like to add kudos to @wmarkow also for his contribution.

Seen similar issues (stops playing accidentally) for some radio stations even on commercial radio devices like: Creative or iRiver (Astell&Kern).

vincegellar commented 3 years ago

At the moment I don't have a complete test setup built. I will try to cobble together a minimal setup for testing purposes in the coming days.

If I can come up with some kind of a solution I will report back.

Dr-Dawg commented 3 years ago

@DindonCurieux Thanks for the reproducible hint, the ESP indeed seems to play the stream "too slow", which goes along with Edzelfs comment on the stream not really playing at 96kbps.

I will report back, too, if I find any solution..

Edzelf commented 3 years ago

In fact, the ESP32 plays too fast, or exactly at 96kbps. The inputstream seem to be too slow.

vincegellar commented 3 years ago

So, bad news, my VS1053 board seems to have died since the last time I hooked it up to anything. I will order a new one, but it will be quite longer before I can test anything out.

Dr-Dawg commented 3 years ago

Hi there,

my problem is solved.

For the sake of completeness first here's what didn't work, but might be interesting: I added

    const uint8_t SM_STREAM = 6;            // Bitnumber in SCI_MODE for Streaming Mode

and

    //  Streaming Mode On
    void streamModeOn();

    //  Streaming Mode Off
    void streamModeOff();  

to VS1053.h

and

void VS1053::streamModeOn() {
    LOG("Performing streamModeOn\n");
    write_register(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_STREAM));
    delay(10);
    await_data_request();
}

void VS1053::streamModeOff() {
    LOG("Performing streamModeOff\n");
    write_register(SCI_MODE, _BV(SM_SDINEW));
    delay(10);
    await_data_request();
}

to VS1053.cpp

making it possible to switch the VS1003's stream mode on and off during playback. The effect is "experimental", varying playback speed showing that the data is not sent in even intervals as required. Still it might be useful for some application.

Dr-Dawg commented 3 years ago

Now to the solution:

I noticed the same effect( microbreaks, ESP out of sync, playback falling behind ) on other Radio stations after playing for 20-30 minutes. Obviously due to a lot of computing and serial traffic I was falling behind in reading the stream and reached the end of the Internet station's buffer.

The main reason for this was my suboptimal ;-) implementation of a ring buffer. I checked the ring-buffer-demo-v2 of @fabitom and it worked..

The main difference and maybe the reason why the WebRadio demo also has trouble for this particular stream ( Double J ): In fabitoms ringbufferdemo the buffer is only played if player.data_request() is true, by just using player.playChunk the main loop is paused in the sdi_send_buffer command until the VS1003/1053's buffer has place for another 32 bytes. Furthermore, I placed the player.playChunk command after the if client.available() > 0) statement, which makes perfect sense for the simple demo, but not for using a buffer.

As far as I can see, all of this is implemented in the code of @Edzelf , so I guess the stream caused no problem here at all.

Unfortunately, I see no simple way of modyfing the WebRadio demo to handle this.

Thanks a lot!

baldram commented 3 years ago

Hi All, I'm about closing this issue.

For now we have two PRs with a simple example on how to improve data streaming and get rid of unwanted artefacts:

The more complex example by @CelliesProjects uses a data patch (aka plugin) feature to apply these patches. These are VS1053b Patches v2.9 and they help to get rid of some streaming problems, as well as handle ID3 tag things better (so that binary data inside the tag is not erroneously interpreted as audio), and so on. There is a ESP32_VS1053_Stream version based on this library (ESP_VS1053_Library) and example player eStreamPlayer32_VS1053. An idea would be to "integrate patches support" into ESP_VS1053_Library.

I opened a discussion here https://github.com/baldram/ESP_VS1053_Library/discussions/66 to discuss further steps . Whether we would like to:

Would you please leave your thoughts in https://github.com/baldram/ESP_VS1053_Library/discussions/66?

CC: @wmarkow @fabitom @philippedc @ewbarnes53 @DindonCurieux @Dr-Dawg @Edzelf @vincegellar

baldram commented 3 years ago

An important change related to this topic was delivered https://github.com/baldram/ESP_VS1053_Library/pull/69. As discussed in https://github.com/baldram/ESP_VS1053_Library/discussions/66, it enables a possibility for applying vs1053 Firmware patches (binary patch files that can easily be loaded to the memory of VS10XX by a microcontroller to fix known firmware bugs).

I'm closing an issue. If about questions in a comment above, they are still valid. If anyone has any insights, it will be very welcome and appreciated. Further discussion still possible here: https://github.com/baldram/ESP_VS1053_Library/discussions/66 or by opening a new discussion here.