diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio.ino index 8dc835059..935a95633 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio.ino @@ -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 diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic.ino index 53550300c..d9ba85259 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic.ino @@ -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 #include -#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 diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream.ino index 72495edb9..af4a873bf 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream.ino @@ -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) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_4_i2s_s3box.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_4_i2s_codecs.ino similarity index 93% rename from tasmota/tasmota_xdrv_driver/xdrv_42_4_i2s_s3box.ino rename to tasmota/tasmota_xdrv_driver/xdrv_42_4_i2s_codecs.ino index 8bf927fc2..1b66edbf9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_4_i2s_s3box.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_4_i2s_codecs.ino @@ -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 + +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