Skip to content

Commit

Permalink
Merge pull request #943 from schreibfaul1/V3.1
Browse files Browse the repository at this point in the history
V3.1
  • Loading branch information
schreibfaul1 authored Jan 7, 2025
2 parents 979823b + 9638f01 commit a50897c
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 184 deletions.
52 changes: 49 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,52 @@ void audio_eof_speech(const char *info){

````
````c++
/* ESP32-S3 EXAMPLE */
#include "Arduino.h"
#include "Audio.h"
#include "WiFi.h"
#include "SD_MMC.h"
#define I2S_DOUT 9
#define I2S_BCLK 3
#define I2S_LRC 1
#define SD_MMC_D0 11
#define SD_MMC_CLK 13
#define SD_MMC_CMD 14
Audio audio;
String ssid = "*****";
String password = "*****";
void setup() {
Serial.begin(115200);
// WiFi.begin(ssid.c_str(), password.c_str());
// while (WiFi.status() != WL_CONNECTED) delay(1500);
pinMode(SD_MMC_D0, INPUT_PULLUP);
SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
SD_MMC.begin("/sdcard", true);
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(12); // default 0...21
// audio.connecttohost("http://stream.antennethueringen.de/live/aac-64/stream.antennethueringen.de/"); // aac
audio.connecttoFS(SD_MMC, "/test.wav");
}
void loop() {
audio.loop();
vTaskDelay(1);
}
// optional
void audio_info(const char *info){
Serial.print("info "); Serial.println(info);
}
````

<br>

|Codec |ESP32 |ESP32 PSRAM |ESP32-S3 PSRAM | |
Expand All @@ -125,10 +171,10 @@ void audio_eof_speech(const char *info){

<br>

Breadboard
![Breadboard](https://github.com/schreibfaul1/ESP32-audioI2S/blob/master/additional_info/Breadboard.jpg)
***
Wiring
![Wiring](https://github.com/schreibfaul1/ESP32-audioI2S/blob/master/additional_info/ESP32_I2S_PCM5102A.JPG)
![Wiring ESP32-S3](https://github.com/user-attachments/assets/15dd1766-0fc1-4079-b378-bc566583e80d)
***
Impulse diagram
![Impulse diagram](https://github.com/schreibfaul1/ESP32-audioI2S/blob/master/additional_info/Impulsdiagramm.jpg)
***
Expand Down
44 changes: 0 additions & 44 deletions examples/Internal DAC/internalDAC.ino

This file was deleted.

138 changes: 7 additions & 131 deletions src/Audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
*
* Created on: Oct 28.2018
*
* Version 3.0.13zi
* Updated on: Jan 06.2025
* Version 3.1.0
* Updated on: Jan 07.2025
* Author: Wolle (schreibfaul1)
*
*/
Expand Down Expand Up @@ -158,7 +158,7 @@ uint32_t AudioBuffer::getWritePos() { return m_writePtr - m_buffer; }
uint32_t AudioBuffer::getReadPos() { return m_readPtr - m_buffer; }
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// clang-format off
Audio::Audio(bool internalDAC /* = false */, uint8_t channelEnabled /* = I2S_SLOT_MODE_STEREO */, uint8_t i2sPort) {
Audio::Audio(uint8_t i2sPort) {

mutex_playAudioData = xSemaphoreCreateMutex();
mutex_audioTask = xSemaphoreCreateMutex();
Expand All @@ -177,12 +177,9 @@ Audio::Audio(bool internalDAC /* = false */, uint8_t channelEnabled /* = I2S_SLO
#define AUDIO_INFO(...) { snprintf(m_ibuff, m_ibuffSize, __VA_ARGS__); if(audio_info) audio_info(m_ibuff); }

clientsecure.setInsecure();
m_f_channelEnabled = channelEnabled;
m_f_internalDAC = internalDAC;
m_i2s_num = i2sPort; // i2s port number

// -------- I2S configuration -------------------------------------------------------------------------------------------
#if ESP_IDF_VERSION_MAJOR == 5
m_i2s_chan_cfg.id = (i2s_port_t)m_i2s_num; // I2S_NUM_AUTO, I2S_NUM_0, I2S_NUM_1
m_i2s_chan_cfg.role = I2S_ROLE_MASTER; // I2S controller master role, bclk and lrc signal will be set to output
m_i2s_chan_cfg.dma_desc_num = 32; // number of DMA buffer
Expand All @@ -206,45 +203,6 @@ Audio::Audio(bool internalDAC /* = false */, uint8_t channelEnabled /* = I2S_SLO
I2Sstart(m_i2s_num);
m_sampleRate = 44100;

if (internalDAC) {
#ifdef CONFIG_IDF_TARGET_ESP32 // ESP32S3 has no DAC
printf("internal DAC is not supported");
// no support in V5 ???
#endif
}
#else
m_i2s_config.sample_rate = 44100;
m_i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
m_i2s_config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT;
m_i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1; // interrupt priority
m_i2s_config.dma_buf_count = 16;
m_i2s_config.dma_buf_len = 512;
m_i2s_config.use_apll = APLL_DISABLE;
m_i2s_config.tx_desc_auto_clear = true;
m_i2s_config.fixed_mclk = true;
m_i2s_config.mclk_multiple = I2S_MCLK_MULTIPLE_128;

if (internalDAC) {
#ifdef CONFIG_IDF_TARGET_ESP32 // ESP32S3 has no DAC
printf("internal DAC");
m_i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN );
m_i2s_config.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_MSB); // vers >= 2.0.5
i2s_driver_install((i2s_port_t)m_i2s_num, &m_i2s_config, 0, NULL);
i2s_set_dac_mode((i2s_dac_mode_t)m_f_channelEnabled);
if(m_f_channelEnabled != I2S_DAC_CHANNEL_BOTH_EN) {
m_f_forceMono = true;
}
#endif
}
else {
m_i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX);
m_i2s_config.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S); // Arduino vers. > 2.0.0
i2s_driver_install((i2s_port_t)m_i2s_num, &m_i2s_config, 0, NULL);
m_f_forceMono = false;
}
i2s_zero_dma_buffer((i2s_port_t) m_i2s_num);

#endif // ESP_IDF_VERSION_MAJOR == 5
for(int i = 0; i < 3; i++) {
m_filter[i].a0 = 1;
m_filter[i].a1 = 0;
Expand All @@ -261,12 +219,8 @@ Audio::~Audio() {
// InBuff.~AudioBuffer(); #215 the AudioBuffer is automatically destroyed by the destructor
setDefaults();

#if ESP_IDF_VERSION_MAJOR == 5
i2s_channel_disable(m_i2s_tx_handle);
i2s_del_channel(m_i2s_tx_handle);
#else
i2s_driver_uninstall((i2s_port_t)m_i2s_num); // #215 free I2S buffer
#endif

x_ps_free(&m_playlistBuff);
x_ps_free(&m_chbuf);
Expand Down Expand Up @@ -300,21 +254,11 @@ void Audio::initInBuff() {

//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
esp_err_t Audio::I2Sstart(uint8_t i2s_num) {
#if ESP_IDF_VERSION_MAJOR == 5
return i2s_channel_enable(m_i2s_tx_handle);
#else
// It is not necessary to call this function after i2s_driver_install() (it is started automatically),
// however it is necessary to call it after i2s_stop()
return i2s_start((i2s_port_t)i2s_num);
#endif
}

esp_err_t Audio::I2Sstop(uint8_t i2s_num) {
#if ESP_IDF_VERSION_MAJOR == 5
return i2s_channel_disable(m_i2s_tx_handle);
#else
return i2s_stop((i2s_port_t)i2s_num);
#endif
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void Audio::setDefaults() {
Expand Down Expand Up @@ -2343,12 +2287,6 @@ void Audio::playChunk() {
(*sample)[LEFTCHANNEL] = (int16_t)xy;
}
Gain(*sample);

if(m_f_internalDAC) {
s2 = *sample;
s2[LEFTCHANNEL] += 0x8000;
s2[RIGHTCHANNEL] += 0x8000;
}
i += 2;
validSamples -= 1;
}
Expand All @@ -2367,13 +2305,7 @@ void Audio::playChunk() {

validSamples = m_validSamples;


#if(ESP_IDF_VERSION_MAJOR == 5)
err = i2s_channel_write(m_i2s_tx_handle, (int16_t*)m_outBuff + count, validSamples * sampleSize, &i2s_bytesConsumed, 10);
#else
err = i2s_write((i2s_port_t)m_i2s_num, (int16_t*)m_outBuff + count, validSamples * sampleSize, &i2s_bytesConsumed, 10);
#endif

if( ! (err == ESP_OK || err == ESP_ERR_TIMEOUT)) goto exit;
m_validSamples -= i2s_bytesConsumed / sampleSize;
count += i2s_bytesConsumed / 2;
Expand Down Expand Up @@ -4774,21 +4706,10 @@ bool Audio::setPinout(uint8_t BCLK, uint8_t LRC, uint8_t DOUT, int8_t MCLK) {
}
esp_err_t result = ESP_OK;

if(m_f_internalDAC) {
#if(ESP_IDF_VERSION_MAJOR != 5)
i2s_set_pin((i2s_port_t)m_i2s_num, NULL);
#endif
return true;
}

#if(ESP_ARDUINO_VERSION_MAJOR < 2)
log_e("Arduino Version too old!");
#endif
#if(ESP_ARDUINO_VERSION_MAJOR == 2 && ESP_ARDUINO_VERSION_PATCH < 8)
log_e("Arduino Version must be 2.0.8 or higher!");
#if(ESP_ARDUINO_VERSION_MAJOR < 3)
log_e("Arduino Version must be 3.0.0 or higher!");
#endif

#if(ESP_IDF_VERSION_MAJOR == 5)
i2s_std_gpio_config_t gpio_cfg = {};
gpio_cfg.bclk = (gpio_num_t)BCLK;
gpio_cfg.din = (gpio_num_t)I2S_GPIO_UNUSED;
Expand All @@ -4798,14 +4719,7 @@ bool Audio::setPinout(uint8_t BCLK, uint8_t LRC, uint8_t DOUT, int8_t MCLK) {
I2Sstop(m_i2s_num);
result = i2s_channel_reconfig_std_gpio(m_i2s_tx_handle, &gpio_cfg);
I2Sstart(m_i2s_num);
#else
m_pin_config.bck_io_num = BCLK;
m_pin_config.ws_io_num = LRC; // wclk = lrc
m_pin_config.data_out_num = DOUT;
m_pin_config.data_in_num = I2S_GPIO_UNUSED;
m_pin_config.mck_io_num = MCLK;
result = i2s_set_pin((i2s_port_t)m_i2s_num, &m_pin_config);
#endif

return (result == ESP_OK);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -4912,24 +4826,6 @@ bool Audio::setFilePos(uint32_t pos) {
return false;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
bool Audio::audioFileSeek(const float speed) {
// 0.5 is half speed
// 1.0 is normal speed
// 1.5 is one and half speed
// if((speed > 1.5f) || (speed < 0.25f)) return false;

// uint32_t srate = getSampleRate() * speed;
// #if ESP_IDF_VERSION_MAJOR == 5
// I2Sstop(m_i2s_num);
// m_i2s_std_cfg.clk_cfg.sample_rate_hz = srate;
// i2s_channel_reconfig_std_clock(m_i2s_tx_handle, &m_i2s_std_cfg.clk_cfg);
// I2Sstart(m_i2s_num);
// #else
// i2s_set_sample_rates((i2s_port_t)m_i2s_num, srate);
// #endif
return true;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
bool Audio::setSampleRate(uint32_t sampRate) {
if(!sampRate) sampRate = 44100; // fuse, if there is no value -> set default #209
m_sampleRate = sampRate;
Expand Down Expand Up @@ -4958,7 +4854,6 @@ uint8_t Audio::getChannels() {
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void Audio::reconfigI2S(){

#if ESP_IDF_VERSION_MAJOR == 5
I2Sstop(0);

if(getBitsPerSample() == 8 && getChannels() == 2) m_i2s_std_cfg.clk_cfg.sample_rate_hz = getSampleRate() * 2;
Expand All @@ -4973,10 +4868,7 @@ void Audio::reconfigI2S(){
i2s_channel_reconfig_std_slot(m_i2s_tx_handle, &m_i2s_std_cfg.slot_cfg);

I2Sstart(m_i2s_num);
#else
m_i2s_config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT;
i2s_set_clk((i2s_port_t)m_i2s_num, m_sampleRate, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO);
#endif

memset(m_filterBuff, 0, sizeof(m_filterBuff)); // Clear FilterBuffer
IIR_calculateCoefficients(m_gain0, m_gain1, m_gain2); // must be recalculated after each samplerate change
return;
Expand All @@ -4999,18 +4891,6 @@ void Audio::setI2SCommFMT_LSB(bool commFMT) {

m_f_commFMT = commFMT;

#if ESP_IDF_VERSION_MAJOR < 5
if(commFMT) {
AUDIO_INFO("commFMT = LSBJ (Least Significant Bit Justified)");
m_i2s_config.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_MSB);
}
else {
AUDIO_INFO("commFMT = Philips");
m_i2s_config.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S);
}
i2s_driver_uninstall((i2s_port_t)m_i2s_num);
i2s_driver_install((i2s_port_t)m_i2s_num, &m_i2s_config, 0, NULL);
#else
i2s_channel_disable(m_i2s_tx_handle);
if(commFMT) {
AUDIO_INFO("commFMT = LSBJ (Least Significant Bit Justified)");
Expand All @@ -5022,7 +4902,6 @@ void Audio::setI2SCommFMT_LSB(bool commFMT) {
}
i2s_channel_reconfig_std_slot(m_i2s_tx_handle, &m_i2s_std_cfg.slot_cfg);
i2s_channel_enable(m_i2s_tx_handle);
#endif
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void Audio::computeVUlevel(int16_t sample[2]) {
Expand Down Expand Up @@ -5134,9 +5013,6 @@ void Audio::setBalance(int8_t bal) { // bal -16...16
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void Audio::setVolume(uint8_t vol, uint8_t curve) { // curve 0: default, curve 1: flat at the beginning

uint16_t v = ESP_ARDUINO_VERSION_MAJOR * 100 + ESP_ARDUINO_VERSION_MINOR * 10 + ESP_ARDUINO_VERSION_PATCH;
if(v < 207) AUDIO_INFO("Do not use this ancient Adruino version V%d.%d.%d", ESP_ARDUINO_VERSION_MAJOR, ESP_ARDUINO_VERSION_MINOR, ESP_ARDUINO_VERSION_PATCH);

if(vol > m_vol_steps) m_vol = m_vol_steps;
else m_vol = vol;

Expand Down
Loading

0 comments on commit a50897c

Please sign in to comment.