mirror of https://github.com/arendst/Tasmota.git
multiple fixes (#21511)
This commit is contained in:
parent
7b478f718c
commit
a4dbc57448
|
@ -186,7 +186,9 @@ bool AudioGeneratorMP3::GetOneSample(int16_t sample[2])
|
||||||
// If we're here, we have one decoded frame and sent 0 or more samples out
|
// If we're here, we have one decoded frame and sent 0 or more samples out
|
||||||
if (samplePtr < synth->pcm.length) {
|
if (samplePtr < synth->pcm.length) {
|
||||||
sample[AudioOutput::LEFTCHANNEL ] = synth->pcm.samples[0][samplePtr];
|
sample[AudioOutput::LEFTCHANNEL ] = synth->pcm.samples[0][samplePtr];
|
||||||
sample[AudioOutput::RIGHTCHANNEL] = synth->pcm.samples[1][samplePtr];
|
if(lastChannels == 2) {
|
||||||
|
sample[AudioOutput::RIGHTCHANNEL] = synth->pcm.samples[1][samplePtr];
|
||||||
|
}
|
||||||
samplePtr++;
|
samplePtr++;
|
||||||
} else {
|
} else {
|
||||||
samplePtr = 0;
|
samplePtr = 0;
|
||||||
|
@ -200,7 +202,9 @@ bool AudioGeneratorMP3::GetOneSample(int16_t sample[2])
|
||||||
}
|
}
|
||||||
// for IGNORE and CONTINUE, just play what we have now
|
// for IGNORE and CONTINUE, just play what we have now
|
||||||
sample[AudioOutput::LEFTCHANNEL ] = synth->pcm.samples[0][samplePtr];
|
sample[AudioOutput::LEFTCHANNEL ] = synth->pcm.samples[0][samplePtr];
|
||||||
sample[AudioOutput::RIGHTCHANNEL] = synth->pcm.samples[1][samplePtr];
|
if(lastChannels == 2) {
|
||||||
|
sample[AudioOutput::RIGHTCHANNEL] = synth->pcm.samples[1][samplePtr];
|
||||||
|
}
|
||||||
samplePtr++;
|
samplePtr++;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -190,7 +190,7 @@ bool AudioOutputMixer::loop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (avail) {
|
if (avail) {
|
||||||
int16_t s[2];
|
int16_t s[2] = {0};
|
||||||
if (leftAccum[readPtr] > 32767) {
|
if (leftAccum[readPtr] > 32767) {
|
||||||
s[LEFTCHANNEL] = 32767;
|
s[LEFTCHANNEL] = 32767;
|
||||||
} else if (leftAccum[readPtr] < -32767) {
|
} else if (leftAccum[readPtr] < -32767) {
|
||||||
|
|
|
@ -197,6 +197,7 @@ public:
|
||||||
// Tx
|
// Tx
|
||||||
virtual bool begin(void) { return beginTx(); }; // the name `begin()`is inherited from superclass, prefer `beginTx()` which is more explicit
|
virtual bool begin(void) { return beginTx(); }; // the name `begin()`is inherited from superclass, prefer `beginTx()` which is more explicit
|
||||||
virtual bool stop(void) { return stopTx(); }; // the name `stop()`is inherited from superclass, prefer `stopTx()` which is more explicit
|
virtual bool stop(void) { return stopTx(); }; // the name `stop()`is inherited from superclass, prefer `stopTx()` which is more explicit
|
||||||
|
virtual void flush(void); // makes sure that all stored DMA samples are consumed / played to prevent static noise after stop()
|
||||||
bool beginTx(void);
|
bool beginTx(void);
|
||||||
bool stopTx(void);
|
bool stopTx(void);
|
||||||
bool ConsumeSample(int16_t sample[2]);
|
bool ConsumeSample(int16_t sample[2]);
|
||||||
|
@ -322,6 +323,11 @@ bool TasmotaI2S::beginTx(void) {
|
||||||
} else
|
} else
|
||||||
#endif // SOC_DAC_SUPPORTED
|
#endif // SOC_DAC_SUPPORTED
|
||||||
{
|
{
|
||||||
|
uint8_t zero_buffer[240] = {0};
|
||||||
|
size_t sz;
|
||||||
|
for(int i = 0;i < 6;i++){
|
||||||
|
i2s_channel_preload_data(_tx_handle, zero_buffer, sizeof(zero_buffer), &sz); // preload DMA buffer with silence
|
||||||
|
}
|
||||||
err = i2s_channel_enable(_tx_handle);
|
err = i2s_channel_enable(_tx_handle);
|
||||||
}
|
}
|
||||||
AddLog(LOG_LEVEL_INFO, "I2S: Tx i2s_channel_enable err=0x%04X", err);
|
AddLog(LOG_LEVEL_INFO, "I2S: Tx i2s_channel_enable err=0x%04X", err);
|
||||||
|
@ -363,6 +369,20 @@ bool TasmotaI2S::stopTx() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TasmotaI2S::flush()
|
||||||
|
{
|
||||||
|
int buffersize = 6 * 240;
|
||||||
|
int16_t samples[2] = {0x0, 0x0};
|
||||||
|
for (int i = 0; i < buffersize; i++)
|
||||||
|
{
|
||||||
|
while (!ConsumeSample(samples))
|
||||||
|
{
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddLog(LOG_LEVEL_INFO, "I2S: flush DMA TX buffer");
|
||||||
|
}
|
||||||
|
|
||||||
bool TasmotaI2S::delTxHandle(void) {
|
bool TasmotaI2S::delTxHandle(void) {
|
||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
AddLog(LOG_LEVEL_DEBUG, "I2S: calling delTxHandle() tx_running:%i tx_handle:%p", _tx_running, _tx_handle);
|
AddLog(LOG_LEVEL_DEBUG, "I2S: calling delTxHandle() tx_running:%i tx_handle:%p", _tx_running, _tx_handle);
|
||||||
|
|
|
@ -473,7 +473,7 @@ exit:
|
||||||
audio_i2s.in->stopRx();
|
audio_i2s.in->stopRx();
|
||||||
audio_i2s_mp3.mic_stop = 0;
|
audio_i2s_mp3.mic_stop = 0;
|
||||||
audio_i2s_mp3.mic_error = error;
|
audio_i2s_mp3.mic_error = error;
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("mp3task result code: %d"), error);
|
AddLog(LOG_LEVEL_INFO, PSTR("I2S: mp3task result code: %d"), error);
|
||||||
audio_i2s_mp3.mic_task_handle = 0;
|
audio_i2s_mp3.mic_task_handle = 0;
|
||||||
audio_i2s_mp3.recdur = 0;
|
audio_i2s_mp3.recdur = 0;
|
||||||
audio_i2s_mp3.stream_active = 0;
|
audio_i2s_mp3.stream_active = 0;
|
||||||
|
@ -484,6 +484,15 @@ exit:
|
||||||
int32_t I2sRecordShine(char *path) {
|
int32_t I2sRecordShine(char *path) {
|
||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
|
|
||||||
|
switch(audio_i2s.Settings->rx.sample_rate){
|
||||||
|
case 32000: case 48000: case 44100:
|
||||||
|
break; // supported
|
||||||
|
default:
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("I2S: unsupported sample rate for MP3 encoding: %d"), audio_i2s.Settings->rx.sample_rate);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("I2S: accepted sample rate for MP3 encoding: %d"), audio_i2s.Settings->rx.sample_rate);
|
||||||
|
|
||||||
#ifdef USE_I2S_MP3
|
#ifdef USE_I2S_MP3
|
||||||
if (audio_i2s_mp3.decoder || audio_i2s_mp3.mp3) return 0;
|
if (audio_i2s_mp3.decoder || audio_i2s_mp3.mp3) return 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -735,8 +744,8 @@ void I2sInit(void) {
|
||||||
}
|
}
|
||||||
if (init_tx_ok) { audio_i2s.out = i2s; }
|
if (init_tx_ok) { audio_i2s.out = i2s; }
|
||||||
if (init_rx_ok) { audio_i2s.in = i2s; }
|
if (init_rx_ok) { audio_i2s.in = i2s; }
|
||||||
audio_i2s.Settings->sys.tx = init_tx_ok;
|
audio_i2s.Settings->sys.tx |= init_tx_ok; // Do not set to zero id already configured on another channnel
|
||||||
audio_i2s.Settings->sys.rx = init_rx_ok;
|
audio_i2s.Settings->sys.rx |= init_rx_ok;
|
||||||
if (init_tx_ok && init_rx_ok) { audio_i2s.Settings->sys.duplex = true; }
|
if (init_tx_ok && init_rx_ok) { audio_i2s.Settings->sys.duplex = true; }
|
||||||
|
|
||||||
// if intput and output are configured, don't proceed with other IS2 ports
|
// if intput and output are configured, don't proceed with other IS2 ports
|
||||||
|
@ -750,11 +759,11 @@ void I2sInit(void) {
|
||||||
if (audio_i2s.out) { audio_i2s.out->setExclusive(exclusive); }
|
if (audio_i2s.out) { audio_i2s.out->setExclusive(exclusive); }
|
||||||
if (audio_i2s.in) { audio_i2s.in->setExclusive(exclusive); }
|
if (audio_i2s.in) { audio_i2s.in->setExclusive(exclusive); }
|
||||||
|
|
||||||
if(audio_i2s.out != nullptr){
|
// if(audio_i2s.out != nullptr){
|
||||||
audio_i2s.out->SetGain(((float)audio_i2s.Settings->tx.gain / 100.0) * 4.0);
|
// audio_i2s.out->SetGain(((float)(audio_i2s.Settings->tx.gain + 1)/ 100.0));
|
||||||
audio_i2s.out->beginTx(); // TODO - useful?
|
// audio_i2s.out->beginTx(); // TODO - useful?
|
||||||
audio_i2s.out->stopTx();
|
// audio_i2s.out->stopTx();
|
||||||
}
|
// }
|
||||||
#ifdef USE_I2S_MP3
|
#ifdef USE_I2S_MP3
|
||||||
audio_i2s_mp3.mp3ram = nullptr;
|
audio_i2s_mp3.mp3ram = nullptr;
|
||||||
if (audio_i2s.Settings->sys.mp3_preallocate == 1){
|
if (audio_i2s.Settings->sys.mp3_preallocate == 1){
|
||||||
|
@ -785,10 +794,20 @@ int32_t I2SPrepareTx(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (audio_i2s_mp3.mic_task_handle) {
|
||||||
|
audio_i2s_mp3.mic_stop = 1;
|
||||||
|
while (audio_i2s_mp3.mic_stop) {
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AddLog(LOG_LEVEL_DEBUG, "I2S: I2SPrepareTx out=%p", audio_i2s.out);
|
AddLog(LOG_LEVEL_DEBUG, "I2S: I2SPrepareTx out=%p", audio_i2s.out);
|
||||||
if (!audio_i2s.out) { return I2S_ERR_OUTPUT_NOT_CONFIGURED; }
|
if (!audio_i2s.out) { return I2S_ERR_OUTPUT_NOT_CONFIGURED; }
|
||||||
|
|
||||||
if (!audio_i2s.out->beginTx()) { return I2S_ERR_TX_FAILED; }
|
if (!audio_i2s.out->beginTx()) { return I2S_ERR_TX_FAILED; }
|
||||||
|
|
||||||
|
audio_i2s.out->SetGain(((float)(audio_i2s.Settings->tx.gain + 1)/ 100.0));
|
||||||
|
|
||||||
return I2S_OK;
|
return I2S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -813,21 +832,20 @@ int32_t I2SPrepareRx(void) {
|
||||||
|
|
||||||
#if defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO)
|
#if defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO)
|
||||||
void I2sMp3Task(void *arg) {
|
void I2sMp3Task(void *arg) {
|
||||||
while (1) {
|
audio_i2s_mp3.task_running = true;
|
||||||
while (audio_i2s_mp3.mp3->isRunning()) {
|
while (audio_i2s_mp3.mp3->isRunning() && audio_i2s_mp3.task_running) {
|
||||||
if (!audio_i2s_mp3.mp3->loop()) {
|
if (!audio_i2s_mp3.mp3->loop()) {
|
||||||
audio_i2s_mp3.mp3->stop();
|
audio_i2s_mp3.task_running == false;
|
||||||
mp3_delete();
|
|
||||||
audio_i2s.out->stop();
|
|
||||||
if (audio_i2s_mp3.mp3_task_handle) {
|
|
||||||
vTaskDelete(audio_i2s_mp3.mp3_task_handle);
|
|
||||||
audio_i2s_mp3.mp3_task_handle = 0;
|
|
||||||
}
|
|
||||||
//mp3_task_handle=nullptr;
|
|
||||||
}
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1));
|
|
||||||
}
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
}
|
}
|
||||||
|
audio_i2s.out->flush();
|
||||||
|
audio_i2s_mp3.mp3->stop();
|
||||||
|
I2sStopPlaying();
|
||||||
|
mp3_delete();
|
||||||
|
audio_i2s_mp3.mp3_task_handle = nullptr;
|
||||||
|
audio_i2s_mp3.task_has_ended = true;
|
||||||
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
#endif // defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO)
|
#endif // defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO)
|
||||||
|
|
||||||
|
@ -851,29 +869,17 @@ void I2sMp3WrTask(void *arg){
|
||||||
vTaskDelay(pdMS_TO_TICKS(1));
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
audio_i2s_mp3.decoder->stop();
|
audio_i2s.out->flush();
|
||||||
audio_i2s_mp3.task_has_ended = true;
|
|
||||||
I2sStopPlaying();
|
I2sStopPlaying();
|
||||||
|
audio_i2s_mp3.mp3_task_handle = nullptr;
|
||||||
|
audio_i2s_mp3.task_has_ended = true;
|
||||||
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
void I2SStopMP3Play(void) {
|
|
||||||
|
|
||||||
if (audio_i2s_mp3.decoder) {
|
|
||||||
audio_i2s_mp3.decoder->stop();
|
|
||||||
delete audio_i2s_mp3.decoder;
|
|
||||||
audio_i2s_mp3.decoder = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audio_i2s_mp3.mp3_task_handle) {
|
|
||||||
vTaskDelete(audio_i2s_mp3.mp3_task_handle);
|
|
||||||
audio_i2s_mp3.mp3_task_handle = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // USE_I2S_MP3
|
#endif // USE_I2S_MP3
|
||||||
|
|
||||||
void I2sStopPlaying() {
|
void I2sStopPlaying() {
|
||||||
#ifdef USE_I2S_MP3
|
|
||||||
I2SStopMP3Play();
|
|
||||||
#endif // USE_I2S_MP3
|
|
||||||
#ifdef USE_I2S_WEBRADIO
|
#ifdef USE_I2S_WEBRADIO
|
||||||
I2sWebRadioStopPlaying();
|
I2sWebRadioStopPlaying();
|
||||||
#endif
|
#endif
|
||||||
|
@ -921,7 +927,12 @@ void mp3_delete(void) {
|
||||||
delete audio_i2s_mp3.id3;
|
delete audio_i2s_mp3.id3;
|
||||||
delete audio_i2s_mp3.mp3;
|
delete audio_i2s_mp3.mp3;
|
||||||
audio_i2s_mp3.mp3=nullptr;
|
audio_i2s_mp3.mp3=nullptr;
|
||||||
I2SAudioPower(false);
|
|
||||||
|
if (audio_i2s_mp3.decoder) {
|
||||||
|
audio_i2s_mp3.decoder->stop();
|
||||||
|
delete audio_i2s_mp3.decoder;
|
||||||
|
audio_i2s_mp3.decoder = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // USE_I2S_MP3
|
#endif // USE_I2S_MP3
|
||||||
|
|
||||||
|
@ -959,7 +970,7 @@ void CmndI2SMic(void) {
|
||||||
|
|
||||||
|
|
||||||
void CmndI2SStop(void) {
|
void CmndI2SStop(void) {
|
||||||
if (!I2SPrepareTx()) {
|
if (I2SPrepareTx() != I2S_OK) {
|
||||||
ResponseCmndChar("I2S output not configured");
|
ResponseCmndChar("I2S output not configured");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1006,7 +1017,7 @@ void CmndI2SGain(void) {
|
||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
|
||||||
if (audio_i2s.out) {
|
if (audio_i2s.out) {
|
||||||
audio_i2s.Settings->tx.gain = XdrvMailbox.payload;
|
audio_i2s.Settings->tx.gain = XdrvMailbox.payload;
|
||||||
audio_i2s.out->SetGain(((float)(audio_i2s.Settings->tx.gain-2)/100.0)*4.0);
|
audio_i2s.out->SetGain(((float)(audio_i2s.Settings->tx.gain+1)/100.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResponseCmndNumber(audio_i2s.Settings->tx.gain);
|
ResponseCmndNumber(audio_i2s.Settings->tx.gain);
|
||||||
|
@ -1050,8 +1061,12 @@ void CmndI2SMicRec(void) {
|
||||||
if (!strncmp(XdrvMailbox.data, "-?", 2)) {
|
if (!strncmp(XdrvMailbox.data, "-?", 2)) {
|
||||||
Response_P("{\"I2SREC-duration\":%d}", audio_i2s_mp3.recdur);
|
Response_P("{\"I2SREC-duration\":%d}", audio_i2s_mp3.recdur);
|
||||||
} else {
|
} else {
|
||||||
I2sRecordShine(XdrvMailbox.data);
|
int err = I2sRecordShine(XdrvMailbox.data);
|
||||||
ResponseCmndChar(XdrvMailbox.data);
|
if(err == pdPASS){
|
||||||
|
ResponseCmndChar(XdrvMailbox.data);
|
||||||
|
} else {
|
||||||
|
ResponseCmndChar_P(PSTR("Did not launch recording task"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (audio_i2s_mp3.mic_task_handle) {
|
if (audio_i2s_mp3.mic_task_handle) {
|
||||||
|
@ -1062,6 +1077,9 @@ void CmndI2SMicRec(void) {
|
||||||
}
|
}
|
||||||
ResponseCmndChar_P(PSTR("Stopped"));
|
ResponseCmndChar_P(PSTR("Stopped"));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
ResponseCmndChar_P(PSTR("No running recording"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
|
@ -21,219 +21,219 @@
|
||||||
#if defined(ESP32) && ESP_IDF_VERSION_MAJOR >= 5
|
#if defined(ESP32) && ESP_IDF_VERSION_MAJOR >= 5
|
||||||
#ifdef USE_I2S_AUDIO
|
#ifdef USE_I2S_AUDIO
|
||||||
|
|
||||||
uint32_t SpeakerMic(uint8_t spkr) {
|
// uint32_t SpeakerMic(uint8_t spkr) {
|
||||||
esp_err_t err = ESP_OK;
|
// esp_err_t err = ESP_OK;
|
||||||
|
|
||||||
// audio_i2s.mode = spkr;
|
// // audio_i2s.mode = spkr;
|
||||||
return err;
|
// return err;
|
||||||
}
|
// }
|
||||||
|
|
||||||
#ifdef USE_SHINE
|
// #ifdef USE_SHINE
|
||||||
|
|
||||||
#include <layer3.h>
|
// #include <layer3.h>
|
||||||
#include <types.h>
|
// #include <types.h>
|
||||||
|
|
||||||
// micro to mp3 file or stream
|
// // micro to mp3 file or stream
|
||||||
void mic_task(void *arg){
|
// void mic_task(void *arg){
|
||||||
int8_t error = 0;
|
// int8_t error = 0;
|
||||||
uint8_t *ucp;
|
// uint8_t *ucp;
|
||||||
int written;
|
// int written;
|
||||||
shine_config_t config;
|
// shine_config_t config;
|
||||||
shine_t s = nullptr;
|
// shine_t s = nullptr;
|
||||||
uint16_t samples_per_pass;
|
// uint16_t samples_per_pass;
|
||||||
File mp3_out = (File)nullptr;
|
// File mp3_out = (File)nullptr;
|
||||||
int16_t *buffer = nullptr;
|
// int16_t *buffer = nullptr;
|
||||||
uint16_t bytesize;
|
// uint16_t bytesize;
|
||||||
uint16_t bwritten;
|
// uint16_t bwritten;
|
||||||
uint32_t ctime;
|
// uint32_t ctime;
|
||||||
|
|
||||||
if (!audio_i2s_mp3.use_stream) {
|
// if (!audio_i2s_mp3.use_stream) {
|
||||||
mp3_out = ufsp->open(audio_i2s_mp3.mic_path, "w");
|
// mp3_out = ufsp->open(audio_i2s_mp3.mic_path, "w");
|
||||||
if (!mp3_out) {
|
// if (!mp3_out) {
|
||||||
error = 1;
|
// error = 1;
|
||||||
goto exit;
|
// goto exit;
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
if (!audio_i2s_mp3.stream_active) {
|
// if (!audio_i2s_mp3.stream_active) {
|
||||||
error = 2;
|
// error = 2;
|
||||||
audio_i2s_mp3.use_stream = 0;
|
// audio_i2s_mp3.use_stream = 0;
|
||||||
goto exit;
|
// goto exit;
|
||||||
}
|
// }
|
||||||
audio_i2s_mp3.client.flush();
|
// audio_i2s_mp3.client.flush();
|
||||||
audio_i2s_mp3.client.setTimeout(3);
|
// audio_i2s_mp3.client.setTimeout(3);
|
||||||
audio_i2s_mp3.client.print("HTTP/1.1 200 OK\r\n"
|
// audio_i2s_mp3.client.print("HTTP/1.1 200 OK\r\n"
|
||||||
"Content-Type: audio/mpeg;\r\n\r\n");
|
// "Content-Type: audio/mpeg;\r\n\r\n");
|
||||||
|
|
||||||
// Webserver->send(200, "application/octet-stream", "");
|
// // Webserver->send(200, "application/octet-stream", "");
|
||||||
//"Content-Type: audio/mp3;\r\n\r\n");
|
// //"Content-Type: audio/mp3;\r\n\r\n");
|
||||||
}
|
// }
|
||||||
|
|
||||||
shine_set_config_mpeg_defaults(&config.mpeg);
|
// shine_set_config_mpeg_defaults(&config.mpeg);
|
||||||
|
|
||||||
if (audio_i2s.Settings->rx.channels == 1) {
|
// if (audio_i2s.Settings->rx.channels == 1) {
|
||||||
config.mpeg.mode = MONO;
|
// config.mpeg.mode = MONO;
|
||||||
} else {
|
// } else {
|
||||||
config.mpeg.mode = STEREO;
|
// config.mpeg.mode = STEREO;
|
||||||
}
|
// }
|
||||||
config.mpeg.bitr = 128;
|
// config.mpeg.bitr = 128;
|
||||||
config.wave.samplerate = audio_i2s.Settings->rx.sample_rate;
|
// config.wave.samplerate = audio_i2s.Settings->rx.sample_rate;
|
||||||
config.wave.channels = (channels)audio_i2s.Settings->rx.channels;
|
// config.wave.channels = (channels)audio_i2s.Settings->rx.channels;
|
||||||
|
|
||||||
if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0) {
|
// if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0) {
|
||||||
error = 3;
|
// error = 3;
|
||||||
goto exit;
|
// goto exit;
|
||||||
}
|
// }
|
||||||
|
|
||||||
s = shine_initialise(&config);
|
// s = shine_initialise(&config);
|
||||||
if (!s) {
|
// if (!s) {
|
||||||
error = 4;
|
// error = 4;
|
||||||
goto exit;
|
// goto exit;
|
||||||
}
|
// }
|
||||||
|
|
||||||
samples_per_pass = shine_samples_per_pass(s);
|
// samples_per_pass = shine_samples_per_pass(s);
|
||||||
bytesize = samples_per_pass * 2 * audio_i2s.Settings->rx.channels;
|
// bytesize = samples_per_pass * 2 * audio_i2s.Settings->rx.channels;
|
||||||
|
|
||||||
buffer = (int16_t*)malloc(bytesize);
|
// buffer = (int16_t*)malloc(bytesize);
|
||||||
if (!buffer) {
|
// if (!buffer) {
|
||||||
error = 5;
|
// error = 5;
|
||||||
goto exit;
|
// goto exit;
|
||||||
}
|
// }
|
||||||
|
|
||||||
ctime = TasmotaGlobal.uptime;
|
// ctime = TasmotaGlobal.uptime;
|
||||||
|
|
||||||
while (!audio_i2s_mp3.mic_stop) {
|
// while (!audio_i2s_mp3.mic_stop) {
|
||||||
uint32_t bytes_read;
|
// uint32_t bytes_read;
|
||||||
bytes_read = audio_i2s.in->readMic((uint8_t*)buffer, bytesize, true /*dc_block*/, false /*apply_gain*/, true /*lowpass*/, nullptr /*peak_ptr*/);
|
// 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));
|
// // i2s_read(audio_i2s.mic_port, (char *)buffer, bytesize, &bytes_read, (100 / portTICK_PERIOD_MS));
|
||||||
|
|
||||||
if (audio_i2s.Settings->rx.gain > 1) {
|
// if (audio_i2s.Settings->rx.gain > 1) {
|
||||||
// set gain
|
// // set gain
|
||||||
for (uint32_t cnt = 0; cnt < bytes_read / 2; cnt++) {
|
// for (uint32_t cnt = 0; cnt < bytes_read / 2; cnt++) {
|
||||||
buffer[cnt] *= audio_i2s.Settings->rx.gain;
|
// buffer[cnt] *= audio_i2s.Settings->rx.gain;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
ucp = shine_encode_buffer_interleaved(s, buffer, &written);
|
// ucp = shine_encode_buffer_interleaved(s, buffer, &written);
|
||||||
|
|
||||||
if (!audio_i2s.Settings->tx.stream_enable) {
|
// if (!audio_i2s.Settings->tx.stream_enable) {
|
||||||
bwritten = mp3_out.write(ucp, written);
|
// bwritten = mp3_out.write(ucp, written);
|
||||||
if (bwritten != written) {
|
// if (bwritten != written) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
audio_i2s_mp3.client.write((const char*)ucp, written);
|
// audio_i2s_mp3.client.write((const char*)ucp, written);
|
||||||
|
|
||||||
if (!audio_i2s_mp3.client.connected()) {
|
// if (!audio_i2s_mp3.client.connected()) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
audio_i2s_mp3.recdur = TasmotaGlobal.uptime - ctime;
|
// audio_i2s_mp3.recdur = TasmotaGlobal.uptime - ctime;
|
||||||
}
|
// }
|
||||||
|
|
||||||
ucp = shine_flush(s, &written);
|
// ucp = shine_flush(s, &written);
|
||||||
|
|
||||||
if (!audio_i2s_mp3.use_stream) {
|
// if (!audio_i2s_mp3.use_stream) {
|
||||||
mp3_out.write(ucp, written);
|
// mp3_out.write(ucp, written);
|
||||||
} else {
|
// } else {
|
||||||
audio_i2s_mp3.client.write((const char*)ucp, written);
|
// audio_i2s_mp3.client.write((const char*)ucp, written);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
exit:
|
// exit:
|
||||||
if (s) {
|
// if (s) {
|
||||||
shine_close(s);
|
// shine_close(s);
|
||||||
}
|
// }
|
||||||
if (mp3_out) {
|
// if (mp3_out) {
|
||||||
mp3_out.close();
|
// mp3_out.close();
|
||||||
}
|
// }
|
||||||
if (buffer) {
|
// if (buffer) {
|
||||||
free(buffer);
|
// free(buffer);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (audio_i2s_mp3.use_stream) {
|
// if (audio_i2s_mp3.use_stream) {
|
||||||
audio_i2s_mp3.client.stop();
|
// audio_i2s_mp3.client.stop();
|
||||||
}
|
// }
|
||||||
|
|
||||||
SpeakerMic(I2S_AUDIO_MODE_SPK);
|
// SpeakerMic(I2S_AUDIO_MODE_SPK);
|
||||||
audio_i2s_mp3.mic_stop = 0;
|
// audio_i2s_mp3.mic_stop = 0;
|
||||||
audio_i2s_mp3.mic_error = error;
|
// audio_i2s_mp3.mic_error = error;
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("mp3task result code: %d"), error);
|
// AddLog(LOG_LEVEL_INFO, PSTR("mp3task result code: %d"), error);
|
||||||
audio_i2s_mp3.mic_task_handle = 0;
|
// audio_i2s_mp3.mic_task_handle = 0;
|
||||||
audio_i2s_mp3.recdur = 0;
|
// audio_i2s_mp3.recdur = 0;
|
||||||
audio_i2s_mp3.stream_active = 0;
|
// audio_i2s_mp3.stream_active = 0;
|
||||||
vTaskDelete(NULL);
|
// vTaskDelete(NULL);
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
int32_t i2s_record_shine(char *path) {
|
// int32_t i2s_record_shine(char *path) {
|
||||||
esp_err_t err = ESP_OK;
|
// esp_err_t err = ESP_OK;
|
||||||
|
|
||||||
if (audio_i2s.in) {
|
// if (audio_i2s.in) {
|
||||||
if (audio_i2s_mp3.decoder || audio_i2s_mp3.mp3) return 0;
|
// if (audio_i2s_mp3.decoder || audio_i2s_mp3.mp3) return 0;
|
||||||
}
|
// }
|
||||||
|
|
||||||
err = SpeakerMic(I2S_AUDIO_MODE_MIC);
|
// err = SpeakerMic(I2S_AUDIO_MODE_MIC);
|
||||||
if (err) {
|
// if (err) {
|
||||||
if (audio_i2s.in) {
|
// if (audio_i2s.in) {
|
||||||
SpeakerMic(I2S_AUDIO_MODE_SPK);
|
// SpeakerMic(I2S_AUDIO_MODE_SPK);
|
||||||
}
|
// }
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("mic init error: %d"), err);
|
// AddLog(LOG_LEVEL_INFO, PSTR("mic init error: %d"), err);
|
||||||
return err;
|
// return err;
|
||||||
}
|
// }
|
||||||
|
|
||||||
strlcpy(audio_i2s_mp3.mic_path, path, sizeof(audio_i2s_mp3.mic_path));
|
// strlcpy(audio_i2s_mp3.mic_path, path, sizeof(audio_i2s_mp3.mic_path));
|
||||||
|
|
||||||
audio_i2s_mp3.mic_stop = 0;
|
// audio_i2s_mp3.mic_stop = 0;
|
||||||
|
|
||||||
uint32_t stack = 4096;
|
// uint32_t stack = 4096;
|
||||||
|
|
||||||
audio_i2s_mp3.use_stream = !strcmp(audio_i2s_mp3.mic_path, "stream.mp3");
|
// audio_i2s_mp3.use_stream = !strcmp(audio_i2s_mp3.mic_path, "stream.mp3");
|
||||||
|
|
||||||
if (audio_i2s_mp3.use_stream) {
|
// if (audio_i2s_mp3.use_stream) {
|
||||||
stack = 8000;
|
// stack = 8000;
|
||||||
}
|
// }
|
||||||
|
|
||||||
err = xTaskCreatePinnedToCore(mic_task, "MIC", stack, NULL, 3, &audio_i2s_mp3.mic_task_handle, 1);
|
// err = xTaskCreatePinnedToCore(mic_task, "MIC", stack, NULL, 3, &audio_i2s_mp3.mic_task_handle, 1);
|
||||||
|
|
||||||
return err;
|
// return err;
|
||||||
}
|
// }
|
||||||
|
|
||||||
void Cmd_MicRec(void) {
|
// void Cmd_MicRec(void) {
|
||||||
|
|
||||||
if (XdrvMailbox.data_len > 0) {
|
// if (XdrvMailbox.data_len > 0) {
|
||||||
if (!strncmp(XdrvMailbox.data, "-?", 2)) {
|
// if (!strncmp(XdrvMailbox.data, "-?", 2)) {
|
||||||
Response_P("{\"I2SREC-duration\":%d}", audio_i2s_mp3.recdur);
|
// Response_P("{\"I2SREC-duration\":%d}", audio_i2s_mp3.recdur);
|
||||||
} else {
|
// } else {
|
||||||
i2s_record_shine(XdrvMailbox.data);
|
// i2s_record_shine(XdrvMailbox.data);
|
||||||
ResponseCmndChar(XdrvMailbox.data);
|
// ResponseCmndChar(XdrvMailbox.data);
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
if (audio_i2s_mp3.mic_task_handle) {
|
// if (audio_i2s_mp3.mic_task_handle) {
|
||||||
// stop task
|
// // stop task
|
||||||
audio_i2s_mp3.mic_stop = 1;
|
// audio_i2s_mp3.mic_stop = 1;
|
||||||
while (audio_i2s_mp3.mic_stop) {
|
// while (audio_i2s_mp3.mic_stop) {
|
||||||
delay(1);
|
// delay(1);
|
||||||
}
|
// }
|
||||||
ResponseCmndChar_P(PSTR("Stopped"));
|
// ResponseCmndChar_P(PSTR("Stopped"));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
// }
|
||||||
#endif // USE_SHINE
|
// #endif // USE_SHINE
|
||||||
|
|
||||||
|
|
||||||
// mic gain in factor not percent
|
// // mic gain in factor not percent
|
||||||
void Cmd_MicGain(void) {
|
// void Cmd_MicGain(void) {
|
||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 256)) {
|
// if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 256)) {
|
||||||
if (audio_i2s.in) {
|
// if (audio_i2s.in) {
|
||||||
audio_i2s.in->setRxGain(XdrvMailbox.payload);
|
// audio_i2s.in->setRxGain(XdrvMailbox.payload);
|
||||||
}
|
// }
|
||||||
if (audio_i2s.Settings) {
|
// if (audio_i2s.Settings) {
|
||||||
audio_i2s.Settings->rx.gain = XdrvMailbox.payload * 16;
|
// audio_i2s.Settings->rx.gain = XdrvMailbox.payload * 16;
|
||||||
}
|
// }
|
||||||
I2SSettingsSave(AUDIO_CONFIG_FILENAME);
|
// I2SSettingsSave(AUDIO_CONFIG_FILENAME);
|
||||||
}
|
// }
|
||||||
ResponseCmndNumber(audio_i2s.Settings->rx.gain / 16);
|
// ResponseCmndNumber(audio_i2s.Settings->rx.gain / 16);
|
||||||
}
|
// }
|
||||||
|
|
||||||
#endif // USE_I2S_AUDIO
|
#endif // USE_I2S_AUDIO
|
||||||
#endif // defined(ESP32) && ESP_IDF_VERSION_MAJOR >= 5
|
#endif // defined(ESP32) && ESP_IDF_VERSION_MAJOR >= 5
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
void Stream_mp3(void) {
|
void Stream_mp3(void) {
|
||||||
if (audio_i2s_mp3.stream_active) {
|
if (audio_i2s_mp3.stream_active) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("I2S: can not handle client - other MP3 task active"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("I2S: Handle mp3server"));
|
AddLog(LOG_LEVEL_INFO, PSTR("I2S: Handle mp3server"));
|
||||||
|
@ -58,6 +59,7 @@ void I2sMp3Init(uint32_t on) {
|
||||||
delete audio_i2s_mp3.MP3Server;
|
delete audio_i2s_mp3.MP3Server;
|
||||||
audio_i2s_mp3.MP3Server = nullptr;
|
audio_i2s_mp3.MP3Server = nullptr;
|
||||||
audio_i2s_mp3.mic_stop = 1;
|
audio_i2s_mp3.mic_stop = 1;
|
||||||
|
audio_i2s_mp3.stream_active = 0;
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("MP3: server deleted"));
|
AddLog(LOG_LEVEL_INFO, PSTR("MP3: server deleted"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,11 @@ void CmndI2SWebRadio(void) {
|
||||||
|
|
||||||
|
|
||||||
void I2sWebRadioStopPlaying() {
|
void I2sWebRadioStopPlaying() {
|
||||||
|
if(audio_i2s_mp3.decoder) {
|
||||||
|
audio_i2s_mp3.decoder->stop();
|
||||||
|
delete audio_i2s_mp3.decoder;
|
||||||
|
audio_i2s_mp3.decoder = nullptr;
|
||||||
|
}
|
||||||
if (Audio_webradio.buff) {
|
if (Audio_webradio.buff) {
|
||||||
Audio_webradio.buff->close();
|
Audio_webradio.buff->close();
|
||||||
delete Audio_webradio.buff;
|
delete Audio_webradio.buff;
|
||||||
|
|
Loading…
Reference in New Issue