Closed gerardwr closed 6 years ago
Howdy,
Can you please post those warnings you're getting? I compile with -Wall and don't get anything in the Audio library (but I do see stuff in SPIFFS and the main ESP arduino libs which I can't touch)...
It looks like things are working fine, you're just losing packets somewhere. The decoder is resyncing and continuing to play from what I can see.
Have you tried adding a buffer between the HTTPStream and the Generator? The README.md shows a simple example...as long as you have memory it's literally a 1-2 line change.
Here's all I get on a clean compile w/-Wall using the latest Arduino and ESP8266Audio Git:
/home/earle/Arduino/libraries/ESP8266Audio/src/AudioGeneratorAAC.cpp: In member function 'virtual bool AudioGeneratorAAC::loop()':
/home/earle/Arduino/libraries/ESP8266Audio/src/AudioGeneratorAAC.cpp:108:69: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (ret = AACDecode(hAACDecoder, &inBuff, &bytesLeft, outSample)) {
^
/home/earle/Arduino/libraries/ESP8266Audio/src/AudioGeneratorAAC.cpp:115:29: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if (fi.sampRateOut != lastRate) {
^
/home/earle/Arduino/libraries/ESP8266Audio/src/libhelix-aac/dequant.c: In function 'raac_DeinterleaveShortBlocks':
/home/earle/Arduino/libraries/ESP8266Audio/src/libhelix-aac/dequant.c:367:41: warning: unused parameter 'aacDecInfo' [-Wunused-parameter]
int DeinterleaveShortBlocks(AACDecInfo *aacDecInfo, int ch)
^
/home/earle/Arduino/libraries/ESP8266Audio/src/libhelix-aac/dequant.c:367:57: warning: unused parameter 'ch' [-Wunused-parameter]
int DeinterleaveShortBlocks(AACDecInfo *aacDecInfo, int ch)
And, as I felt bad having them hanging around, I just cleared up those 4 warnings with the latest push. No functional changes, just stuff to make GCC happy.
Thanks for your response, is appreciated!
The warnings in your post LOOK similar to mine, but I will check in detail later today, and report back. AND I will check the version with the 4 warnings cleared, nice work!
And NO, i didn't try adding a buffer yet, just added my SSID and compiled the standard example sketch.
My turn again, I will report back later. Thx.
These are my warnings with the latest Arduino-ESP8266 GIT and with the former ESP8266Audio GIT:
/Users/gerard/Documents/My Data/ArduinoESP/libraries/ESP8266Audio/src/AudioGeneratorAAC.cpp: In member function 'virtual bool AudioGeneratorAAC::loop()':
/Users/gerard/Documents/My Data/ArduinoESP/libraries/ESP8266Audio/src/AudioGeneratorAAC.cpp:108:69: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (ret = AACDecode(hAACDecoder, &inBuff, &bytesLeft, outSample)) {
^
/Users/gerard/Documents/My Data/ArduinoESP/libraries/ESP8266Audio/src/AudioGeneratorAAC.cpp:115:29: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if (fi.sampRateOut != lastRate) {
^
/Users/gerard/Documents/My Data/ArduinoESP/libraries/ESP8266Audio/src/libhelix-aac/dequant.c: In function 'raac_DeinterleaveShortBlocks':
/Users/gerard/Documents/My Data/ArduinoESP/libraries/ESP8266Audio/src/libhelix-aac/dequant.c:367:41: warning: unused parameter 'aacDecInfo' [-Wunused-parameter]
int DeinterleaveShortBlocks(AACDecInfo *aacDecInfo, int ch)
^
/Users/gerard/Documents/My Data/ArduinoESP/libraries/ESP8266Audio/src/libhelix-aac/dequant.c:367:57: warning: unused parameter 'ch' [-Wunused-parameter]
int DeinterleaveShortBlocks(AACDecInfo *aacDecInfo, int ch)
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp:45:18: warning: unused parameter 'client' [-Wunused-parameter]
virtual bool verify(WiFiClient& client, const char* host)
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp:45:18: warning: unused parameter 'host' [-Wunused-parameter]
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/SD.cpp:233:9: warning: unused parameter 'isLastComponent' [-Wunused-parameter]
boolean callback_pathExists(SdFile& parentDir, char *filePathComponent,
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/SD.cpp:233:9: warning: unused parameter 'object' [-Wunused-parameter]
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/SD.cpp:311:9: warning: unused parameter 'object' [-Wunused-parameter]
boolean callback_remove(SdFile& parentDir, char *filePathComponent,
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/SD.cpp:319:9: warning: unused parameter 'object' [-Wunused-parameter]
boolean callback_rmdir(SdFile& parentDir, char *filePathComponent,
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/Sd2Card.cpp: In member function 'uint8_t Sd2Card::readData(uint32_t, uint16_t, uint16_t, uint8_t*)':
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/Sd2Card.cpp:396:12: warning: unused variable 'n' [-Wunused-variable]
uint16_t n;
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/SdFile.cpp: In static member function 'static uint8_t SdFile::make83Name(const char*, uint8_t*)':
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/SdFile.cpp:262:15: warning: unused variable 'b' [-Wunused-variable]
uint8_t b;
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/SdFile.cpp: In member function 'uint8_t SdFile::rmRfStar()':
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/SdFile.cpp:908:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if (curPosition_ != (32*(index + 1))) {
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_hydrogen.c: In function 'SPIFFS_buffer_bytes_for_filedescs':
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_hydrogen.c:16:49: warning: unused parameter 'fs' [-Wunused-parameter]
u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) {
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp: In member function 'bool EspClass::eraseConfig()':
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp:399:10: warning: unused variable 'ret' [-Wunused-variable]
bool ret = true;
^
Archiving built core (caching) in: /var/folders/5l/fjrz26dn5710yvf5hgzlcvsw0000gn/T/arduino_cache_825551/core/core_esp8266com_esp8266_d1_mini_CpuFrequency_160,FlashSize_4M3M,LwIPVariant_open,Debug_Disabled,DebugLevel_None____,UploadSpeed_230400_0a1796809b00622e6557403083020d45.a
De schets gebruikt 397437 bytes (38%) programma-opslagruimte. Maximum is 1044464 bytes.
Globale variabelen gebruiken 35924 bytes (43%) van het dynamisch geheugen. Resteren 45996 bytes voor lokale variabelen. Maximum is 81920 bytes.
Uploading 401584 bytes from /var/folders/5l/fjrz26dn5710yvf5hgzlcvsw0000gn/T/arduino_build_926479/StreamMP3FromHTTP.ino.bin to flash at 0x00000000
................................................................................ [ 20% ]
................................................................................ [ 40% ]
................................................................................ [ 61% ]
................................................................................ [ 81% ]
......................................................................... [ 100% ]
These are my warnings with the latest Arduino-ESP8266 GIT and with your latest ESP8266Audio GIT:
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp:45:18: warning: unused parameter 'client' [-Wunused-parameter]
virtual bool verify(WiFiClient& client, const char* host)
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp:45:18: warning: unused parameter 'host' [-Wunused-parameter]
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/SD.cpp:233:9: warning: unused parameter 'isLastComponent' [-Wunused-parameter]
boolean callback_pathExists(SdFile& parentDir, char *filePathComponent,
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/SD.cpp:233:9: warning: unused parameter 'object' [-Wunused-parameter]
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/SD.cpp:311:9: warning: unused parameter 'object' [-Wunused-parameter]
boolean callback_remove(SdFile& parentDir, char *filePathComponent,
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/SD.cpp:319:9: warning: unused parameter 'object' [-Wunused-parameter]
boolean callback_rmdir(SdFile& parentDir, char *filePathComponent,
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/Sd2Card.cpp: In member function 'uint8_t Sd2Card::readData(uint32_t, uint16_t, uint16_t, uint8_t*)':
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/Sd2Card.cpp:396:12: warning: unused variable 'n' [-Wunused-variable]
uint16_t n;
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/SdFile.cpp: In static member function 'static uint8_t SdFile::make83Name(const char*, uint8_t*)':
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/SdFile.cpp:262:15: warning: unused variable 'b' [-Wunused-variable]
uint8_t b;
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/SdFile.cpp: In member function 'uint8_t SdFile::rmRfStar()':
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/libraries/SD/src/utility/SdFile.cpp:908:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if (curPosition_ != (32*(index + 1))) {
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_hydrogen.c: In function 'SPIFFS_buffer_bytes_for_filedescs':
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/cores/esp8266/spiffs/spiffs_hydrogen.c:16:49: warning: unused parameter 'fs' [-Wunused-parameter]
u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) {
^
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp: In member function 'bool EspClass::eraseConfig()':
/Users/gerard/Documents/My Data/ArduinoESP/hardware/esp8266com/esp8266/cores/esp8266/Esp.cpp:399:10: warning: unused variable 'ret' [-Wunused-variable]
bool ret = true;
^
Archiving built core (caching) in: /var/folders/5l/fjrz26dn5710yvf5hgzlcvsw0000gn/T/arduino_cache_604903/core/core_esp8266com_esp8266_d1_mini_CpuFrequency_160,FlashSize_4M3M,LwIPVariant_open,Debug_Disabled,DebugLevel_None____,UploadSpeed_230400_0a1796809b00622e6557403083020d45.a
De schets gebruikt 397437 bytes (38%) programma-opslagruimte. Maximum is 1044464 bytes.
Globale variabelen gebruiken 35924 bytes (43%) van het dynamisch geheugen. Resteren 45996 bytes voor lokale variabelen. Maximum is 81920 bytes.
Uploading 401584 bytes from /var/folders/5l/fjrz26dn5710yvf5hgzlcvsw0000gn/T/arduino_build_570333/StreamMP3FromHTTP.ino.bin to flash at 0x00000000
................................................................................ [ 20% ]
................................................................................ [ 40% ]
................................................................................ [ 61% ]
................................................................................ [ 81% ]
......................................................................... [ 100% ]
Now running StreamMP3fromHTTP sketch from the latest GIT:
Is this the behaviour you expect from the sketch?
...Connecting to WiFi
...Connecting to WiFi
...Connecting to WiFi
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 0
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 418
Decoding error 0x0101 (lost synchronization) at byte offset 2054
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 2090
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 2508
Decoding error 0x0101 (lost synchronization) at byte offset 15453
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 15464
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 15882
Decoding error 0x0101 (lost synchronization) at byte offset 30462
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 30511
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 30929
Decoding error 0x0101 (lost synchronization) at byte offset 43862
.
<many more similar lines with increasing byte offset value
.
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 844695
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 845113
Decoding error 0x0101 (lost synchronization) at byte offset 858046
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 858070
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 858488
Decoding error 0x0101 (lost synchronization) at byte offset 873054
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 873117
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 873535
Decoding error 0x0101 (lost synchronization) at byte offset 886453
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 886491
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 886909
MP3 done
MP3 done
MP3 done
MP3 done
MP3 done
MP3 done
.
<unending MP3 done lines>
.
Now tested the example in the README.MD playing the stream from http://mp3radio.com/playback" with the extra buffer.
After uploading/resetting the ESP8266 the "MP3 done" starts immediately without the former "Decoding error" lines.
Looks like SUCCESS to me!! Now searching for a working earpiece ;-)
sl l⸮⸮| ⸮l⸮|⸮l⸮c|⸮⸮⸮⸮{⸮c⸮c⸮⸮oo⸮loo⸮⸮⸮cp⸮lsl{lp⸮o⸮⸮d⸮⸮co⸮|d⸮⸮c⸮⸮oo⸮ d⸮⸮d`⸮nnd`o{⸮⸮⸮oc⸮l{⸮⸮oc⸮l⸮⸮⸮⸮⸮⸮⸮⸮⸮`⸮⸮o⸮⸮MP3 done
MP3 done
MP3 done
MP3 done
MP3 done
MP3 done
<etcetera>
All those warnings you've got on the latest GIT are in the main Arduino code, not the audio portion. They're harmless, but I'm sure igrr wouldn't mind a PR if you want to fix them.
As to the "MP3 done," that actually means the MP3 is..err...done, and not playing any more. So the socket got closed, the file was completed, etc.
The example http address in the readme isn't a real URL. I thought it was obvious, but I guess not. You'll need to replace that with a real MP3 stream URL to run it.
One other possibility is that the errors are related to things like ICY tags or ID3 or other form of station identification.
Understand. For testing the sketch in the README I used the URL "http://streaming.shoutcast.com/80sPlanet?lang=en-US" used in the StreamMp3FromHttp example sketch.
Tried this URL in a browser windows and the stream plays, si I assume it's OK for testing the sketch.
But I still get every second the "Mp3 done" message. Now I know this indicates that no sound is played.
Will do some more testing tomorrow.
Thanks for your support so far in tackling my issues!
Started again to do some testing to get this beauty working, sorry to bother you, again.
As "baseline" I uploaded example sketch PlayWavFromProgmem. Works perfectly, violin sounds through speaker system connected to RX :-)
Uploaded HTTP stream example from README, using the valid URL from the StreamMp3FromHTTP example. Result:
The sketch contains this line in Setup:
WiFi.forceSleepBegin();
I think this disables Wifi alltogether, and that would mean that playing the stream is impossible. I would say this sketch cannot work "as is", or am I mistaken?
Uploaded StreamMP3FromHTTP example, URL="http://streaming.shoutcast.com/80sPlanet?lang=en-US". Result: 1 - ESP connects OK to router (gets IP) 2 - Serial monitor displays 3 lines "Decoding error" 3 - plays appr. 1 second good quality sound from the stream 4 - appr. 1 second silence Steps 2,3 and 4 repeated until "Mp3 done".
This is the serial monitor output, some further suggestions, maybe, I'm getting banana's here!
1384, room 16
tail 8
chksum ...Connecting to WiFi
...Connecting to WiFi
...Connecting to WiFi
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 0
Decoding error 0x0101 (lost synchronization) at byte offset 2054
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 2090
Decoding error 0x0101 (lost synchronization) at byte offset 15453
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 15464
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 15882
Decoding error 0x0101 (lost synchronization) at byte offset 30462
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 30511
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 30929
Decoding error 0x0101 (lost synchronization) at byte offset 43862
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 43886
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 44303
<many similar lines deleted>
Decoding error 0x0101 (lost synchronization) at byte offset 802837
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 802899
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 803317
Decoding error 0x0101 (lost synchronization) at byte offset 816238
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 816274
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 816692
Decoding error 0x0101 (lost synchronization) at byte offset 829638
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 829649
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 830067
Decoding error 0x0101 (lost synchronization) at byte offset 844645
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 844695
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 845113
MP3 done
MP3 done
MP3 done
MP3 done
MP3 done
MP3 done
MP3 done
MP3 done
MP3 done
MP3 done
Yup, the README.md example was just intended to show how to add the buffer. That's what I get for cutting-and-pasting code in a text file and expecting it to work
I'll delete it, you should start w/the Stream example and add the buffer instead.
Try a different webserver, or your own sitting on your own network to start. I just picked the first working URL I could find for the example as I don't do any web streaming myself. Looks like you're having bad packet loss between your ESP and that streamcast server...
Glad to help, grin!
As said before the stream example (without buffer) "works" alternating good sound with silences. Just tried adding a buffer but that seemed to make things even worse.
Also tried another URL (in my home country), but to no avail.
Spent (to) many hours today, so I'll call it quits for now. Tomorrow is another day :-)
Would be really pleased to get this working. I would love to have a couple of streaming ESP's.
Thx.
So it turns out that @armSeb, who's been doing lots of work with me recently, found a bug overnight in the buffer routine which would cause certain reads to return invalid data. You should do a pull of the updated repo and see if it changes things for you.
Yep, it changes things dramatically!
First pulled the updated repo and uploaded the example sketch StreamMP3FromHTTP (no buffer). Behaviour was similar as before with repeating "Decoding error" messages and eventually 1-sec repeating "Mp3 done" messages.
Then added a buffer to the sketch. Sound plays with a disturbing hickup of 50Herz or so, but it plays continually, NO "Decoding error" and NO "MP3 done" messages anymore.
Not sure where the 50?Herz hickup is coming from, but it is quite disturbing. But it is dramatic progress for me, it shows that my environment is more or less OK.
Will do some more testing later.
Good show!
Hello,
What is the MP3 bitrate ?
For testing I used this URL, but I have no clue what the bitrate is, sorry: http://icecast.omroep.nl/radio1-bb-mp3
For fun I just tried the default URL in the sketch: http://streaming.shoutcast.com/80sPlanet?lang=en-US
Wow, NO 50?Hz hickups with this stream, perfect sound !!!!!! Just a "crackle" now and then.
Also no idea what the bitrate for this stream is :-(
It's 192kbit/s 48000 Hz.
Please try with 44100Hz streaming ;)
And for buffer, you can try 4096 or 8192 bytes.
Great feedback on the example. I've just added buffering to the sample code so it's obvious to new users how to do it.
@earlephilhower : Glad that I could give something back to you guys!
@armSeb : Now that I know that bitrate is an issue I investigated the bitrate of the tested streams (opened stream in iTunes and showed INFO).
These are the streams and results I tested so far (note : loooong lines, scrolling required):
// const char *URL="http://streaming.shoutcast.com/80sPlanet?lang=en-US"; // 80sPlanet radio, 128kbps 44.1 kHz : works, only occasional a hickup
// const char *URL="http://icecast.omroep.nl/radio1-bb-mp3"; // Dutch Radio 1, 128kbps 48.0 kHz : works with a 50Hz hickup hickups (mayne hight mp3 bitrate)
// const char *URL="http://91.221.151.155:80/;?.mp3"; // Arrow Classick Rock, 128kbps 44.1 kHz : works, only occasional a hickup
The 44.1kHz@128kbps work satisfactory, the 48kHz@128kbps stream has severe hickups.
Increasing the buffer to 4096 : I THINK the number of small hickups decreased, but it may be wishfull thinking. Increasing the buffer to 8192 : This resulted in many hickups and standstills. May be a coincidence, no scientific testing done :-)
Will do some more testing when I'm alone in the house, so not to bother them with the crackles and hickups :-)
I think the issue is that at 48KHz the audio output portion that copies to I2S isn't being called often enough due to WiFi and other background ops taking time.
The ESP8266 can decode samples at >> 48KHz with no problem, probably even @ 80MHz, but there's a minuscule I2S buffer of only 11ms @ 44KHz, which is <10ms @48KHz. Even if you've got 20ms of data decoded and ready to go, only what fits in the I2S buffer will be used if there's a delay somewhere in the whole system.
I've put in a PR to let a user app override this default, https://github.com/esp8266/Arduino/pull/3790 , but it's obviously a low priority for them as they're releasing a new version soon and cleaning up existing features. The change is easy and you could hand-apply it if you're running the GIT head simply enough and set a larger buffer count.
Are you using an I2S DAC or the SW one? If it's the SW one you are using more CPU (~10 more insns/sample) than the HW DAC, so that makes it even harder to hit 48KHz...
One simple, if unappealing, way to work around this is to introduce a subsampler. It's not rocket science to downsample from 48KHz->44.1KHz if you don't care too much about noise floors, and then you gain an extra 1ms or 2 of time to play around in background tasks.
@earlephilhower : Thanks for enlightening me re. the 48kHz issue. The fact is that I just happened to test using a stream that was MP3 @ 48kHz. The stream I'm mostly interested is an AAC stream @128kbps.
From your explanation I gues the small I2S is the major bottleneck. I read the PR and I think I can manage changing it to a larger buffer count. Before I'll go that route I'll refrain myself to getting "the best quality sound" using the current default.
I'm currently using the SW DAC, one challenge at a time, right ;-) I understand this "wastes" some extra CPU power compared to an I2S DAC.
So for now, I'll focus on getting the AAC @128kbps as good as possible. Then I'll know what imperfection I will have to deal with.
Many thanks for the inspiration.
@armSeb : did some more tests with different buffer sizes: 2048 works 4096 works (a bit better, less hickups) 8192 does not work at all (MP3 done) or dramatic hickups Possibly setting the buffer to 8192 consumer all RAM?
8192 works for me, but I think the best compromise is 4096. You need free heap to be able to decode mp3 (and AAC) correctly.
I received my SPI RAM chip, I need some time to plug it an begin the tests. If I can use it, this will bring 128kbytes of buffer, without eating the main RAM.
@armSeb : Not sure why 8192 fails for me, but for now I'll stick with 4096.
Adding extra RAM will certainly help. Too bad that it adds an extra component, the fact that it runs on "just" a basic ESP8266 with a speaker is magic.
Yeah but with a real DAC you really get a nice stereo sound :)
Stereo, hickups from 2 sides ;-)
Seriously, a DAC is certainly worth the couple of $$.
Really ?
I bought this one : https://www.ebay.com/itm/PCM5102A-DAC-Decoder-I2S-32bit-Player-Module-Beyond-ES9023-PCM1794-Raspberry-Pi/331976578784
Without DAC you already have to decode stereo mp3, then converted to mono.
I believe a saw an even cheaper one on Aliexpress, but can't find it right now. If I do find it again , I'll let you know.
So the SW DAC wastes CPU cycles?, had no idea.
I am more of a SW guy myself, but I guess there's no way avoiding a hardware DAC :-(
Signing off for tonite.
SW DAC has to convert the samples to delta sigma. It's a hack that works but not for daily use. But if you can optimize a lot more the SW DAC code you will get a better quality, but only in mono. The output filter is important to eliminate the high freq harmonics, to avoid noise.
So, I guess the next step is to add some inline ASM with xtensa specific instructions to optimize a lot more the decoder and audio output, with pre-processing instructions to keep compability with other architectures.
8K won't work reliably due to memory limitations. Depending on when/what the WiFi does you'll hit OOM randomly. You start w/~40KB with the Hello World app in Arduino, and it goes down from there, very fast.
Without profiling, I would not assume that the SW DAC is eating an appreciable amount of time compared to other bits.
For the SW DAC, the generated assembly isn't too bad. I'm not sure you're going to do much better by hand. The whole SPI progam ROM+ IROM cache may actually slow you down more than the code. It's possible to do a table-lookup and convert 2-4 bits at a time instead of just 1, but it gets complicated very fast and the table explodes which means ICACHE misses which means it'll be way slower than the calculated code (40MHz SPI takes ages to load a $-line).
As for quality, if the I2S can go fast enough you can go to x64 or x128 oversampling. It already works and is a class method. :) This, however, reduces the effective time the I2S buffers last for by 2x or 4x...leading to hiccups during IP stuff.
LIBMAD has provisions for using assembly in the inner loops, however the Xtensa core that ESPRESSIF bought doesn't have the proper type of signed multiply instruction hardware. You're not going to make MP3 much faster is my thinking. I spent way too much time learning GCC ASM syntax only to find they'd not built that bit into the HW.
AAC has the possibility, and they definitely did use some targeted asm in the ARM port I looked at, but it was actually used mostly because the ARM was the wrong endinaness compared to the file...
l built a FIR filter and decimation engine so you can lowpass the 48khz and send it out at 44.1khz (or any other FIR and rate change you want), but that doesn't seem to be the problem. There's some sort of buffering/IP issue when listening to that stream and it's not related to the I2S output.
You can adjust the buffering in the MP3 decoder and the external buffer and try and you'll see that it decodes the first bit fine when you do, but then after a while (when the RAM buffering of the IP data is exhausted) starts the 20Hz silences/ticks.
buff = new AudioFileSourceBuffer(file, 3000);
...
mp3 = new AudioGeneratorMP3();
mp3->SetBufferSize(1000);
mp3->begin(buff, out);
Could be related to the stream encoded BW more than the I2S is my thinking. Maybe hitting the ESP's TCP processing limit?
Oh, and listening to Dutch talk radio is very disconcerting for an American English speaker. Like I should be able to understand them due to the common roots, but enough differences to make it unintelligible to me.
@armSeb
Have been searching for the "few dollars DAC" but didn't find it. I then remembered I saw an amplifier board with an I2S input. It's more expensive as the DAC you found on Ebay, appr. $10, but the board also contains an few-Watt mono amplifier.
https://learn.adafruit.com/adafruit-max98357-i2s-class-d-mono-amp/overview
You can get an analog stereo class d amplifier, which you can plug to the DAC with a potentiometer. The dac itself is enough to drive a little earpiece/earphones.
@gerardwr My opinion is that the SW DAC is a proof of concept. The most important is to fine tune the rest, the goal is to make a really usable device with a real DAC.
@gerardwr, try pulling the latest repo. @armSeb found a case where on slower streams the buffer would never refill and you'd be stuck w/micro-stutter. His suggestion was to just take the hit and do 1 bigger stutter and refill in that case, and that's just been committed. I was able to listen to a Dutch report about Mugabe resigning w/o hiccups on that 48KHz URL w/o stuttering except when the Buffering... appeared (because the stream fell behind the audio out).
@earlephilhower : Excellent, will do that later today and report back.
I have to do my best to keep up with the responses from you and @armSeb , so much to do, so little time ;-)
In the meantime you can continue practicing your Dutch skills, I fully missed Mugabe resigning. Must have been a hickup in the stream ;-)
@earlephilhower : Installed the latest repo, but unfortunately all of my test streams (48 and 44 kHz) now displays "Buffering..'" appr. every second in the serial monitor with the related hickups.
Not sure what is happening, but for me this is a step back.
Will do some further testing later to make sure that my test results are reliable.
BTW : I'm on a rather slow 40 Mbits/s WAN connection, but assume the ESP wifi is the bottleneck anyway.
@earlephilhower : 1 addition to my previous remark.
With the latest repo the stream continues to play indefinitely, while the previous repo often ended after a while with "MP3 done" (Tested with a 4096 buffer).
So, that's an important positive change!
For me it works like a charm, I have an ADSL connection @13Mbit/s, and many people using wifi around me.
After the troubles with the continuously "buffering" of my MP3 streams I tried this AAC stream with the latest repo: "http://stream.morow.com:8080/morow_med.aacp"
Much better.
No "buffering"/hickups (maybe 1 every few minutes) , occasionally a 1 sec whistling/hissing tone in the output, that's quite disturbing.
Stay tuned.
Not sure what I'm fighting here.
I tested the Morow Radio stream, that's available both as MP3 stream and AAC stream. http://stream.morow.com:8080/morow_med.aacp http://stream.morow.com:8000/morow.mp3
I created the AAC sketch adapting the StreamMp3FromHTTP (both with a 4096 buffer).
The AAC stream plays continuously with a disturbing "whistling hiss" now and then (maybe every 20 secs?) but otherwise quality is OK.
The MP3 stream pauses appr. every second while displaying "Buffering", and sounds awfull.
Both stream play fine in my browser.
Need a drink!
@gerardwr Your MP3 stream plays fine :)
Can you try to ping your ESP from computer ?
I just soldered my SPI RAM chip, the big job will be to create a class to use it as buffer (as described here: https://github.com/espressif/ESP8266_MP3_DECODER)
@armSeb : Thank for confirming the MP3 stream playing OK for you. Must be somethig weard over here.
Ping not quite stable (understatement)
64 bytes from 192.168.0.41: icmp_seq=0 ttl=255 time=4.380 ms
64 bytes from 192.168.0.41: icmp_seq=1 ttl=255 time=0.977 ms
64 bytes from 192.168.0.41: icmp_seq=2 ttl=255 time=1.117 ms
64 bytes from 192.168.0.41: icmp_seq=3 ttl=255 time=8.662 ms
64 bytes from 192.168.0.41: icmp_seq=4 ttl=255 time=0.848 ms
64 bytes from 192.168.0.41: icmp_seq=5 ttl=255 time=0.904 ms
64 bytes from 192.168.0.41: icmp_seq=6 ttl=255 time=99.734 ms
64 bytes from 192.168.0.41: icmp_seq=7 ttl=255 time=0.869 ms
64 bytes from 192.168.0.41: icmp_seq=8 ttl=255 time=0.940 ms
64 bytes from 192.168.0.41: icmp_seq=9 ttl=255 time=5.031 ms
64 bytes from 192.168.0.41: icmp_seq=10 ttl=255 time=97.047 ms
64 bytes from 192.168.0.41: icmp_seq=11 ttl=255 time=7.243 ms
64 bytes from 192.168.0.41: icmp_seq=12 ttl=255 time=0.920 ms
64 bytes from 192.168.0.41: icmp_seq=13 ttl=255 time=0.959 ms
64 bytes from 192.168.0.41: icmp_seq=14 ttl=255 time=67.528 ms
64 bytes from 192.168.0.41: icmp_seq=15 ttl=255 time=11.874 ms
64 bytes from 192.168.0.41: icmp_seq=16 ttl=255 time=0.828 ms
64 bytes from 192.168.0.41: icmp_seq=17 ttl=255 time=0.861 ms
64 bytes from 192.168.0.41: icmp_seq=18 ttl=255 time=85.606 ms
64 bytes from 192.168.0.41: icmp_seq=19 ttl=255 time=1.197 ms
64 bytes from 192.168.0.41: icmp_seq=20 ttl=255 time=0.827 ms
64 bytes from 192.168.0.41: icmp_seq=21 ttl=255 time=101.695 ms
64 bytes from 192.168.0.41: icmp_seq=22 ttl=255 time=2.692 ms
64 bytes from 192.168.0.41: icmp_seq=23 ttl=255 time=0.913 ms
Mine is more stable:
64 bytes from 192.168.1.2: icmp_seq=0 ttl=128 time=72.497 ms
64 bytes from 192.168.1.2: icmp_seq=1 ttl=128 time=4.317 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=128 time=3.169 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=128 time=10.710 ms
64 bytes from 192.168.1.2: icmp_seq=4 ttl=128 time=31.852 ms
64 bytes from 192.168.1.2: icmp_seq=5 ttl=128 time=5.967 ms
64 bytes from 192.168.1.2: icmp_seq=6 ttl=128 time=10.196 ms
64 bytes from 192.168.1.2: icmp_seq=7 ttl=128 time=22.208 ms
64 bytes from 192.168.1.2: icmp_seq=8 ttl=128 time=10.469 ms
64 bytes from 192.168.1.2: icmp_seq=9 ttl=128 time=5.658 ms
64 bytes from 192.168.1.2: icmp_seq=10 ttl=128 time=5.760 ms
64 bytes from 192.168.1.2: icmp_seq=11 ttl=128 time=6.304 ms
64 bytes from 192.168.1.2: icmp_seq=12 ttl=128 time=15.903 ms
64 bytes from 192.168.1.2: icmp_seq=13 ttl=128 time=11.712 ms
64 bytes from 192.168.1.2: icmp_seq=14 ttl=128 time=2.975 ms
64 bytes from 192.168.1.2: icmp_seq=15 ttl=128 time=21.010 ms
64 bytes from 192.168.1.2: icmp_seq=16 ttl=128 time=8.289 ms
64 bytes from 192.168.1.2: icmp_seq=17 ttl=128 time=12.555 ms
64 bytes from 192.168.1.2: icmp_seq=18 ttl=128 time=4.964 ms
64 bytes from 192.168.1.2: icmp_seq=19 ttl=128 time=8.784 ms
64 bytes from 192.168.1.2: icmp_seq=20 ttl=128 time=35.620 ms
64 bytes from 192.168.1.2: icmp_seq=21 ttl=128 time=20.904 ms
64 bytes from 192.168.1.2: icmp_seq=22 ttl=128 time=23.099 ms
Switched to another ESP8266 module, slightly better, but MP3 hickups remain :-(
Possibly my streaming experiments result in a network overhaul :-(
Try to share a mp3 file (for example with python -m SimpleHTTPServer) on your LAN, to spot the issue (Wifi or WAN issue)
Your streams plays very nicely, with very good sound, and no hiccups.
Can you try without the buffer ?
As said before in this (now ) looooong topic, the only stream I use on a daily basis is the Morow Radio stream. The fact that it plays "very nicely" on your ESP keeps me motivated.
Your support and from @earlephilhower is greatly appreciated.
Wow, neat trick with the local server, would have never thought of this!
...Connecting to WiFi
...Connecting to WiFi
...Connecting to WiFi
Buffering...
Decoding error 0x0101 (lost synchronization) at byte offset 0
Buffering...
Buffering...
Buffering...
Tried sketch without buffer, result sounds similar as with buffers (hickup every second, followed by "Decoding error"
...Connecting to WiFi
...Connecting to WiFi
Decoding error 0x0101 (lost synchronization) at byte offset 0
Decoding error 0x0101 (lost synchronization) at byte offset 11790
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 11809
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 12227
Decoding error 0x0101 (lost synchronization) at byte offset 30551
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 30618
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 31036
Decoding error 0x0101 (lost synchronization) at byte offset 49311
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 49426
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 49844
Decoding error 0x0101 (lost synchronization) at byte offset 68071
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 68234
Decoding error 0x0235 (bad main_data_begin pointer) at byte offset 68652
I'm lost.
Did you select the correct ESP frequency ? You have to set it to 160MHz (Sometimes the Arduino IDE can reset this setting).
This looks like an excellent library to stream internet-radio.
The StreamMP3FromHTTP sketch compiles (Arduino 1.8.1 and ESP8266 2.3.0), but with dozens of "red" warnings.
Upload to a Wemos D1 Mini (160Mhz)results in the errors below.
Any suggestions what to do?