Hendrik Langer
7 years ago
6 changed files with 210 additions and 29 deletions
@ -0,0 +1,137 @@ |
|||
#include "mp3.h" |
|||
|
|||
#include <HTTPClient.h> |
|||
#include <SD.h> |
|||
#include "AudioFileSourceICYStream.h" |
|||
#include "AudioFileSourceBuffer.h" |
|||
#include "AudioGeneratorMP3.h" |
|||
#include "AudioOutputI2S.h" |
|||
//#include "driver/gpio.h"
|
|||
//#include "driver/periph_ctrl.h"
|
|||
//#include "soc/gpio_sig_map.h"
|
|||
|
|||
#include <stdio.h> |
|||
#include "freertos/FreeRTOS.h" |
|||
#include "freertos/task.h" |
|||
#include "driver/i2s.h" |
|||
#include "esp_system.h" |
|||
#include <math.h> |
|||
|
|||
char titleStr[64]; |
|||
|
|||
MP3::MP3() {} |
|||
|
|||
/*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_22,GPIO_MODE_OUTPUT); |
|||
gpio_matrix_out(13, I2S0O_BCK_OUT_IDX, 0, 0); |
|||
gpio_matrix_out(12, I2S0O_WS_OUT_IDX, 0, 0); |
|||
gpio_matrix_out(22, I2S0O_DATA_OUT0_IDX, 0, 0); |
|||
//periph_module_reset( PERIPH_I2S0_MODULE );
|
|||
periph_module_disable(PERIPH_I2S0_MODULE); |
|||
delay(100); |
|||
periph_module_enable(PERIPH_I2S0_MODULE);*/ |
|||
|
|||
void MP3::cTaskWrapper(void* parameters) { |
|||
static_cast<MP3*>(parameters)->mp3_decoder_task(NULL); |
|||
} |
|||
|
|||
void MP3::mp3_decoder_task(void *pvParameters) { |
|||
while(true) { |
|||
if (mp3->isRunning()) { |
|||
if (millis()-lastms > 1000) { |
|||
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); |
|||
} |
|||
vTaskDelay(10 / portTICK_PERIOD_MS); |
|||
} |
|||
vTaskDelete(NULL); |
|||
} |
|||
|
|||
bool MP3::begin() { |
|||
strcpy(titleStr, "StreamTitle"); |
|||
|
|||
// First, preallocate all the memory needed for the buffering and codecs, never to be freed
|
|||
preallocateBuffer = malloc(preallocateBufferSize); |
|||
preallocateCodec = malloc(preallocateCodecSize); |
|||
if (!preallocateBuffer || !preallocateCodec) { |
|||
Serial.printf_P(PSTR("FATAL ERROR: Unable to preallocate %d bytes for app\n"), preallocateBufferSize+preallocateCodecSize); |
|||
return false; |
|||
} |
|||
|
|||
Serial.println("Starting mp3 playback"); |
|||
|
|||
file = new AudioFileSourceICYStream(URL); |
|||
file->RegisterMetadataCB(MDCallback, (void*)"ICY"); |
|||
buff = new AudioFileSourceBuffer(file, preallocateBuffer, preallocateBufferSize); |
|||
buff->RegisterStatusCB(StatusCallback, (void*)"buffer"); |
|||
out = new AudioOutputI2S(I2S_NUM_0, false); |
|||
out->SetPinout(12, 13, 23); |
|||
out->SetOutputModeMono(false); |
|||
out->SetRate(44100); |
|||
out->SetBitsPerSample(16); |
|||
out->SetChannels(2); |
|||
mp3 = new AudioGeneratorMP3(preallocateCodec, preallocateCodecSize); |
|||
mp3->RegisterStatusCB(StatusCallback, (void*)"mp3"); |
|||
mp3->begin(buff, out); |
|||
out->SetGain(1.0); |
|||
|
|||
/*
|
|||
I2S0.clkm_conf.clka_en = 1; // was 0
|
|||
I2S0.clkm_conf.clkm_div_a = 1; // was 63;
|
|||
I2S0.clkm_conf.clkm_div_b = 0; // was clkmDecimals;
|
|||
I2S0.clkm_conf.clkm_div_num = 1; // was clkmInteger;
|
|||
|
|||
// periph_module_enable(PERIPH_EMAC_MODULE);
|
|||
// rtc_clk_apll_enable(1,0,73,7,8);
|
|||
// i2s_set_clk((i2s_port_t)portNo, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO);
|
|||
|
|||
i2s_set_clk(I2S_NUM, SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO); |
|||
*/ |
|||
|
|||
xTaskCreate( |
|||
&cTaskWrapper, /* Task function. */ |
|||
"audioTask", /* String with name of task. */ |
|||
2048, /* Stack size in words. */ |
|||
this, /* Parameter passed as input of the task */ |
|||
tskIDLE_PRIORITY+1, /* Priority of the task. */ |
|||
&audioTaskHandle); /* Task handle. */ |
|||
} |
|||
|
|||
|
|||
// 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(); |
|||
if (strcmp("StreamTitle", type)==0) { |
|||
strncpy_P(titleStr, string, sizeof(titleStr)); |
|||
s2[sizeof(s2)-1]=0; |
|||
} |
|||
} |
|||
|
|||
// 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(); |
|||
} |
@ -0,0 +1,39 @@ |
|||
#ifndef _MP3_H |
|||
#define _MP3_H |
|||
|
|||
#include <HTTPClient.h> |
|||
#include <SD.h> |
|||
#include "AudioFileSourceICYStream.h" |
|||
#include "AudioFileSourceBuffer.h" |
|||
#include "AudioGeneratorMP3.h" |
|||
#include "AudioOutputI2S.h" |
|||
|
|||
void MDCallback(void *cbData, const char *type, bool isUnicode, const char *string); |
|||
void StatusCallback(void *cbData, int code, const char *string); |
|||
extern char titleStr[]; |
|||
|
|||
class MP3 { |
|||
public: |
|||
MP3(); |
|||
bool begin(void); |
|||
//const char *URL="http://streaming.shoutcast.com/80sPlanet?lang=en-US";
|
|||
const char *URL="http://swr-swr1-bw.cast.addradio.de/swr/swr1/bw/mp3/64/stream.mp3"; |
|||
private: |
|||
AudioGeneratorMP3 *mp3; |
|||
AudioFileSourceICYStream *file; |
|||
AudioFileSourceBuffer *buff; |
|||
AudioOutputI2S *out; |
|||
|
|||
TaskHandle_t audioTaskHandle; |
|||
void mp3_decoder_task(void*); |
|||
static void cTaskWrapper(void*); |
|||
|
|||
static constexpr int preallocateBufferSize = 5*1024; |
|||
static constexpr int preallocateCodecSize = 29192; // MP3 codec max mem needed
|
|||
void *preallocateBuffer = NULL; |
|||
void *preallocateCodec = NULL; |
|||
|
|||
int lastms = 0; |
|||
}; |
|||
|
|||
#endif /* _MP3_H */ |
@ -0,0 +1,2 @@ |
|||
172.16.75.18 |
|||
esp32-node QXLhCf9yXE |
Loading…
Reference in new issue