MrBuddyCasino / ESP32_MP3_Decoder

A internet radio and bluetooth speaker project for the Espressif ESP32
782 stars 182 forks source link

reading from broadcast #31

Closed frankipl closed 6 years ago

frankipl commented 6 years ago

Hi MrBuddyCasino, Would it be possible to read broadcasted mp3 data from UDP port? I have 80 devices with ESP32 modules in single wifi network, I would like to setup a Linux server that will stream 16 channels to broadcast address on different port and I would like ESP modules to connect to one of 16 channels. The idea is to have lower wifi usage (16 UDP streams) instead of 80 TCP/IP simultaneous connections. Best Regards Marek

MrBuddyCasino commented 6 years ago

80 devices with ESP32 modules Interesting. Is that an art project or something? For so many devices, have you looked into the ESPNow protocol?

frankipl commented 6 years ago

This is commercial project. I did look into ESPNow just now ;) but it seems that this is not what I'm looking for. Total number of peers should be less than 20. In this project 80 devices is located in double decker bus and they receive audio stream for passengers. All at once

MrBuddyCasino commented 6 years ago

I see, some kind of tourist guide I suppose? UDP is not yet supported, but a raw MP3 stream with a custom udp:// protocol handler shouldn't be too difficult. I usually accept well-written pull requests.

frankipl commented 6 years ago

Yes it is. For now we are playing with your work and it works well ;) I don't know how it will work with 80 devices. Quick estimate is that single mp3 stream is 200kbps so multiply by 80 and it is 16Mbit/s well withing 'g' mode bandwith - 54Mbit/s. Although if this will work with UDP then it is 16x200kb/s On the other hand with TCP we have collision detections and retransmission. Back in old days easiest way to block some network was to send hude data to broadcast - will this be a problem?

MrBuddyCasino commented 6 years ago

The MP3 decoder will try to re-sync if a frame is bad, which means you loose ~418bytes for a 128k bitrate. Not so bad, if transmission errors are rare. If you are doing mostly voice, you could lower the bitrate to 64k / mono.

To increase reliability in congested wifi conditions, you should also at least double the recv buffer size, if you don't need AAC there is spare heap memory available.

frankipl commented 6 years ago

We have increased buffer size to 96000, I don't need AAC so will try to free this memory. In audio stream there is a mix of voice and songs, 128k bitrate seems to be optimal. We have some minor issues during testing but maybe this is due to our experimental board. Board is: https://www.dfrobot.com/product-1590.html, we are using internal DAC One is that from time to time, full buffer suddenly goes to empty like this:

I (124521) audio_player: Buffer fill 97%, 93469 bytes E (131231) mad_decoder: Buffer underflow, need 2515 bytes. ..... E (131811) mad_decoder: Buffer underflow, need 2515 bytes. I (131831) audio_player: Buffer fill 2%, 2079 bytes

It seems to happen more often (but not only) when I'm touching the board but I can't find the pattern or reproduce the problem on demand. Second is that I can hear some static noise during playback, I'm testing with files: Audio file with ID3 version 2.4.0, extended header, contains: MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Monaural

However, the first problem may be wifi related. When I start the playback and I'm watching output from minicom, playback ends with full buffer, like this: I (32320) audio_player: Buffer fill 97%, 93643 bytes E (40700) mad_decoder: Buffer underflow, need 2785 bytes. Server has send all file, and I can hear the end of music, but debug doesn't show that buffer goes to empty.

Best Regards Marek

MrBuddyCasino commented 6 years ago

Error recovery is currently not optimal I think, its possible the decoder tries to resume playback too early. People have tried different solutions in the forum thread, you might want to check those out (task yield, buffer fill etc.).

The internal DAC won't give you good quality, and PDM doesn't work too well either, for currently unknown reasons. You'll want an I2S amp and preferably a chip rev.1 or higher, because then you can use the APLL which sounds better and solves time sync issues because playback is a little too fast without it.

frankipl commented 6 years ago

Regarding first problem I think this is simply some issue with displaying that buffer goes to empty, it simply doesn't show that when there is a lag on wifi network. We want to try with I2S, currently waiting for a chip to arrive from store. Second option for us is to add some microSD card to the final board and read mp3 files from the board, and write to the SD card using wifi from the server (before playback starts) - thats should be easy, but then for some reason we need to play mp3 file with some offset eg. 0+30 seconds, 0+45 seconds, We did that with wav files but I'm not sure whether "rewind" will work with mp3 files. Could you comment on this?

Best Regards Marek

MrBuddyCasino commented 6 years ago

You can seek into constant-bitrate MP3s quite easily I think, it gets difficult with VBR though. I didn't try that yet, but a stupid "seek to byte offset" should work due to self-syncronisation.

If you can get away with preloaded files this will make your job much easier, the 2.4GHz spectrum is very noisy and I suspect it will be hard to make it resilient against dropouts.

frankipl commented 6 years ago

MP3 are loaded from our server so I thought about adding some external library to the server and convert all mp3/wav files to some constant-bitrate format before uploading to SD card. I tried to send some mp3 file cut in half "file.remove(0,file.size()/2)" and it works. I (3050) mad_decoder: decoder start E (3060) mad_decoder: dec err 0x0101 (lost synchronization) E (3060) mad_decoder: dec err 0x0235 (bad main_data_begin pointer) I (3100) audio_player: Buffer fill 97%, 93392 bytes

Sorry if this thread goes a bit long. I have one more question. I need to change SSID and PASS after chip is flashed. I mean it should be flashed with some initial SSID and PASS and then it should connect to the server with that credentials and download new ones, save it and after restart try to connect with new credentials. Any hint on that how we could do that?

Best Regards Marek