I2SStream and AnalogStream on the same I2S port? #1137
-
Hello, What is my case?On ESP32 I need to catch audio from my I2S mic (INMP441) and then stream it using e.x. AudioWavServer. Meanwhile at the same time I need to catch audio from URLStream and output it to analog amplifier (LM386). The most important (and I think challenging) thing here is that I can use only one I2S port. What is the issue?When using two Streams separately with two different I2S ports, everything works fine, but when using one I2SStream in RXTX_MODE, I get huge noise on output with barely hearable correct audio. My findingsWhile doing my research I found information that I2S is duplex so if I understand correctly it should separate input and output audio and provide correct one for each. I also noticed that RXTX mode is not supported in AnalogStream. I tried to combine these two classes - taking I2SStream pieces for config and reading, and AnalogStream write for output, but it didn't work as expected. My questionSo here I started to wonder if it's even possible to combine these two streams? So have I2S on input and analog on output. Or should I rather replace analog amplifier with some I2S output module, but will it work as I need it to then? I feel I'm missing something here... Maybe someone had similar case or issue and could provide some clues what can be done here? I would appreciate any help or advice. My codeHere's my code pieces which I tried while looking for a right way... Mic only - working AudioWAVServer server(ssid, password, 4713);
I2SStream i2sStream;
ConverterFillLeftAndRight<int16_t> filler(RightIsEmpty);
void init_audio_in() {
auto config = i2sStream.defaultConfig(RX_MODE);
config.is_master = true;
config.i2s_format = I2S_STD_FORMAT;
config.sample_rate = 44100;
config.channels = 2;
config.bits_per_sample = 16;
config.pin_ws = 15;
config.pin_bck = 14;
config.port_no = 1;
config.pin_data = 32;
i2sStream.begin(config);
server.begin(i2sStream, config, &filler);
} Audio output only - working URLStream url(ssid, password);
AnalogAudioStream out; // final output of decoded stream
EncodedAudioStream dec(&out, new MP3DecoderHelix()); // Decoding stream
StreamCopy copier(dec, url); // copy url to decoder
void setup(){
auto config = out.defaultConfig(TX_MODE);
out.begin(config);
dec.setNotifyAudioChange(out);
dec.begin();
url.begin("http://stream.srg-ssr.ch/m/rsj/mp3_128","audio/mp3");
}
void loop(){
copier.copy();
} Input to Output - I used i2s-i2s example here. Not working (huge noise on output with barely hearable correct audio) AudioInfo info(44100, 2, 16);
I2SStream i2s;
StreamCopy copier(i2s, i2s); // copies sound into i2s
ConverterFillLeftAndRight<int16_t> filler(RightIsEmpty);
void setup(void) {
auto config = i2s.defaultConfig(RXTX_MODE);
config.copyFrom(info);
config.is_master = true;
config.i2s_format = I2S_STD_FORMAT;
config.sample_rate = 44100;
config.channels = 2;
config.bits_per_sample = 16;
config.pin_ws = 15;
config.pin_bck = 14;
config.port_no = 1;
config.pin_data = 25;
config.pin_data_rx = 32;
i2s.begin(config);
}
void loop() {
copier.copy(filler);
} My custom class which I tried to use to have analog output. Didn't work as I suppose there could be some issue with DAC configuration class I2SInputAnalogOutputStream : public I2SStream
{
public:
I2SInputAnalogOutputStream() = default;
size_t write(const uint8_t *src, size_t size_bytes) override
{
size_t result = 0;
I2SConfig cfg = i2s.config();
i2s_port_t port_no;
switch (cfg.port_no)
{
case 0:
port_no = I2S_NUM_0;
break;
case 1:
port_no = I2S_NUM_1;
break;
default:
port_no = I2S_NUM_MAX;
break;
}
if (size_bytes > 0 && src != nullptr)
{
TRACED();
size_t output_size = 0;
size_t result;
uint16_t *dst = (uint16_t *)src;
// Only case for 24 bit left
int24_t *data = (int24_t *)src;
output_size = (size_bytes / 3) * 2;
for (int j = 0; j < size_bytes / 3; j++)
{
dst[j] = (uint32_t)convert8DAC(data[j], 24);
}
if (output_size > 0)
{
if (i2s_write(port_no, src, output_size, &result, portMAX_DELAY) != ESP_OK)
{
LOGE("%s: %d", LOG_METHOD, output_size);
}
}
LOGD("i2s_write %d -> %d bytes", size_bytes, result);
return result;
}
return size_bytes;
}
}; |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
There are 2 ports (0 and 1) and you can use only one port at a time (to do i2s or analog input or output via the i2s api)! So this means:
For the INMP441 I have the gut feeling that you just ignored my information in the documentation |
Beta Was this translation helpful? Give feedback.
There are 2 ports (0 and 1) and you can use only one port at a time (to do i2s or analog input or output via the i2s api)!
In addition all analog operations (input or output) need to be on port 0.
So this means:
For the INMP441 I have the gut feeling that you just ignored my information in the documentation