Replies: 13 comments 6 replies
-
The value of the output signal with 16bit/sample can be between INT16_MIN and INT16_MAX (-32768, 32767) at I2S for each channel. The lower or upper limit at the maximum level from the signal source must not be exceeded, as this would lead to distortion. Surely there is a margin that you can exploit, as in your example. Nevertheless, I am of the opinion that the level attenuation comes from the HW used. |
Beta Was this translation helpful? Give feedback.
-
I am using digital input chips. I do not change anything and I really can't change anything in I2S stream, it moves directly from I2S ESP32 output pins to MAX98357 (you could see a schematic). And I have no any distortion when playing full amplitude test 1 KHZ sine file with twice values in volumetable[]. It is notes that something wrong, I suppouse. Or, we deal with some strange feature of MAX98357 chip. |
Beta Was this translation helpful? Give feedback.
-
Dear schreibfaul1 sir I AM USING A2DP SINK AND SOURCE LIBRARY. |
Beta Was this translation helpful? Give feedback.
-
This is a difficult thing. The microphone used has a processing width of 24 bits, I2S must be set to 32 bits (because 24 does not exist), and the actual BT transmission uses 16 bits per channel. The simplest method is to cut out the lower 8 bits.
|
Beta Was this translation helpful? Give feedback.
-
Thank you for your reply
But Dear its sound goes very low
Any middle solution using a filter
Where and how shall I add a filer after samples.
Also any where I can reduce LAtency in A2dp Tx?
…On Sun, Aug 27, 2023 at 10:19 PM Wolle ***@***.***> wrote:
This is a difficult thing. The microphone used has a processing width of
24 bits, I2S must be set to 32 bits (because 24 does not exist), and the
actual BT transmission uses 16 bits per channel. The simplest method is to
cut out the lower 8 bits.
//int32_t sample = (buf_ptr_read1[3] << 24) + (buf_ptr_read1[2] << 16) + (buf_ptr_read1[1] << 8);
//sample = sample >> gain;
int16_t sample = (buf_ptr_read1[3] << 8) + (buf_ptr_read1[2] );
—
Reply to this email directly, view it on GitHub
<#475 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACV6JJDPZ7E72UUSD76YMS3XXN3BPANCNFSM6AAAAAAUOHZ7Y4>
.
You are receiving this because you commented.Message ID:
***@***.***
com>
--
SIMPLY GAURAV
|
Beta Was this translation helpful? Give feedback.
-
Dear Sir , how can I use the Pink colour text having high gain and reducing
noise. Please
/*
This example code is in the Public Domain (or CC0 licensed, at your
option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
Arduino port of
https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/a2dp_source
origin URL: https://github.com/dgm3333/Arduino_A2DP_Source
After connection with A2DP sink is established, the example performs the
following running loop 1-2-3-4-1:
1. audio transmission starts and lasts for a while
2. audio transmission stops
3. disconnect with target device
4. reconnect to target device
The example implements an event loop triggered by a periodic "heart beat"
timer and events from Bluetooth protocol stack callback functions.
For current stage, the supported audio codec in ESP32 A2DP is SBC
(SubBand Coding).
SBC specification is in Appendix B (page 50) of the document
A2DP_Spec_V1_0 (can be found with search engine, although the original is
behind the Bluetooth firewall)
SBC audio stream is encoded from PCM data normally formatted as 44.1kHz
sampling rate, two-channel 16-bit sample data.
Other SBC configurations can be supported but there is a need for
additional modifications to the protocol stack.
*/
#include "sos-iir-filter.h"
#include "Arduino.h"
#include "a2dp_source.h"
#include <driver/i2s.h>
//* SCK 5 = bit clock line (BCLK)
//* FS 25 = WS PIN
//* DIN 35 MIC
#define RX_I2S_DIN 35 // connect with I2S microphone pin SO
(signal out)
#define RX_I2S_BCLK 5 // connect with I2S microphone pin SCK (bit
clock)
#define RX_I2S_LRC 33 // connect with I2S microphone pin WS (word
select)
//#define RX_I2S_DIN 33 // connect with I2S microphone pin SO
(signal out)
//#define RX_I2S_BCLK 15 // connect with I2S microphone pin SCK (bit
clock)
//#define RX_I2S_LRC 14 // connect with I2S microphone pin WS (word
select)
char BT_SINK_NAME[] = "Airdopes 141"; //"Infinity Glide 120,
Nirvana Ion, Airdopes 141/boAt Rockerz 510";Smartbuy EB4MVBT // set your
sink devicename here
char BT_SINK_PIN[] = "0000"; // sink pincode
char BT_DEVICE_NAME[] = "ESP_A2DP_SRC"; // source devicename
const i2s_port_t I2S_PORT_RX = I2S_NUM_0;
const uint32_t sample_rate = 44100; //44100; //43945;
const uint16_t buf_len = 1024;
size_t bytes_written = 0;
char readBuff[buf_len];
uint16_t buffSize;
uint8_t buffStat;
uint8_t gain = 12; // reduce volume -> increase gain
enum : uint8_t {BUFF_FULL, BUFF_EMPTY};
// DC-Blocker filter - removes DC component from I2S data
// See: https://www.dsprelated.com/freebooks/filters/DC_Blocker.html
// a1 = -0.9992 should heavily attenuate frequencies below 10Hz
//SOS_IIR_Filter DC_BLOCKER = {
//gain: 1.0,
//sos: {{-1.0, 0.0, +0.9992, 0}}
//};
// TDK/InvenSense INMP441
// Datasheet:
https://www.invensense.com/wp-content/uploads/2015/02/INMP441.pdf
// B ~= [1.00198, -1.99085, 0.98892]
// A ~= [1.0, -1.99518, 0.99518]
//SOS_IIR_Filter INMP441 = {
//gain: 1.00197834654696,
//sos: { // Second-Order Sections {b1, b2, -a1, -a2}
//{-1.986920458344451, +0.986963226946616, +1.995178510504166,
-0.995184322194091}
//}
//};
//---------------------------------------------------------------------------------------------------------------------
void i2s_install(){
/* RX: I2S_NUM_1 */
i2s_config_t i2s_config_rx = {
.mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX), // Only TX
I2S_COMM_FORMAT_STAND_PCM_SHORT
.sample_rate = sample_rate,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, // Only 8-bit DAC
support
.channel_format =
I2S_CHANNEL_FMT_RIGHT_LEFT,//I2S_CHANNEL_FMT_ALL_RIGHT,
//I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels
.communication_format = (i2s_comm_format_t)
I2S_COMM_FORMAT_STAND_I2S, // I2S_COMM_FORMAT_STAND_I2S,
//I2S_COMM_FORMAT_STAND_PCM_SHORT,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL2, // Interrupt level 1
.dma_buf_count = 4, // number of buffers, 128
max.
.dma_buf_len = 512, // size of each buffer60
60 pe good hain // 4-512;
.use_apll = false,
.tx_desc_auto_clear = true, // new in V1.0.1
.fixed_mclk = I2S_PIN_NO_CHANGE,
.mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT
};
i2s_pin_config_t pin_config_rx = {
.bck_io_num = RX_I2S_BCLK,
.ws_io_num = RX_I2S_LRC,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = RX_I2S_DIN
};
i2s_driver_install(I2S_PORT_RX, &i2s_config_rx, 0, NULL);
i2s_set_pin(I2S_PORT_RX, &pin_config_rx);
}
//---------------------------------------------SETUP--------------------------------------------------------------------
void setup(){
Serial.begin(115200);
i2s_install();
buffStat = BUFF_EMPTY;
log_i("free heap %i", esp_get_free_heap_size());
a2dp_source_init(BT_SINK_NAME, BT_SINK_PIN);
log_i("free heap %i", esp_get_free_heap_size());
}
//----------------------------------------------LOOP--------------------------------------------------------------------
void loop() {
//char *buf_ptr_read1 = readBuff + 4; // connect L/R with VDD
char *buf_ptr_read1 = readBuff; // connect L/R with GND
char *buf_ptr_write1 = readBuff;
if(buffStat == BUFF_EMPTY) {
size_t bytes_read = 0;
while(bytes_read == 0) {
i2s_read(I2S_PORT_RX, readBuff, buf_len, &bytes_read,
portMAX_DELAY);
}
uint32_t samples_read = bytes_read / 2 / (I2S_BITS_PER_SAMPLE_32BIT
/ 8);
// convert 2x 32 bit stereo -> 1 x 16 bit mono
for(int i = 0; i < samples_read; i++) {
// left channel
//int32_t sample = (buf_ptr_read1[3] << 24) + (buf_ptr_read1[2]
<< 16) + (buf_ptr_read1[1] << 8); //(buf_ptr_read1[4] << 32)+
//sample = sample >> gain;
int32_t sample = (buf_ptr_read1[3] << 24) +
(buf_ptr_read1[2]<<16);
sample = sample >> gain;
buf_ptr_write1[0] = sample & 0x00FF;
buf_ptr_write1[1] = (sample >>8) & 0x00FF;
// right channel
buf_ptr_write1[2] = buf_ptr_write1[0]; // mid
buf_ptr_write1[3] = buf_ptr_write1[1]; // high
buf_ptr_write1 += 2 * (I2S_BITS_PER_SAMPLE_16BIT / 8);
buf_ptr_read1 += 2 * (I2S_BITS_PER_SAMPLE_32BIT / 8);
buffSize = samples_read * 2 * (I2S_BITS_PER_SAMPLE_16BIT / 8);
}
buffStat = BUFF_FULL;
}
bt_loop();
}
//---------------------------------------------EVENTS-------------------------------------------------------------------
int32_t bt_data(uint8_t *data, int32_t len, uint32_t* sr){ // BT data event
*sr = 44100;
if (len < 0 || data == NULL) {
buffStat = BUFF_EMPTY;
return 0;
}
if(!buffSize) return 0;
memcpy(data, readBuff, buffSize);
buffStat = BUFF_EMPTY;
return buffSize;
}
void bt_info(const char* info){
Serial.printf("bt_info: %s\n", info);
}
On Mon, Aug 28, 2023 at 2:07 PM Dr. Gaurav Purohit ***@***.***>
wrote:
… Thank you for your reply
But Dear its sound goes very low
Any middle solution using a filter
Where and how shall I add a filer after samples.
Also any where I can reduce LAtency in A2dp Tx?
On Sun, Aug 27, 2023 at 10:19 PM Wolle ***@***.***> wrote:
> This is a difficult thing. The microphone used has a processing width of
> 24 bits, I2S must be set to 32 bits (because 24 does not exist), and the
> actual BT transmission uses 16 bits per channel. The simplest method is to
> cut out the lower 8 bits.
>
> //int32_t sample = (buf_ptr_read1[3] << 24) + (buf_ptr_read1[2] << 16) + (buf_ptr_read1[1] << 8);
> //sample = sample >> gain;
> int16_t sample = (buf_ptr_read1[3] << 8) + (buf_ptr_read1[2] );
>
> —
> Reply to this email directly, view it on GitHub
> <#475 (comment)>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ACV6JJDPZ7E72UUSD76YMS3XXN3BPANCNFSM6AAAAAAUOHZ7Y4>
> .
> You are receiving this because you commented.Message ID:
> ***@***.***
> .com>
>
--
SIMPLY GAURAV
--
SIMPLY GAURAV
|
Beta Was this translation helpful? Give feedback.
-
The microphone runs in 24 bit mode and BT uses 16 bit. Thus, the value range of the microphone is 256 times larger. This causes a right shift of 8 bits. In my example it is less, which increases the sensitivity, but an overflow (larger INT16_MAX or smaller INT16_MIN) You can build a filter with a curve that amplifies low signals and attenuates strong pages. |
Beta Was this translation helpful? Give feedback.
-
Thanks sir, But i am unable to do the same as you suggested.
Meanwhile I get this suggestion
*********
Now what i recommend is converting it to 16-bit signed samples:
CODE: SELECT ALL <https://www.esp32.com/viewtopic.php?t=15185#>
int16_t buffer16[ESP_NOW_MAX_DATA_LEN] = {0};for (int i=0; i<samplesRead; i++) {
uint8_t mid = buffer32[i * 4 + 2];
uint8_t msb = buffer32[i * 4 + 3];
uint16_t raw = (((uint32_t)msb) << 8) + ((uint32_t)mid);
memcpy(&buffer16[i], &raw, sizeof(raw)); // Copy so sign bits
aren't interfered with somehow.
}************By Chris_oz link:
https://www.esp32.com/viewtopic.php?t=15185Can you lead to use the
same in your existing code.
…On Fri, Sep 1, 2023 at 12:52 AM Wolle ***@***.***> wrote:
The microphone runs in 24 bit mode and BT uses 16 bit. Thus, the value
range of the microphone is 256 times larger. This causes a right shift of 8
bits. In my example it is less, which increases the sensitivity, but an
overflow (larger INT16_MAX or smaller INT16_MIN) You can build a filter
with a curve that amplifies low signals and attenuates strong pages.
—
Reply to this email directly, view it on GitHub
<#475 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACV6JJEDXBIWWN7N5DP2EJ3XYDP7JANCNFSM6AAAAAAUOHZ7Y4>
.
You are receiving this because you commented.Message ID:
***@***.***
com>
--
SIMPLY GAURAV
|
Beta Was this translation helpful? Give feedback.
-
The above mail is regarding
The microphone is a 24-bit one, but if you use bits_per_sample =
I2S_BITS_PER_SAMPLE_24BIT it doesn't work, maybe an ESP bug? Anyway 32 bits
works with some workarounds.
The 4 bytes that make up each sample in buffer32 are as follows:
First byte: E0 or 00, regardless of the sign of the other bytes, discard
these!
Byte 2: Lowest significant byte of the sample. You can also discard this
because it's just fuzz even in a quiet room.
Byte 3: Middle byte of the sample (signed)
Last byte: Most significant byte of the sample (signed).
Now what i recommend is converting it to 16-bit signed samples:
…On Tue, Sep 5, 2023 at 2:25 PM Dr. Gaurav Purohit ***@***.***> wrote:
Thanks sir, But i am unable to do the same as you suggested.
Meanwhile I get this suggestion
*********
Now what i recommend is converting it to 16-bit signed samples:
CODE: SELECT ALL <https://www.esp32.com/viewtopic.php?t=15185#>
int16_t buffer16[ESP_NOW_MAX_DATA_LEN] = {0};for (int i=0; i<samplesRead; i++) {
uint8_t mid = buffer32[i * 4 + 2];
uint8_t msb = buffer32[i * 4 + 3];
uint16_t raw = (((uint32_t)msb) << 8) + ((uint32_t)mid);
memcpy(&buffer16[i], &raw, sizeof(raw)); // Copy so sign bits aren't interfered with somehow.
}************By Chris_oz link: https://www.esp32.com/viewtopic.php?t=15185Can you lead to use the same in your existing code.
On Fri, Sep 1, 2023 at 12:52 AM Wolle ***@***.***> wrote:
> The microphone runs in 24 bit mode and BT uses 16 bit. Thus, the value
> range of the microphone is 256 times larger. This causes a right shift of 8
> bits. In my example it is less, which increases the sensitivity, but an
> overflow (larger INT16_MAX or smaller INT16_MIN) You can build a filter
> with a curve that amplifies low signals and attenuates strong pages.
>
> —
> Reply to this email directly, view it on GitHub
> <#475 (comment)>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ACV6JJEDXBIWWN7N5DP2EJ3XYDP7JANCNFSM6AAAAAAUOHZ7Y4>
> .
> You are receiving this because you commented.Message ID:
> ***@***.***
> .com>
>
--
SIMPLY GAURAV
--
SIMPLY GAURAV
|
Beta Was this translation helpful? Give feedback.
-
// Define a simple compressor function
int32_t compress(int32_t input, float threshold, float ratio) {
// Apply compression only if the input exceeds the threshold
if (input > threshold) {
// Apply compression ratio
input = threshold + (input - threshold) / ratio;
}
return input;
}
int main() {
// Sample byte array buf_ptr_read1
uint8_t buf_ptr_read1[4] = {0x11, 0x22, 0x33, 0x44};
// Combine bytes at indices 3 and 2 to create a 32-bit integer
int32_t sample = (buf_ptr_read1[3] << 24) + (buf_ptr_read1[2] << 16);
// Right-shift the combined sample (as in your original code)
sample = sample >> 14;
// Apply compression (you can adjust threshold and ratio as needed)
float threshold = 0x1000; // Adjust this threshold value as needed
float ratio = 2.0; // Adjust this compression ratio as needed
sample = compress(sample, threshold, ratio);
// Extract and store the compressed sample in buf_ptr_write1
buf_ptr_write1[0] = sample & 0x00FF;
buf_ptr_write1[1] = (sample >> 8) & 0x00FF;
// Print the result
printf("Sample: 0x%X%X\n", buf_ptr_write1[1], buf_ptr_write1[0]);
return 0;
}
is this want to say for dynamic range compression
am I doing right
…On Tue, Sep 5, 2023 at 2:26 PM Dr. Gaurav Purohit ***@***.***> wrote:
The above mail is regarding
The microphone is a 24-bit one, but if you use bits_per_sample =
I2S_BITS_PER_SAMPLE_24BIT it doesn't work, maybe an ESP bug? Anyway 32 bits
works with some workarounds.
The 4 bytes that make up each sample in buffer32 are as follows:
First byte: E0 or 00, regardless of the sign of the other bytes, discard
these!
Byte 2: Lowest significant byte of the sample. You can also discard this
because it's just fuzz even in a quiet room.
Byte 3: Middle byte of the sample (signed)
Last byte: Most significant byte of the sample (signed).
Now what i recommend is converting it to 16-bit signed samples:
On Tue, Sep 5, 2023 at 2:25 PM Dr. Gaurav Purohit ***@***.***>
wrote:
> Thanks sir, But i am unable to do the same as you suggested.
> Meanwhile I get this suggestion
>
> *********
> Now what i recommend is converting it to 16-bit signed samples:
>
> CODE: SELECT ALL <https://www.esp32.com/viewtopic.php?t=15185#>
>
> int16_t buffer16[ESP_NOW_MAX_DATA_LEN] = {0};for (int i=0; i<samplesRead; i++) {
> uint8_t mid = buffer32[i * 4 + 2];
> uint8_t msb = buffer32[i * 4 + 3];
> uint16_t raw = (((uint32_t)msb) << 8) + ((uint32_t)mid);
> memcpy(&buffer16[i], &raw, sizeof(raw)); // Copy so sign bits aren't interfered with somehow.
> }************By Chris_oz link: https://www.esp32.com/viewtopic.php?t=15185Can you lead to use the same in your existing code.
>
>
> On Fri, Sep 1, 2023 at 12:52 AM Wolle ***@***.***> wrote:
>
>> The microphone runs in 24 bit mode and BT uses 16 bit. Thus, the value
>> range of the microphone is 256 times larger. This causes a right shift of 8
>> bits. In my example it is less, which increases the sensitivity, but an
>> overflow (larger INT16_MAX or smaller INT16_MIN) You can build a filter
>> with a curve that amplifies low signals and attenuates strong pages.
>>
>> —
>> Reply to this email directly, view it on GitHub
>> <#475 (comment)>,
>> or unsubscribe
>> <https://github.com/notifications/unsubscribe-auth/ACV6JJEDXBIWWN7N5DP2EJ3XYDP7JANCNFSM6AAAAAAUOHZ7Y4>
>> .
>> You are receiving this because you commented.Message ID:
>> <schreibfaul1/ESP32-audioI2S/repo-discussions/475/comments/6879204@
>> github.com>
>>
>
>
> --
> SIMPLY GAURAV
>
--
SIMPLY GAURAV
--
SIMPLY GAURAV
|
Beta Was this translation helpful? Give feedback.
-
Dear Sir any comment or help on improving the Lag on A2DP
|
Beta Was this translation helpful? Give feedback.
-
Respected
Why Cant I change
const uint16_t buf_len
In the A2dp Code , I need to experiment whether I can improve the latency
issue in A2dp
Can I change SBS codec functionalities anywhere?
Regards
gaurav
|
Beta Was this translation helpful? Give feedback.
-
Dear Respected
Why Cant I change
const uint16_t buf_len 1024 to 512
can I improve the latency by reducing this value?
…
In the A2dp Code , I need to experiment whether I can improve the latency
issue in A2dp
Can I change SBS codec functionalities anywhere?
Regards
gaurav
--
SIMPLY GAURAV
|
Beta Was this translation helpful? Give feedback.
-
Hi!
I have a small project:
https://oshwlab.com/sir066/max98357esp32_shield
It is the MAX98357 based 2*3Watt stereo amplifier shield for LILYGO® TTGO T7 V1.3 MINI 32 ESP32 and other pin-compatible ESP32 boards. The board contains two MAX98357 chips, SD slot and IR receiver. No DAC used, MAX98357 directly utilise i2s stream from esp32.
I have just trued to use ESP-AudioI2S library with my board. It work fine, but there is some problem. The sound level with setting audio.SetVolume(21) is definely much lower than when I use other audio libraries. I tried to double values in volumetable[]:
// const uint8_t volumetable[22]={ 0, 1, 2, 3, 4 , 6 , 8, 10, 12, 14, 17,
// 20, 23, 27, 30 ,34, 38, 43 ,48, 52, 58, 64}; //22 elements
const uint8_t volumetable[22]={ 0, 2, 4, 6, 8 , 12 , 16, 20, 24, 28, 34,
40, 46, 54, 60 , 68, 76, 86 , 96, 104, 116, 128}; //22 elements
and now I still have much more louder and absolutely clear sound. I tested it with number of track, including special full amplitude sine 1Khz 16bit sound test track. No any dшstortions noted. So I do not understand why such volumetable[] value uses in this library. I suppose that there is something wrong in this place. Who can explain me this feature?
Beta Was this translation helpful? Give feedback.
All reactions