diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_0_config_idf51.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_0_config_idf51.ino index f724da1f0..414a014ce 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_0_config_idf51.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_0_config_idf51.ino @@ -79,7 +79,8 @@ typedef struct{ uint8_t slot_config = I2S_SLOT_MSB;// B07 - slot configuration MSB = 0, PCM = 1, PHILIPS = 2 uint8_t channels = 2; // B08 - mono/stereo - 1 is added for both bool apll = 1; // B09 - will be ignored on unsupported SOC's - uint8_t spare[6]; // B0A-0F + bool stream_enable = 0; // B0A - enable streaming of MP3 + uint8_t spare[5]; // B0B-0F } tx; struct { uint32_t sample_rate = 16000; // B00-03 diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino index 33dae7ec6..e772add39 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_0_i2s_audio_idf51.ino @@ -65,6 +65,7 @@ void Cmd_Time(void); void Rtttl(char *buffer); void CmndI2SRtttl(void); void I2sWebRadioStopPlaying(void); +void CmndI2SMP3Stream(void); /*********************************************************************************************\ * More structures @@ -79,7 +80,7 @@ struct AUDIO_I2S_MP3_t { void *mp3ram = NULL; #endif // USE_I2S_MP3 -#if defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO) +#if defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO) || defined(USE_SHINE) || defined(MP3_MIC_STREAM) AudioGeneratorMP3 *decoder = NULL; TaskHandle_t mp3_task_handle; TaskHandle_t mic_task_handle; @@ -108,6 +109,9 @@ struct AUDIO_I2S_MP3_t { } audio_i2s_mp3; +#define I2S_AUDIO_MODE_MIC 1 +#define I2S_AUDIO_MODE_SPK 2 + /*********************************************************************************************\ * Commands definitions \*********************************************************************************************/ @@ -1033,7 +1037,7 @@ void CmndI2SMicGain(void) { \*********************************************************************************************/ void I2sMp3Loop(void); -void I2sMp3Init(void); +void I2sMp3Init(uint32_t on); void MP3ShowStream(void); bool Xdrv42(uint32_t function) { @@ -1059,7 +1063,7 @@ bool Xdrv42(uint32_t function) { break; case FUNC_WEB_ADD_HANDLER: #if defined(USE_SHINE) && defined(MP3_MIC_STREAM) - audio_i2s.stream_enable = 1; + audio_i2s.Settings->tx.stream_enable = 1; I2sMp3Init(1); #endif #if defined(I2S_BRIDGE) 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 d283abcaa..17974cc6e 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic.ino @@ -18,7 +18,7 @@ */ -#if ESP32 && (ESP_IDF_VERSION_MAJOR < 5) +#if defined(ESP32) && (ESP_IDF_VERSION_MAJOR < 5) #if ( (defined(USE_I2S_AUDIO) && defined(USE_I2S_MIC)) || defined(USE_M5STACK_CORE2) || defined(ESP32S3_BOX) ) uint32_t SpeakerMic(uint8_t spkr) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic_idf51.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic_idf51.ino index cfc9ba166..e846d07b6 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic_idf51.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_1_i2s_mp3mic_idf51.ino @@ -70,14 +70,14 @@ void mic_task(void *arg){ shine_set_config_mpeg_defaults(&config.mpeg); - if (audio_i2s.mic_channels == 1) { + if (audio_i2s.Settings->rx.channels == 1) { config.mpeg.mode = MONO; } else { config.mpeg.mode = STEREO; } config.mpeg.bitr = 128; - config.wave.samplerate = audio_i2s.mic_rate; - config.wave.channels = (channels)audio_i2s.mic_channels; + config.wave.samplerate = audio_i2s.Settings->rx.sample_rate; + config.wave.channels = (channels)audio_i2s.Settings->rx.channels; if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0) { error = 3; @@ -91,7 +91,7 @@ void mic_task(void *arg){ } samples_per_pass = shine_samples_per_pass(s); - bytesize = samples_per_pass * 2 * audio_i2s.mic_channels; + bytesize = samples_per_pass * 2 * audio_i2s.Settings->rx.channels; buffer = (int16_t*)malloc(bytesize); if (!buffer) { @@ -103,17 +103,18 @@ void mic_task(void *arg){ while (!audio_i2s_mp3.mic_stop) { uint32_t bytes_read; - i2s_read(audio_i2s.mic_port, (char *)buffer, bytesize, &bytes_read, (100 / portTICK_RATE_MS)); + bytes_read = audio_i2s.in->readMic((uint8_t*)buffer, bytesize, true /*dc_block*/, false /*apply_gain*/, true /*lowpass*/, nullptr /*peak_ptr*/); + // i2s_read(audio_i2s.mic_port, (char *)buffer, bytesize, &bytes_read, (100 / portTICK_PERIOD_MS)); - if (audio_i2s.mic_gain > 1) { + if (audio_i2s.Settings->rx.gain > 1) { // set gain for (uint32_t cnt = 0; cnt < bytes_read / 2; cnt++) { - buffer[cnt] *= audio_i2s.mic_gain; + buffer[cnt] *= audio_i2s.Settings->rx.gain; } } ucp = shine_encode_buffer_interleaved(s, buffer, &written); - if (!audio_i2s_mp3.use_stream) { + if (!audio_i2s.Settings->tx.stream_enable) { bwritten = mp3_out.write(ucp, written); if (bwritten != written) { break; @@ -152,11 +153,11 @@ exit: audio_i2s_mp3.client.stop(); } - SpeakerMic(MODE_SPK); + SpeakerMic(I2S_AUDIO_MODE_SPK); audio_i2s_mp3.mic_stop = 0; audio_i2s_mp3.mic_error = error; AddLog(LOG_LEVEL_INFO, PSTR("mp3task result code: %d"), error); - audio_i2s.mic_task_h = 0; + audio_i2s_mp3.mic_task_handle = 0; audio_i2s_mp3.recdur = 0; audio_i2s_mp3.stream_active = 0; vTaskDelete(NULL); @@ -166,14 +167,14 @@ exit: int32_t i2s_record_shine(char *path) { esp_err_t err = ESP_OK; - if (audio_i2s.mic_port == 0) { + if (audio_i2s.in) { if (audio_i2s_mp3.decoder || audio_i2s_mp3.mp3) return 0; } - err = SpeakerMic(MODE_MIC); + err = SpeakerMic(I2S_AUDIO_MODE_MIC); if (err) { - if (audio_i2s.mic_port == 0) { - SpeakerMic(MODE_SPK); + if (audio_i2s.in) { + SpeakerMic(I2S_AUDIO_MODE_SPK); } AddLog(LOG_LEVEL_INFO, PSTR("mic init error: %d"), err); return err; @@ -191,7 +192,7 @@ esp_err_t err = ESP_OK; stack = 8000; } - err = xTaskCreatePinnedToCore(mic_task, "MIC", stack, NULL, 3, &audio_i2s.mic_task_h, 1); + err = xTaskCreatePinnedToCore(mic_task, "MIC", stack, NULL, 3, &audio_i2s_mp3.mic_task_handle, 1); return err; } @@ -206,7 +207,7 @@ void Cmd_MicRec(void) { ResponseCmndChar(XdrvMailbox.data); } } else { - if (audio_i2s.mic_task_h) { + if (audio_i2s_mp3.mic_task_handle) { // stop task audio_i2s_mp3.mic_stop = 1; while (audio_i2s_mp3.mic_stop) { 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 af4a873bf..1fc06477f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream.ino @@ -1,5 +1,5 @@ -#ifdef ESP32 +#if defined(ESP32) && (ESP_IDF_VERSION_MAJOR < 5) #if defined(USE_SHINE) && ( (defined(USE_I2S_AUDIO) && defined(USE_I2S_MIC)) || defined(USE_M5STACK_CORE2) || defined(ESP32S3_BOX) ) #ifdef MP3_MIC_STREAM @@ -61,4 +61,4 @@ void Cmd_MP3Stream(void) { #endif // USE_SHINE -#endif // ESP32 +#endif // defined(ESP32) && (ESP_IDF_VERSION_MAJOR < 5) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream_idf51.ino b/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream_idf51.ino new file mode 100644 index 000000000..5a83f0d70 --- /dev/null +++ b/tasmota/tasmota_xdrv_driver/xdrv_42_2_i2s_mp3stream_idf51.ino @@ -0,0 +1,78 @@ +/* + xdrv_42_2_i2s_mp3stream_idf51.ino - Audio dac support for Tasmota + + Copyright (C) 2024 Gerhard Mutz and Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if defined(ESP32) && ESP_IDF_VERSION_MAJOR >= 5 +#if defined(USE_I2S_AUDIO) && defined(USE_SHINE) && defined(MP3_MIC_STREAM) + +#ifndef MP3_STREAM_PORT +#define MP3_STREAM_PORT 81 +#endif + + +void Stream_mp3(void) { + if (!audio_i2s.Settings->tx.stream_enable) { + return; + } + + if (audio_i2s_mp3.stream_active) { + return; + } + AddLog(LOG_LEVEL_INFO, PSTR("I2S: Handle mp3server")); + audio_i2s_mp3.stream_active = 1; + audio_i2s_mp3.client = audio_i2s_mp3.MP3Server->client(); + AddLog(LOG_LEVEL_INFO, PSTR("I2S: Create client")); + i2s_record_shine((char*)"stream.mp3"); +} + +void I2sMp3Loop(void) { + if (audio_i2s_mp3.MP3Server) { + audio_i2s_mp3.MP3Server->handleClient(); + } +} + +void I2sMp3Init(uint32_t on) { + if (on) { + if (!audio_i2s_mp3.MP3Server) { + audio_i2s_mp3.MP3Server = new ESP8266WebServer(MP3_STREAM_PORT); + audio_i2s_mp3.MP3Server->on(PSTR("/stream.mp3"), Stream_mp3); + audio_i2s_mp3.MP3Server->on(PSTR("/stream.m3a"), Stream_mp3); + audio_i2s_mp3.MP3Server->begin(); + AddLog(LOG_LEVEL_INFO, PSTR("MP3: server created on port: %d "), MP3_STREAM_PORT); + } + } else { + if (audio_i2s_mp3.MP3Server) { + audio_i2s_mp3.MP3Server->stop(); + delete audio_i2s_mp3.MP3Server; + audio_i2s_mp3.MP3Server = nullptr; + AddLog(LOG_LEVEL_INFO, PSTR("MP3: server deleted")); + } + } +} + + +void CmndI2SMP3Stream(void) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + audio_i2s_mp3.stream_enable = XdrvMailbox.payload; + } + I2sMp3Init(audio_i2s_mp3.stream_enable); + ResponseCmndNumber(audio_i2s_mp3.stream_enable); +} + +#endif // defined(USE_I2S_AUDIO) && defined(USE_SHINE) && defined(MP3_MIC_STREAM) +#endif // defined(ESP32) && ESP_IDF_VERSION_MAJOR >= 5