mirror of https://github.com/arendst/Tasmota.git
update i2s audio
This commit is contained in:
parent
7831c72be5
commit
4dc910391f
|
@ -67,13 +67,13 @@
|
|||
#define i2s_port_t uint8_t
|
||||
#endif
|
||||
|
||||
#ifdef ESP32
|
||||
#define MODE_MIC 0
|
||||
#define MODE_SPK 1
|
||||
|
||||
#ifndef MICSRATE
|
||||
#define MICSRATE 16000
|
||||
#define MICSRATE 32000
|
||||
#endif
|
||||
#endif // ESP32
|
||||
|
||||
|
||||
struct AUDIO_I2S_t {
|
||||
uint8_t is2_volume; // should be in settings
|
||||
|
@ -105,6 +105,7 @@ struct AUDIO_I2S_t {
|
|||
#ifdef ESP32
|
||||
TaskHandle_t mp3_task_h;
|
||||
TaskHandle_t mic_task_h;
|
||||
#endif // ESP32
|
||||
uint32_t mic_size;
|
||||
uint32_t mic_rate;
|
||||
uint8_t *mic_buff;
|
||||
|
@ -118,9 +119,10 @@ struct AUDIO_I2S_t {
|
|||
int8_t mic_ws = -1;
|
||||
int8_t mic_din = -1;
|
||||
int8_t mic_dout = -1;
|
||||
uint8_t mic_gain = 1;
|
||||
bool use_stream = false;
|
||||
i2s_port_t mic_port;
|
||||
#endif // ESP32
|
||||
|
||||
|
||||
#ifdef USE_SHINE
|
||||
uint32_t recdur;
|
||||
|
@ -130,10 +132,13 @@ struct AUDIO_I2S_t {
|
|||
ESP8266WebServer *MP3Server;
|
||||
#endif
|
||||
|
||||
uint8_t mode;
|
||||
|
||||
} audio_i2s;
|
||||
|
||||
|
||||
#ifndef MIC_CHANNELS
|
||||
#define MIC_CHANNELS 1
|
||||
#endif
|
||||
|
||||
#ifdef USE_TTGO_WATCH
|
||||
#undef AUDIO_PWR_ON
|
||||
|
@ -198,6 +203,15 @@ void Cmd_MicRec(void);
|
|||
void Cmd_wav2mp3(void);
|
||||
void Cmd_Time(void);
|
||||
|
||||
void copy_micpars(uint32_t port) {
|
||||
audio_i2s.mic_mclk = audio_i2s.mclk;
|
||||
audio_i2s.mic_bclk = audio_i2s.bclk;
|
||||
audio_i2s.mic_ws = audio_i2s.ws;
|
||||
audio_i2s.mic_dout = audio_i2s.dout;
|
||||
audio_i2s.mic_din = audio_i2s.din;
|
||||
audio_i2s.mic_port = (i2s_port_t)port;
|
||||
}
|
||||
|
||||
int32_t I2S_Init_0(void) {
|
||||
|
||||
audio_i2s.i2s_port = (i2s_port_t)0;
|
||||
|
@ -216,6 +230,9 @@ int32_t I2S_Init_0(void) {
|
|||
audio_i2s.ws = DAC_IIS_WS;
|
||||
audio_i2s.dout = DAC_IIS_DOUT;
|
||||
audio_i2s.din = DAC_IIS_DIN;
|
||||
|
||||
copy_micpars(0);
|
||||
|
||||
#else
|
||||
#ifdef USE_I2S_NO_DAC
|
||||
if (PinUsed(GPIO_I2S_DOUT)) {
|
||||
|
@ -235,12 +252,7 @@ int32_t I2S_Init_0(void) {
|
|||
audio_i2s.dout = Pin(GPIO_I2S_DOUT);
|
||||
audio_i2s.din = Pin(GPIO_I2S_DIN);
|
||||
|
||||
audio_i2s.mic_mclk = audio_i2s.mclk;
|
||||
audio_i2s.mic_bclk = audio_i2s.bclk;
|
||||
audio_i2s.mic_ws = audio_i2s.ws;
|
||||
audio_i2s.mic_dout = audio_i2s.dout;
|
||||
audio_i2s.mic_din = audio_i2s.din;
|
||||
audio_i2s.mic_port = (i2s_port_t)0;
|
||||
copy_micpars(0);
|
||||
|
||||
// check if 2 ports used, use second for micro
|
||||
if (PinUsed(GPIO_I2S_BCLK, 1) && PinUsed(GPIO_I2S_WS, 1) && PinUsed(GPIO_I2S_DIN, 1)) {
|
||||
|
@ -265,12 +277,7 @@ int32_t I2S_Init_0(void) {
|
|||
audio_i2s.dout = Pin(GPIO_I2S_DOUT, 1);
|
||||
audio_i2s.din = Pin(GPIO_I2S_DIN, 1);
|
||||
|
||||
audio_i2s.mic_mclk = audio_i2s.mclk;
|
||||
audio_i2s.mic_bclk = audio_i2s.bclk;
|
||||
audio_i2s.mic_ws = audio_i2s.ws;
|
||||
audio_i2s.mic_dout = audio_i2s.dout;
|
||||
audio_i2s.mic_din = audio_i2s.din;
|
||||
audio_i2s.mic_port = (i2s_port_t)1;
|
||||
copy_micpars(1);
|
||||
|
||||
} else {
|
||||
return -1;
|
||||
|
@ -299,21 +306,32 @@ int32_t I2S_Init_0(void) {
|
|||
|
||||
#endif // USE_I2S_EXTERNAL_DAC
|
||||
|
||||
audio_i2s.mode = MODE_SPK;
|
||||
|
||||
#idef USE_I2S_COMMON_IO
|
||||
audio_i2s.out->SetRate(MICSRATE);
|
||||
#endif
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void I2S_Init(void) {
|
||||
|
||||
#if defined(ESP32) && defined(ESP32S3_BOX)
|
||||
S3boxInit();
|
||||
#endif
|
||||
|
||||
if (I2S_Init_0()) {
|
||||
return;
|
||||
}
|
||||
|
||||
audio_i2s.is2_volume=10;
|
||||
audio_i2s.out->SetGain(((float)audio_i2s.is2_volume/100.0)*4.0);
|
||||
#if defined(ESP32) && defined(ESP32S3_BOX)
|
||||
S3boxInit();
|
||||
#endif
|
||||
|
||||
#ifdef USE_W8960
|
||||
W8960_Init();
|
||||
#endif
|
||||
|
||||
audio_i2s.is2_volume = 10;
|
||||
audio_i2s.out->SetGain(((float)audio_i2s.is2_volume / 100.0) * 4.0);
|
||||
audio_i2s.out->stop();
|
||||
audio_i2s.mp3ram = nullptr;
|
||||
|
||||
|
@ -517,12 +535,17 @@ void Play_mp3(const char *path) {
|
|||
if (I2S_Task) {
|
||||
xTaskCreatePinnedToCore(mp3_task, "MP3", 8192, NULL, 3, &audio_i2s.mp3_task_h, 1);
|
||||
} else {
|
||||
#define MP3_TIMEOUT 30000
|
||||
uint32_t tout = millis();
|
||||
while (audio_i2s.mp3->isRunning()) {
|
||||
if (!audio_i2s.mp3->loop()) {
|
||||
audio_i2s.mp3->stop();
|
||||
break;
|
||||
}
|
||||
OsWatchLoop();
|
||||
if (millis()-tout > MP3_TIMEOUT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
audio_i2s.out->stop();
|
||||
mp3_delete();
|
||||
|
@ -568,6 +591,7 @@ const char kI2SAudio_Commands[] PROGMEM = "I2S|"
|
|||
#endif // USE_I2S_WEBRADIO
|
||||
#if defined(USE_SHINE) && ( (defined(USE_I2S_AUDIO) && defined(USE_I2S_MIC)) || defined(USE_M5STACK_CORE2) || defined(ESP32S3_BOX) )
|
||||
"|REC"
|
||||
"|MGain"
|
||||
#ifdef MP3_MIC_STREAM
|
||||
"|STREAM"
|
||||
#endif // MP3_MIC_STREAM
|
||||
|
@ -587,6 +611,7 @@ void (* const I2SAudio_Command[])(void) PROGMEM = {
|
|||
#endif // USE_I2S_WEBRADIO
|
||||
#if defined(USE_SHINE) && ( (defined(USE_I2S_AUDIO) && defined(USE_I2S_MIC)) || defined(USE_M5STACK_CORE2) || defined(ESP32S3_BOX) )
|
||||
,&Cmd_MicRec
|
||||
,&Cmd_MicGain
|
||||
#ifdef MP3_MIC_STREAM
|
||||
,&Cmd_MP3Stream
|
||||
#endif // MP3_MIC_STREAM
|
||||
|
|
|
@ -21,30 +21,36 @@
|
|||
#ifdef ESP32
|
||||
#if defined(USE_SHINE) && ( (defined(USE_I2S_AUDIO) && defined(USE_I2S_MIC)) || defined(USE_M5STACK_CORE2) || defined(ESP32S3_BOX) )
|
||||
|
||||
#define MP3_BOUNDARY "e8b8c539-047d-4777-a985-fbba6edff11e"
|
||||
|
||||
uint32_t SpeakerMic(uint8_t spkr) {
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
#ifndef USE_I2S_COMMON_IO
|
||||
|
||||
if (spkr == MODE_SPK) {
|
||||
if (audio_i2s.mic_port == 0) {
|
||||
if (audio_i2s.i2s_port == audio_i2s.mic_port) {
|
||||
if (audio_i2s.mode != MODE_SPK) {
|
||||
i2s_driver_uninstall(audio_i2s.mic_port);
|
||||
}
|
||||
I2S_Init_0();
|
||||
audio_i2s.out->SetGain(((float)(audio_i2s.is2_volume-2)/100.0)*4.0);
|
||||
audio_i2s.out->SetGain(((float)(audio_i2s.is2_volume - 2) / 100.0) * 4.0);
|
||||
audio_i2s.out->stop();
|
||||
}
|
||||
audio_i2s.mode = spkr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// set micro
|
||||
if (audio_i2s.mic_port == 0) {
|
||||
if (audio_i2s.i2s_port == audio_i2s.mic_port) {
|
||||
// close audio out
|
||||
if (audio_i2s.out) {
|
||||
audio_i2s.out->stop();
|
||||
delete audio_i2s.out;
|
||||
audio_i2s.out = nullptr;
|
||||
}
|
||||
i2s_driver_uninstall(audio_i2s.i2s_port);
|
||||
if (audio_i2s.mode == MODE_SPK) {
|
||||
i2s_driver_uninstall(audio_i2s.i2s_port);
|
||||
}
|
||||
}
|
||||
|
||||
// config mic
|
||||
|
@ -104,6 +110,10 @@ esp_err_t err = ESP_OK;
|
|||
}
|
||||
err += i2s_set_clk(audio_i2s.mic_port, audio_i2s.mic_rate, I2S_BITS_PER_SAMPLE_16BIT, mode);
|
||||
|
||||
#endif // USE_I2S_COMMON_IO
|
||||
|
||||
audio_i2s.mode = spkr;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -112,8 +122,6 @@ esp_err_t err = ESP_OK;
|
|||
#include <layer3.h>
|
||||
#include <types.h>
|
||||
|
||||
#define MP3HANDLECLIENT audio_i2s.MP3Server->handleClient();
|
||||
|
||||
// micro to mp3 file or stream
|
||||
void mic_task(void *arg){
|
||||
int8_t error = 0;
|
||||
|
@ -144,7 +152,9 @@ void mic_task(void *arg){
|
|||
audio_i2s.client.setTimeout(3);
|
||||
audio_i2s.client.print("HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: audio/mpeg;\r\n\r\n");
|
||||
MP3HANDLECLIENT
|
||||
|
||||
// Webserver->send(200, "application/octet-stream", "");
|
||||
//"Content-Type: audio/mp3;\r\n\r\n");
|
||||
}
|
||||
|
||||
shine_set_config_mpeg_defaults(&config.mpeg);
|
||||
|
@ -183,6 +193,13 @@ void mic_task(void *arg){
|
|||
while (!audio_i2s.mic_stop) {
|
||||
uint32_t bytes_read;
|
||||
i2s_read(audio_i2s.mic_port, (char *)buffer, bytesize, &bytes_read, (100 / portTICK_RATE_MS));
|
||||
|
||||
if (audio_i2s.mic_gain > 1) {
|
||||
// set gain
|
||||
for (uint32_t cnt = 0; cnt < bytes_read / 2; cnt++) {
|
||||
buffer[cnt] *= audio_i2s.mic_gain;
|
||||
}
|
||||
}
|
||||
ucp = shine_encode_buffer_interleaved(s, buffer, &written);
|
||||
|
||||
if (!audio_i2s.use_stream) {
|
||||
|
@ -192,7 +209,7 @@ void mic_task(void *arg){
|
|||
}
|
||||
} else {
|
||||
audio_i2s.client.write((const char*)ucp, written);
|
||||
MP3HANDLECLIENT
|
||||
|
||||
if (!audio_i2s.client.connected()) {
|
||||
break;
|
||||
}
|
||||
|
@ -206,7 +223,6 @@ void mic_task(void *arg){
|
|||
mp3_out.write(ucp, written);
|
||||
} else {
|
||||
audio_i2s.client.write((const char*)ucp, written);
|
||||
MP3HANDLECLIENT
|
||||
}
|
||||
|
||||
|
||||
|
@ -223,13 +239,12 @@ exit:
|
|||
|
||||
if (audio_i2s.use_stream) {
|
||||
audio_i2s.client.stop();
|
||||
MP3HANDLECLIENT
|
||||
}
|
||||
|
||||
SpeakerMic(MODE_SPK);
|
||||
audio_i2s.mic_stop = 0;
|
||||
audio_i2s.mic_error = error;
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("mp3task error: %d"), error);
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("mp3task result code: %d"), error);
|
||||
audio_i2s.mic_task_h = 0;
|
||||
audio_i2s.recdur = 0;
|
||||
audio_i2s.stream_active = 0;
|
||||
|
@ -292,6 +307,14 @@ void Cmd_MicRec(void) {
|
|||
|
||||
}
|
||||
|
||||
// mic gain in factor not percent
|
||||
void Cmd_MicGain(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 256)) {
|
||||
audio_i2s.mic_gain = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndNumber(audio_i2s.mic_gain);
|
||||
}
|
||||
|
||||
#endif // USE_SHINE
|
||||
#endif // USE_I2S_AUDIO
|
||||
#endif // ESP32
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
|
||||
#ifdef MP3_MIC_STREAM
|
||||
|
||||
#ifndef MP3_STREAM_PORT
|
||||
#define MP3_STREAM_PORT 81
|
||||
#endif
|
||||
|
||||
|
||||
void Stream_mp3(void) {
|
||||
if (!audio_i2s.stream_enable) {
|
||||
return;
|
||||
|
@ -28,10 +33,11 @@ void i2s_mp3_loop(void) {
|
|||
void i2s_mp3_init(uint32_t on) {
|
||||
if (on) {
|
||||
if (!audio_i2s.MP3Server) {
|
||||
audio_i2s.MP3Server = new ESP8266WebServer(81);
|
||||
audio_i2s.MP3Server = new ESP8266WebServer(MP3_STREAM_PORT);
|
||||
audio_i2s.MP3Server->on(PSTR("/stream.mp3"), Stream_mp3);
|
||||
audio_i2s.MP3Server->on(PSTR("/stream.m3a"), Stream_mp3);
|
||||
audio_i2s.MP3Server->begin();
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("MP3: server created"));
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("MP3: server created on port: %d "), MP3_STREAM_PORT);
|
||||
}
|
||||
} else {
|
||||
if (audio_i2s.MP3Server) {
|
||||
|
|
|
@ -70,7 +70,6 @@ uint32_t es7243e_init() {
|
|||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
// box adc init
|
||||
uint32_t es7210_init() {
|
||||
uint32_t ret_val = ESP_OK;
|
||||
|
@ -124,7 +123,7 @@ uint32_t ES8311_init() {
|
|||
return ret_val;
|
||||
}
|
||||
|
||||
void S3boxInit() {
|
||||
void S3boxInit(void) {
|
||||
if (TasmotaGlobal.i2c_enabled_2) {
|
||||
// box lite
|
||||
ES8156_init();
|
||||
|
@ -137,4 +136,20 @@ void S3boxInit() {
|
|||
}
|
||||
}
|
||||
#endif // ESP32S3_BOX
|
||||
|
||||
|
||||
#ifdef USE_W8960
|
||||
|
||||
#include <wm8960.h>
|
||||
|
||||
void W8960_Init(void) {
|
||||
if (TasmotaGlobal.i2c_enabled_2) {
|
||||
if (I2cSetDevice(W8960_ADDR, 1)) {
|
||||
I2cSetActiveFound(W8960_ADDR, "W8960-I2C", 1);
|
||||
W8960_Init(&Wire1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // USE_W8960
|
||||
|
||||
#endif // ESP32
|
Loading…
Reference in New Issue