earlephilhower / ESP8266Audio

Arduino library to play MOD, WAV, FLAC, MIDI, RTTTL, MP3, and AAC files on I2S DACs or with a software emulated delta-sigma DAC on the ESP8266 and ESP32
GNU General Public License v3.0
1.99k stars 433 forks source link

Garbled sound issue with Jazz24 streaming #609

Open drhenk opened 1 year ago

drhenk commented 1 year ago

Hi all, I am using this awesome library to stream internet radio on an ESP32-WROVER-IE (8MB) with a PCM5102A DAC to my stereo using a very simple sketch compiled in Arduino IDE (as proof of concept first.) Many of my favorite stations play well, however, I only hear "garbled sound snippets" on Jazz24, my all-time favorite :), via this link: 128k MP3: http://live.wostreaming.net/direct/ppm-jazz24mp3-ibc1

Here the error messages:

09:26:09.851 -> [  3179][V][HTTPClient.cpp:252] beginInternal(): url: http://3.90.240.207/ppm-jazz24mp3-ibc1?session-id=4a67102c2e29c584a233f7d38a9bbc02
09:26:09.908 -> [  3191][D][HTTPClient.cpp:297] beginInternal(): switching host from 'live.wostreaming.net' to '3.90.240.207'. disconnecting first
09:26:09.908 -> [  3202][D][HTTPClient.cpp:395] disconnect(): tcp stop
09:26:09.908 -> [  3208][D][HTTPClient.cpp:303] beginInternal(): protocol: http, host: 3.90.240.207 port: 80 url: /ppm-jazz24mp3-ibc1?session-id=4a67102c2e29c584a233f7d38a9bbc02
09:26:09.908 -> [  3221][D][HTTPClient.cpp:598] sendRequest(): request type: 'GET' redirCount: 1
09:26:09.908 -> 
09:26:10.035 -> [  3374][D][HTTPClient.cpp:1156] connect():  connected to 3.90.240.207:80
09:26:10.240 -> [  3586][V][HTTPClient.cpp:1250] handleHeaderResponse(): RX: 'HTTP/1.1 200 OK'
09:26:10.275 -> [  3587][V][HTTPClient.cpp:1250] handleHeaderResponse(): RX: 'Date: Thu, 23 Mar 2023 08:26:07 GMT'
09:26:10.275 -> [  3591][V][HTTPClient.cpp:1250] handleHeaderResponse(): RX: 'Content-Type: audio/mpeg'
09:26:10.275 -> [  3599][V][HTTPClient.cpp:1250] handleHeaderResponse(): RX: 'Cache-Control: no-cache'
09:26:10.275 -> [  3606][V][HTTPClient.cpp:1250] handleHeaderResponse(): RX: 'Pragma: no-cache'
09:26:10.275 -> [  3614][V][HTTPClient.cpp:1250] handleHeaderResponse(): RX: 'Transfer-Encoding: chunked'
09:26:10.309 -> [  3622][V][HTTPClient.cpp:1250] handleHeaderResponse(): RX: 'Expires: Thu, 01 Jan 1970 00:00:01 GMT'
09:26:10.309 -> [  3630][V][HTTPClient.cpp:1250] handleHeaderResponse(): RX: 'icy-br: 128'
09:26:10.309 -> [  3637][V][HTTPClient.cpp:1250] handleHeaderResponse(): RX: 'icy-metaint: 2048'
09:26:10.309 -> [  3644][V][HTTPClient.cpp:1250] handleHeaderResponse(): RX: 'icy-name: Jazz24'
09:26:10.344 -> [  3651][V][HTTPClient.cpp:1250] handleHeaderResponse(): RX: ''
09:26:10.344 -> [  3657][D][HTTPClient.cpp:1307] handleHeaderResponse(): code: 200
09:26:10.344 -> [  3662][D][HTTPClient.cpp:1314] handleHeaderResponse(): Transfer-Encoding: chunked
09:26:10.344 -> [  3670][D][HTTPClient.cpp:628] sendRequest(): sendRequest code=200
09:26:10.344 -> 
09:26:11.353 -> +0 0x3ffb21b0
09:26:11.353 -> STATUS(buffer) '2' = 'Refilling buffer'
09:26:11.353 -> METADATA(ICY) 'StreamTitle' = 'Abdullah Ibrahim - Mannenberg Revisited'
09:26:11.489 -> STATUS(buffer) '3' = 'Buffer underflow'
09:26:11.489 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 2048'
09:26:11.489 -> STATUS(buffer) '2' = 'Refilling buffer'
09:26:11.881 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 3073'
09:26:11.934 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 5121'
09:26:11.934 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 6145'
09:26:11.934 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 7169'
09:26:12.078 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 8193'
...
09:26:56.150 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 172415'
09:26:56.150 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 172416'
09:26:56.150 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 172417'
09:26:56.150 -> STATUS(mp3) '565' = 'Decoding error 'bad main_data_begin pointer' at byte offset 172'
09:26:56.218 -> Running for 49534 ms...
09:26:56.218 -> STATUS(mp3) '259' = 'Decoding error 'forbidden bitrate value' at byte offset 173672'
09:26:56.218 -> STATUS(mp3) '565' = 'Decoding error 'bad main_data_begin pointer' at byte offset 173'
09:26:56.252 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 174091'
09:26:56.252 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 174092'
...
09:26:57.601 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 176351'
09:26:57.601 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 176352'
09:26:57.601 -> STATUS(mp3) '565' = 'Decoding error 'bad main_data_begin pointer' at byte offset 176'
09:26:57.636 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 177189'
09:26:57.636 -> STATUS(mp3) '565' = 'Decoding error 'bad main_data_begin pointer' at byte offset 177'
09:26:57.705 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 178443'
09:26:57.705 -> STATUS(mp3) '257' = 'Decoding error 'lost synchronization' at byte offset 178444'

Here the sketch:

#include <Arduino.h>
#include <WiFi.h>
#include "AudioFileSourceICYStream.h"
#include "AudioFileSourceBuffer.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2S.h"

// Enter your WiFi setup here:
const char *SSID = "xxx";
const char *PASSWORD = "xxx";

//const char *URL="http://fm02-ice.stream.khz.se/fm02_mp3";
//const char *URL="http://stream.ffn.de/energybremen/mp3-192/;stream.nsv";
const char *URL="http://live.wostreaming.net/direct/ppm-jazz24mp3-ibc1";

AudioGeneratorMP3 *mp3;
AudioFileSourceICYStream *file;
AudioFileSourceBuffer *buff;
AudioOutputI2S *out;
// Called when a metadata event occurs (i.e. an ID3 tag, an ICY block, etc.
void MDCallback(void *cbData, const char *type, bool isUnicode, const char *string)
{
  const char *ptr = reinterpret_cast<const char *>(cbData);
  (void) isUnicode; // Punt this ball for now
  // Note that the type and string may be in PROGMEM, so copy them to RAM for printf
  char s1[32], s2[64];
  strncpy_P(s1, type, sizeof(s1));
  s1[sizeof(s1)-1]=0;
  strncpy_P(s2, string, sizeof(s2));
  s2[sizeof(s2)-1]=0;
  Serial.printf("METADATA(%s) '%s' = '%s'\n", ptr, s1, s2);
  Serial.flush();
}
// Called when there's a warning or error (like a buffer underflow or decode hiccup)
void StatusCallback(void *cbData, int code, const char *string)
{
  const char *ptr = reinterpret_cast<const char *>(cbData);
  // Note that the string may be in PROGMEM, so copy it to RAM for printf
  char s1[64];
  strncpy_P(s1, string, sizeof(s1));
  s1[sizeof(s1)-1]=0;
  Serial.printf("STATUS(%s) '%d' = '%s'\n", ptr, code, s1);
  Serial.flush();
}

void setup()
{
  Serial.begin(115200);
  delay(1000);
  Serial.println("Connecting to WiFi");
  WiFi.disconnect();
  WiFi.softAPdisconnect(true);
  WiFi.mode(WIFI_STA); 
  WiFi.begin(SSID, PASSWORD);
  // Try forever
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("...Connecting to WiFi");
    delay(1000);
  }
  Serial.println("Connected");

  audioLogger = &Serial;
  file = new AudioFileSourceICYStream(URL);
  file->RegisterMetadataCB(MDCallback, (void*)"ICY");
  buff = new AudioFileSourceBuffer(file, 65536); // playing with this value did not help Jazz24
  buff->RegisterStatusCB(StatusCallback, (void*)"buffer");
  out = new AudioOutputI2S();
  out->SetGain(0.1);
  out->SetPinout(27, 26, 25);
  mp3 = new AudioGeneratorMP3();
  mp3->RegisterStatusCB(StatusCallback, (void*)"mp3");
  delay(1000); // Don't start and stop while filling first buffer
  mp3->begin(buff, out);
}

void loop()
{
  static int lastms = 0;
  if (mp3->isRunning()) {
    if (millis()-lastms > 10000) {
      lastms = millis();
      Serial.printf("Running for %d ms...\n", lastms);
      Serial.flush();
     }
    if (!mp3->loop()) mp3->stop();
  } else {
    Serial.printf("MP3 done\n");
    delay(1000);
  }
}

Many thanks for any hint on how to solve this riddle.

Daniel