|
@ -19,7 +19,10 @@ |
|
|
|
|
|
|
|
|
char titleStr[64]; |
|
|
char titleStr[64]; |
|
|
|
|
|
|
|
|
MP3::MP3() {} |
|
|
MP3::MP3() { |
|
|
|
|
|
strncpy_P(URL, "http://streaming.shoutcast.com/80sPlanet?lang=en-US", sizeof(URL)); |
|
|
|
|
|
//const char *URL="http://swr-swr1-bw.cast.addradio.de/swr/swr1/bw/mp3/64/stream.mp3";
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/*gpio_set_direction(GPIO_NUM_13,GPIO_MODE_OUTPUT); // GPIO_MODE_DEF_OUTPUT
|
|
|
/*gpio_set_direction(GPIO_NUM_13,GPIO_MODE_OUTPUT); // GPIO_MODE_DEF_OUTPUT
|
|
|
gpio_set_direction(GPIO_NUM_12,GPIO_MODE_OUTPUT); |
|
|
gpio_set_direction(GPIO_NUM_12,GPIO_MODE_OUTPUT); |
|
@ -40,9 +43,22 @@ void MP3::stop() { |
|
|
Serial.println("Stopping mp3 playback"); |
|
|
Serial.println("Stopping mp3 playback"); |
|
|
strcpy(titleStr, ""); |
|
|
strcpy(titleStr, ""); |
|
|
playing = false; |
|
|
playing = false; |
|
|
|
|
|
// while (audioTaskHandle && eTaskGetState(audioTaskHandle) != eDeleted) {
|
|
|
|
|
|
// Serial.println("waiting for audio to finish");
|
|
|
|
|
|
delay(100); |
|
|
|
|
|
// }
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void MP3::start(const char* url) { |
|
|
|
|
|
strncpy(URL, url, sizeof(URL)); |
|
|
|
|
|
URL[sizeof(URL)-1] = '\0'; |
|
|
|
|
|
start(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void MP3::start() { |
|
|
void MP3::start() { |
|
|
|
|
|
if (playing) { |
|
|
|
|
|
stop(); |
|
|
|
|
|
} |
|
|
Serial.println("Starting mp3 playback"); |
|
|
Serial.println("Starting mp3 playback"); |
|
|
Serial.printf("%x\n", audioTaskHandle); |
|
|
Serial.printf("%x\n", audioTaskHandle); |
|
|
if (playing == false) { |
|
|
if (playing == false) { |
|
@ -57,12 +73,19 @@ void MP3::start() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void MP3::setVolume(int volume) { |
|
|
void MP3::setVolume(int volume) { |
|
|
if (playing && out) |
|
|
if (volume > 0 && volume <= 100) { |
|
|
if (volume > 0 && volume <= 100) |
|
|
this->volume = volume; |
|
|
out->SetGain(((float)volume)/100.0); |
|
|
volumeChanged = true; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void MP3::mp3_decoder_task(void *pvParameters) { |
|
|
void MP3::mp3_decoder_task(void *pvParameters) { |
|
|
|
|
|
AudioGenerator *decoder = nullptr; |
|
|
|
|
|
AudioFileSourceICYStream *file = nullptr; |
|
|
|
|
|
AudioFileSourceBuffer *buff = nullptr; |
|
|
|
|
|
AudioOutputI2S *out = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
strcpy(titleStr, "..."); |
|
|
strcpy(titleStr, "..."); |
|
|
file = new AudioFileSourceICYStream(URL); |
|
|
file = new AudioFileSourceICYStream(URL); |
|
|
file->RegisterMetadataCB(MDCallback, (void*)"ICY"); |
|
|
file->RegisterMetadataCB(MDCallback, (void*)"ICY"); |
|
@ -72,10 +95,22 @@ void MP3::mp3_decoder_task(void *pvParameters) { |
|
|
out = new AudioOutputI2S(I2S_NUM_0, false, 0); |
|
|
out = new AudioOutputI2S(I2S_NUM_0, false, 0); |
|
|
out->SetPinout(12, 13, 25); |
|
|
out->SetPinout(12, 13, 25); |
|
|
} |
|
|
} |
|
|
decoder = new AudioGeneratorMP3(); |
|
|
decoder = new AudioGeneratorMP3(preallocateCodec, preallocateCodecSize); |
|
|
decoder->RegisterStatusCB(StatusCallback, (void*)"mp3"); |
|
|
decoder->RegisterStatusCB(StatusCallback, (void*)"mp3"); |
|
|
|
|
|
Serial.println("prefilling buffer"); |
|
|
|
|
|
for (int i=0; i<10; i++) { |
|
|
|
|
|
// char c;
|
|
|
|
|
|
// buff->read(&c, 1);
|
|
|
|
|
|
buff->loop(); delay(100); // pre-fill buffer
|
|
|
|
|
|
} |
|
|
|
|
|
Serial.println("prefilling buffer done"); |
|
|
decoder->begin(buff, out); |
|
|
decoder->begin(buff, out); |
|
|
out->SetGain(0.2); |
|
|
if (volume > 0 && volume <= 100) { |
|
|
|
|
|
out->SetGain(((float)volume)/100.0); |
|
|
|
|
|
} else { |
|
|
|
|
|
out->SetGain(0.2); |
|
|
|
|
|
volume = 20; |
|
|
|
|
|
} |
|
|
playing = true; |
|
|
playing = true; |
|
|
|
|
|
|
|
|
while(decoder->isRunning()) { |
|
|
while(decoder->isRunning()) { |
|
@ -84,6 +119,10 @@ void MP3::mp3_decoder_task(void *pvParameters) { |
|
|
Serial.printf("Running for %d ms...\n", lastms); |
|
|
Serial.printf("Running for %d ms...\n", lastms); |
|
|
Serial.flush(); |
|
|
Serial.flush(); |
|
|
} |
|
|
} |
|
|
|
|
|
if (volumeChanged) { |
|
|
|
|
|
volumeChanged = false; |
|
|
|
|
|
out->SetGain(((float)volume)/100.0); |
|
|
|
|
|
} |
|
|
if (!decoder->loop()) break; |
|
|
if (!decoder->loop()) break; |
|
|
if (!playing) break; |
|
|
if (!playing) break; |
|
|
vTaskDelay(5 / portTICK_PERIOD_MS); |
|
|
vTaskDelay(5 / portTICK_PERIOD_MS); |
|
@ -95,19 +134,19 @@ void MP3::mp3_decoder_task(void *pvParameters) { |
|
|
playing = false; |
|
|
playing = false; |
|
|
|
|
|
|
|
|
if (decoder) { |
|
|
if (decoder) { |
|
|
decoder->stop(); |
|
|
decoder->stop(); // ToDo: takes long
|
|
|
delete decoder; |
|
|
delete decoder; |
|
|
decoder = NULL; |
|
|
decoder = nullptr; |
|
|
} |
|
|
} |
|
|
if (buff) { |
|
|
if (buff) { |
|
|
buff->close(); |
|
|
buff->close(); |
|
|
delete buff; |
|
|
delete buff; |
|
|
buff = NULL; |
|
|
buff = nullptr; |
|
|
} |
|
|
} |
|
|
if (file) { |
|
|
if (file) { |
|
|
file->close(); |
|
|
file->close(); |
|
|
delete file; |
|
|
delete file; |
|
|
file = NULL; |
|
|
file = nullptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
vTaskDelete(NULL); |
|
|
vTaskDelete(NULL); |
|
@ -119,7 +158,8 @@ bool MP3::begin() { |
|
|
|
|
|
|
|
|
// First, preallocate all the memory needed for the buffering and codecs, never to be freed
|
|
|
// First, preallocate all the memory needed for the buffering and codecs, never to be freed
|
|
|
preallocateBuffer = malloc(preallocateBufferSize); |
|
|
preallocateBuffer = malloc(preallocateBufferSize); |
|
|
if (!preallocateBuffer) { |
|
|
preallocateCodec = malloc(preallocateCodecSize); |
|
|
|
|
|
if (!preallocateBuffer || !preallocateCodec) { |
|
|
Serial.printf_P(PSTR("FATAL ERROR: Unable to preallocate %d bytes for app\n"), preallocateBufferSize+preallocateCodecSize); |
|
|
Serial.printf_P(PSTR("FATAL ERROR: Unable to preallocate %d bytes for app\n"), preallocateBufferSize+preallocateCodecSize); |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|