mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-21 01:36:31 +00:00
I2S: AAC support for web radio (#22787)
* I2S: AAC decoding support for web radio * optimize AAC-lib for size
This commit is contained in:
parent
1fc6f5c707
commit
b73f50be6b
@ -18,7 +18,7 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma GCC optimize ("O3")
|
#pragma GCC optimize ("Os")
|
||||||
|
|
||||||
#include "AudioGeneratorAAC.h"
|
#include "AudioGeneratorAAC.h"
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
#define AAC_ENABLE_SBR 1
|
#define AAC_ENABLE_SBR 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma GCC optimize ("O3")
|
#pragma GCC optimize ("Os")
|
||||||
|
|
||||||
#include "aacdec.h"
|
#include "aacdec.h"
|
||||||
#include "statname.h"
|
#include "statname.h"
|
||||||
|
@ -1409,6 +1409,7 @@
|
|||||||
#define USE_SHINE
|
#define USE_SHINE
|
||||||
#define MP3_MIC_STREAM
|
#define MP3_MIC_STREAM
|
||||||
#define USE_I2S_AUDIO_BERRY
|
#define USE_I2S_AUDIO_BERRY
|
||||||
|
#define USE_I2S_AAC
|
||||||
#endif // USE_I2S_ALL
|
#endif // USE_I2S_ALL
|
||||||
|
|
||||||
#endif // _MY_USER_CONFIG_H_
|
#endif // _MY_USER_CONFIG_H_
|
||||||
|
@ -52,6 +52,12 @@ enum : int8_t {
|
|||||||
I2S_SLOT_PHILIPS = 2, // Philips
|
I2S_SLOT_PHILIPS = 2, // Philips
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// I2S decoder type
|
||||||
|
enum : uint32_t {
|
||||||
|
AAC_DECODER = 0,
|
||||||
|
MP3_DECODER = 1,
|
||||||
|
};
|
||||||
|
|
||||||
#define I2S_SLOTS 2
|
#define I2S_SLOTS 2
|
||||||
#define AUDIO_SETTINGS_VERSION 2
|
#define AUDIO_SETTINGS_VERSION 2
|
||||||
|
|
||||||
|
@ -30,7 +30,9 @@
|
|||||||
#include "AudioGeneratorTalkie.h"
|
#include "AudioGeneratorTalkie.h"
|
||||||
#include "AudioFileSourceICYStream.h"
|
#include "AudioFileSourceICYStream.h"
|
||||||
#include "AudioFileSourceBuffer.h"
|
#include "AudioFileSourceBuffer.h"
|
||||||
|
#ifdef USE_I2S_AAC
|
||||||
#include "AudioGeneratorAAC.h"
|
#include "AudioGeneratorAAC.h"
|
||||||
|
#endif // USE_I2S_AAC
|
||||||
|
|
||||||
#include <layer3.h>
|
#include <layer3.h>
|
||||||
|
|
||||||
@ -54,9 +56,9 @@
|
|||||||
extern FS *ufsp;
|
extern FS *ufsp;
|
||||||
extern FS *ffsp;
|
extern FS *ffsp;
|
||||||
|
|
||||||
const int preallocateBufferSize = 16*1024;
|
constexpr int preallocateBufferSize = 16*1024;
|
||||||
const int preallocateCodecSize = 29192; // MP3 codec max mem needed
|
constexpr int preallocateCodecSize = 29192; // MP3 codec max mem needed
|
||||||
//const int preallocateCodecSize = 85332; // AAC+SBR codec max mem needed
|
constexpr int preallocateCodecSizeAAC = 85332; // AAC+SBR codec max mem needed
|
||||||
|
|
||||||
void sayTime(int hour, int minutes);
|
void sayTime(int hour, int minutes);
|
||||||
void Cmndwav2mp3(void);
|
void Cmndwav2mp3(void);
|
||||||
@ -81,7 +83,7 @@ struct AUDIO_I2S_MP3_t {
|
|||||||
#endif // USE_I2S_MP3
|
#endif // USE_I2S_MP3
|
||||||
|
|
||||||
#if defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO) || defined(USE_SHINE) || defined(MP3_MIC_STREAM)
|
#if defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO) || defined(USE_SHINE) || defined(MP3_MIC_STREAM)
|
||||||
AudioGeneratorMP3 *decoder = NULL;
|
AudioGenerator *decoder = nullptr;
|
||||||
TaskHandle_t mp3_task_handle;
|
TaskHandle_t mp3_task_handle;
|
||||||
TaskHandle_t mic_task_handle;
|
TaskHandle_t mic_task_handle;
|
||||||
#endif // defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO)
|
#endif // defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO)
|
||||||
|
@ -46,7 +46,29 @@ void I2SWrStatusCB(void *cbData, int code, const char *str){
|
|||||||
AddLog(LOG_LEVEL_INFO, "I2S: status: %s",str);
|
AddLog(LOG_LEVEL_INFO, "I2S: status: %s",str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Webradio(const char *url) {
|
bool I2SinitDecoder(uint32_t decoder_type){
|
||||||
|
switch(decoder_type){
|
||||||
|
case MP3_DECODER:
|
||||||
|
audio_i2s_mp3.decoder = dynamic_cast<AudioGenerator *>(new AudioGeneratorMP3(Audio_webradio.preallocateCodec, preallocateCodecSize));
|
||||||
|
break;
|
||||||
|
#ifdef USE_I2S_AAC
|
||||||
|
case AAC_DECODER:
|
||||||
|
Audio_webradio.preallocateCodec = special_realloc(Audio_webradio.preallocateCodec, preallocateCodecSizeAAC);
|
||||||
|
if(Audio_webradio.preallocateCodec == nullptr){
|
||||||
|
AddLog(LOG_LEVEL_ERROR, "I2S: could not alloc heap for AAC");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
audio_i2s_mp3.decoder = dynamic_cast<AudioGenerator *>(new AudioGeneratorAAC(Audio_webradio.preallocateCodec, preallocateCodecSizeAAC));
|
||||||
|
break;
|
||||||
|
#endif //USE_I2S_AAC
|
||||||
|
}
|
||||||
|
if(audio_i2s_mp3.decoder == nullptr){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool I2SWebradio(const char *url, uint32_t decoder_type) {
|
||||||
// allocate buffers if not already done
|
// allocate buffers if not already done
|
||||||
if (Audio_webradio.preallocateBuffer == NULL) {
|
if (Audio_webradio.preallocateBuffer == NULL) {
|
||||||
Audio_webradio.preallocateBuffer = special_malloc(preallocateBufferSize);
|
Audio_webradio.preallocateBuffer = special_malloc(preallocateBufferSize);
|
||||||
@ -65,41 +87,49 @@ void Webradio(const char *url) {
|
|||||||
free(Audio_webradio.preallocateCodec);
|
free(Audio_webradio.preallocateCodec);
|
||||||
Audio_webradio.preallocateCodec = NULL;
|
Audio_webradio.preallocateCodec = NULL;
|
||||||
}
|
}
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Audio_webradio.ifile = new AudioFileSourceICYStream();
|
Audio_webradio.ifile = new AudioFileSourceICYStream();
|
||||||
Audio_webradio.ifile->RegisterMetadataCB(I2sMDCallback, NULL);
|
Audio_webradio.ifile->RegisterMetadataCB(I2sMDCallback, NULL);
|
||||||
Audio_webradio.ifile->RegisterStatusCB(I2SWrStatusCB, NULL);
|
Audio_webradio.ifile->RegisterStatusCB(I2SWrStatusCB, NULL);
|
||||||
if(!Audio_webradio.ifile->open(url)){
|
if(!Audio_webradio.ifile->open(url)){
|
||||||
I2sWebRadioStopPlaying();
|
goto i2swr_fail;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
AddLog(LOG_LEVEL_INFO, "I2S: did connect to %s",url);
|
AddLog(LOG_LEVEL_INFO, "I2S: did connect to %s",url);
|
||||||
|
|
||||||
I2SAudioPower(true);
|
I2SAudioPower(true);
|
||||||
Audio_webradio.buff = new AudioFileSourceBuffer(Audio_webradio.ifile, Audio_webradio.preallocateBuffer, preallocateBufferSize);
|
Audio_webradio.buff = new AudioFileSourceBuffer(Audio_webradio.ifile, Audio_webradio.preallocateBuffer, preallocateBufferSize);
|
||||||
if(Audio_webradio.buff == nullptr){
|
if(Audio_webradio.buff == nullptr){
|
||||||
return;
|
goto i2swr_fail;
|
||||||
}
|
}
|
||||||
Audio_webradio.buff->RegisterStatusCB(I2sStatusCallback, NULL);
|
Audio_webradio.buff->RegisterStatusCB(I2sStatusCallback, NULL);
|
||||||
audio_i2s_mp3.decoder = new AudioGeneratorMP3(Audio_webradio.preallocateCodec, preallocateCodecSize);
|
|
||||||
if(audio_i2s_mp3.decoder == nullptr){
|
if(I2SinitDecoder(decoder_type) == false){
|
||||||
return;
|
AddLog(LOG_LEVEL_DEBUG, "I2S: decoder init failed");
|
||||||
}
|
goto i2swr_fail;
|
||||||
audio_i2s_mp3.decoder->RegisterStatusCB(I2sStatusCallback, NULL);
|
|
||||||
audio_i2s_mp3.decoder->begin(Audio_webradio.buff, audio_i2s.out);
|
|
||||||
if (!audio_i2s_mp3.decoder->isRunning()) {
|
|
||||||
I2sStopPlaying();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AddLog(LOG_LEVEL_DEBUG,PSTR("I2S: will launch webradio task"));
|
audio_i2s_mp3.decoder->RegisterStatusCB(I2sStatusCallback, NULL);
|
||||||
|
if(audio_i2s_mp3.decoder->begin(Audio_webradio.buff, audio_i2s.out)){
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, "I2S: decoder started");
|
||||||
|
} else {
|
||||||
|
goto i2swr_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddLog(LOG_LEVEL_DEBUG,PSTR("I2S: will launch webradio task with decoder type %u"), decoder_type);
|
||||||
xTaskCreatePinnedToCore(I2sMp3WrTask, "MP3-WR", 8192, NULL, 3, &audio_i2s_mp3.mp3_task_handle, 1);
|
xTaskCreatePinnedToCore(I2sMp3WrTask, "MP3-WR", 8192, NULL, 3, &audio_i2s_mp3.mp3_task_handle, 1);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
i2swr_fail:
|
||||||
|
I2sStopPlaying();
|
||||||
|
I2sWebRadioStopPlaying();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
const char HTTP_WEBRADIO[] PROGMEM =
|
const char HTTP_WEBRADIO[] PROGMEM =
|
||||||
"{s}" "I2S_WR-Title" "{m}%s{e}";
|
"{s}" "Webradio:" "{m}%s{e}";
|
||||||
|
|
||||||
void I2sWrShow(bool json) {
|
void I2sWrShow(bool json) {
|
||||||
if (audio_i2s_mp3.decoder) {
|
if (audio_i2s_mp3.decoder) {
|
||||||
@ -116,8 +146,11 @@ void CmndI2SWebRadio(void) {
|
|||||||
if (I2SPrepareTx() != I2S_OK) return;
|
if (I2SPrepareTx() != I2S_OK) return;
|
||||||
|
|
||||||
if (XdrvMailbox.data_len > 0) {
|
if (XdrvMailbox.data_len > 0) {
|
||||||
Webradio(XdrvMailbox.data);
|
if(I2SWebradio(XdrvMailbox.data, XdrvMailbox.index)){
|
||||||
ResponseCmndChar(XdrvMailbox.data);
|
ResponseCmndChar(XdrvMailbox.data);
|
||||||
|
} else {
|
||||||
|
ResponseCmndFailed();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ResponseCmndChar_P(PSTR("Stopped"));
|
ResponseCmndChar_P(PSTR("Stopped"));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user