From 1c5b1c0ee0ac260cab3c90d5c5e1ad77730e1498 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 2 Aug 2021 11:34:24 +0200 Subject: [PATCH] Fix ESP32 regression of I2s_write_bytes (#12812) --- .../ESP8266Audio/src/AudioOutputI2S.cpp | 8 +- .../ESP8266Audio/src/AudioOutputI2SNoDAC.cpp | 10 ++- lib/lib_audio/ESP8266AudioAttention.md | 82 +++++++++++++++++++ 3 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 lib/lib_audio/ESP8266AudioAttention.md diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp index cd915f58b..84672bb62 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp @@ -1,7 +1,7 @@ /* AudioOutputI2S Base class for I2S interface port - + Copyright (C) 2017 Earle F. Philhower, III This program is free software: you can redistribute it and/or modify @@ -269,7 +269,11 @@ bool AudioOutputI2S::ConsumeSample(int16_t sample[2]) { s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff); } - return i2s_write_bytes((i2s_port_t)portNo, (const char *)&s32, sizeof(uint32_t), 0); +// Deprecated. Use i2s_write +// return i2s_write_bytes((i2s_port_t)portNo, (const char *)&s32, sizeof(uint32_t), 0); + size_t bytes_written; + i2s_write((i2s_port_t)portNo, (const char*)&s32, sizeof(uint32_t), &bytes_written, 0); + return bytes_written; #elif defined(ESP8266) uint32_t s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff); return i2s_write_sample_nb(s32); // If we can't store it, return false. OTW true diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp index 774602fd9..65c639e01 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp @@ -1,7 +1,7 @@ /* AudioOutputI2SNoDAC Audio player using SW delta-sigma to generate "analog" on I2S data - + Copyright (C) 2017 Earle F. Philhower, III This program is free software: you can redistribute it and/or modify @@ -66,7 +66,7 @@ void AudioOutputI2SNoDAC::DeltaSigma(int16_t sample[2], uint32_t dsBuff[8]) for (int j = 0; j < oversample32; j++) { uint32_t bits = 0; // The bits we convert the sample into, MSB to go on the wire first - + for (int i = 32; i > 0; i--) { bits = bits << 1; if (cumErr < 0) { @@ -95,7 +95,11 @@ bool AudioOutputI2SNoDAC::ConsumeSample(int16_t sample[2]) // Either send complete pulse stream or nothing #ifdef ESP32 - if (!i2s_write_bytes((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), 0)) +// Deprecated. Use i2s_write +// if (!i2s_write_bytes((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), 0)) + size_t bytes_written; + i2s_write((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), &bytes_written, 0); + if (!bytes_written) return false; #elif defined(ESP8266) if (!i2s_write_sample_nb(dsBuff[0])) return false; // No room at the inn diff --git a/lib/lib_audio/ESP8266AudioAttention.md b/lib/lib_audio/ESP8266AudioAttention.md new file mode 100644 index 000000000..7077d8211 --- /dev/null +++ b/lib/lib_audio/ESP8266AudioAttention.md @@ -0,0 +1,82 @@ +The current library needs two fixes solving the deprecated ``i2s_write_bytes`` function. + +In file AudioOutputI2S.cpp: + +bool AudioOutputI2S::ConsumeSample(int16_t sample[2]) +{ + + //return if we haven't called ::begin yet + if (!i2sOn) + return false; + + int16_t ms[2]; + + ms[0] = sample[0]; + ms[1] = sample[1]; + MakeSampleStereo16( ms ); + + if (this->mono) { + // Average the two samples and overwrite + int32_t ttl = ms[LEFTCHANNEL] + ms[RIGHTCHANNEL]; + ms[LEFTCHANNEL] = ms[RIGHTCHANNEL] = (ttl>>1) & 0xffff; + } + #ifdef ESP32 + uint32_t s32; + if (output_mode == INTERNAL_DAC) + { + int16_t l = Amplify(ms[LEFTCHANNEL]) + 0x8000; + int16_t r = Amplify(ms[RIGHTCHANNEL]) + 0x8000; + s32 = (r << 16) | (l & 0xffff); + } + else + { + s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff); + } +// Deprecated. Use i2s_write +// return i2s_write_bytes((i2s_port_t)portNo, (const char *)&s32, sizeof(uint32_t), 0); + size_t bytes_written; + i2s_write((i2s_port_t)portNo, (const char*)&s32, sizeof(uint32_t), &bytes_written, 0); + return bytes_written; + #elif defined(ESP8266) + uint32_t s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff); + return i2s_write_sample_nb(s32); // If we can't store it, return false. OTW true + #elif defined(ARDUINO_ARCH_RP2040) + return !!I2S.write((void*)ms, 4); + #endif +} + +In file AudioOutputI2SNoDac.cpp: + +bool AudioOutputI2SNoDAC::ConsumeSample(int16_t sample[2]) +{ + int16_t ms[2]; + ms[0] = sample[0]; + ms[1] = sample[1]; + MakeSampleStereo16( ms ); + + // Make delta-sigma filled buffer + uint32_t dsBuff[8]; + DeltaSigma(ms, dsBuff); + + // Either send complete pulse stream or nothing +#ifdef ESP32 +// Deprecated. Use i2s_write +// if (!i2s_write_bytes((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), 0)) + size_t bytes_written; + i2s_write((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), &bytes_written, 0); + if (!bytes_written) + return false; +#elif defined(ESP8266) + if (!i2s_write_sample_nb(dsBuff[0])) return false; // No room at the inn + // At this point we've sent in first of possibly 8 32-bits, need to send + // remaining ones even if they block. + for (int i = 32; i < oversample; i+=32) + i2s_write_sample( dsBuff[i / 32]); +#elif defined(ARDUINO_ARCH_RP2040) + int16_t *p = (int16_t *) dsBuff; + for (int i = 0; i < oversample / 16; i++) { + I2S.write(*(p++)); + } +#endif + return true; +}