tierneytim / btaudio Goto Github PK
View Code? Open in Web Editor NEWBluetooth Audio for Arduino
Bluetooth Audio for Arduino
Hey,
First of great work!
I was wondering how to output the Bluetooth audio instead of an I2S signal, as an analog audio signal by using the built in DAC of the ESP. I couldn´t find anything about it in your libary.
I hope this is the right place to post my request, I am new to github.
Thanks in advance.
Hello! Would it be possible to use this library to make ESP32 act as bluetooth audio passthrough device? e.g. I can connect my laptop and phone to it, and let it stream to my bluetooth headphones combined audio from both devices
Hi,
It's great library to play music through Bluetooth and it also has volume control feature. By the way, how can I add additional features like play, pause, next. There is other library available on GitHub which has these features but it utilises more space and it doesn't work when combined with other code. I want a very light library which has all these features. I just want to try adding those features/commands to this library.
Can you please guide me how to do this?
Hi Tim,
how complicated would be to add a2dp source feature? I would like to decode something on the ESP32 and send it to Bluetooth headset. (Have 8k 16bit signed mono data) I know that HFP_GW is not (yet) supported by the arduino_esp32 but a2dp source shall work.
#include <Arduino.h>
#include <btAudio.h>
#define bck 26
#define ws 27
#define dout 25
// Sets the name of the audio device
btAudio audio = btAudio("ESP_Speaker");
void setup() {
// streams audio data to the ESP32
audio.begin();
// outputs the received data to an I2S DAC https://www.adafruit.com/product/3678
audio.I2S(bck, dout, ws);
}
void loop() {
}
fatal error: WebServer.h: No such file or directory
How to solve the error?
Should this work on MAX98357A (https://www.adafruit.com/product/3006) or will this only work on I2S Stereo Decoder - UDA1334A (https://www.adafruit.com/product/3678)?
Could code be modified to work with PWM audio Pam8302-(https://www.adafruit.com/product/2130)?
Would it be possible to setup Bluetooth so that requires passcode or pin number to sync?
Please add a simple way to add a custom data callback(s)
Hi!
First of all - thank you so much for your work. It's awesome and it's simple to use, I'm using it for my BT Speaker project. I tried to code it the normal way using ESP32 SDK, but I'm only a beginner and I couldn't handle it.
I'm just curious - is there any way to use your filters as an equalizer? They already exist, someone would "just" have to add a gain setting. I'd do it myself, but I don't have any idea how to start. If you could just point me in the right direction, maybe I'd manage.
Thanks again, keep up the good work!
Is it possible to record the data received while listening to the audio simultaneously?
I'm planning to apply your code with a Bluetooth microphone as a source, I tried using this, however, when I added the recording feature inside the callback function, the streaming stops.
Is there other way to retrieve the bt data that wont disturb the streaming of bt data?
Still, and again, awesome work! Thanks!
Is there a way to merge left and right data to produce the same audio on both output channels?
Hi!
Thank you so much for you work, it really has helped out with my project and works flawlessly.
I was just wondering if there was a way to perform some sort of Bluetooth connection status check?
I am currently working on a Bluetooth speaker and would love to be able to add a Bluetooth connection status light to show the user that they have successfully connected to the speaker but cannot figure out how to do it.
Any pointers in the right direction towards how to actually detect that a device has connected successfully would be greatly appreciated as I am fully stuck with this.
Thanks again!!
Wow! Fantastic work! Thank you!
Is there a way to apply, say, a low pass to the left channel and a high pass to the right channel?
I am using the "underTheHood" Bluetooth code of 'tierneytim' for my ESP32 application combined with the "bitluni" amplitude modulator for old AM radio's. In this application i2s0 is fed with AM modulated (at 800 kHz) BT audio data, i2s0 is linked to the internal DAC, and i2s1 is the 16-bit output for devices such as MAX98357 3W amp or the PCM5102 headphone module. Basically both i2s are fed by the bluetooth output data. This application worked perfect for more than one year on my old AM radio's, one is nearly 100 years old!
Recently I accepted a Arduine boards upgrade, since then, I cannot get the script working again: that is, after some code changes I needed to do since apparently three API's changed: 'i2s_write..' requires 5 arguments, i'2s_config... communication_format' changed.. the compiler accepted the changes but the i2s1 output remains distorted, with some echo effects..
Has someone an idea where I could find a solution? Or what I could test to isolate the problem? Should I perhaps go back to older versions of Arduino boards? (I forgot to note the version levels from the previous working code, =lesson learned!)
and.. does the "underTheHood" code still works after the latest Arduino boards updates?
IDE:2.2.1; Arduino ESP32 Boards 2.0.13; esp32 by Espressif Systems 2.0.14; Board used: ESP32 Dev Module @240MHz Cpu
Any help would be most appreciated!
Fre19
Hi, I've been trying to develop a feature by adding a record capability where it is triggered by a push button to record data received to a connected microSD card. Unfortunately I'm quite confused using the library since I'm new to object-oriented programming. May I ask for help for a sample code for this if possible?
You have advised that:
If you go this line you can add a RECORD case by simply writing to an SD card using SDIO.
but I'm quite lost how to do it.
You also said that:
This isn't in the code because you could then easily stream copyrighted music from the internet to an SD card. That would be illegal...
I'll be using this receiver together with another ESP32 as a BT source connected to an i2s mic.
Thank you very much.
Warm regards,
rmond
Hi man,
Thks for your wonderfull job !
I wonder if there would be a way to retrive information from the music that is streamed to the ESP32? I think of title, album, etc
/home/qwerty/Car Bluetooth/cemu/Cemu v2 Arduino ESP32/Arduino Code/libraries/btAudio-master/src/btAudio.cpp: In member function 'void btAudio::I2S(int, int, int)':
/home/qwerty/Car Bluetooth/cemu/Cemu v2 Arduino ESP32/Arduino Code/libraries/btAudio-master/src/btAudio.cpp:179:3: warning: narrowing conversion of 'btAudio::_sampleRate' from 'int32_t' {aka 'int'} to 'uint32_t' {aka 'unsigned int'} inside { } [-Wnarrowing]
};
First of all, I am really liking this btAudio project!!
Awesome work! :)
This is not an issue, but more like a question if you know how much the system latency is when using the IIR biquad filters?
I am purely talking about how much time the ESP32 needs to compute, not the external ADC/DAC.
Also, do you have any idea how many biquads can be used in total?
Need to update README to
I have problems integrating the reconnect option
error message:
C:\Users\X\Documents\Arduino\sketch_jul26a\sketch_jul26a.ino: In function 'void setup()':
sketch_jul26a:12:8: error: 'class btAudio' has no member named 'reconnect'
audio.reconnect();
^
Mehrere Bibliotheken wurden für "WiFi.h" gefunden
Benutzt: C:\Users\X\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.6\libraries\WiFi
Nicht benutzt: C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.57.0_x86__mdqgnx93n4wtt\libraries\WiFi
exit status 1
'class btAudio' has no member named 'reconnect'
whats my mistake here?
thank you so much
My use case for this library is to upgrade my car's stereo system with Bluetooth. What would be the best way to go about handling routing a microphone input back to the phone?
Hi 👋 can I get the playback time and the duration?
Building in release mode
Compiling .pio\build\esp32doit-devkit-v1\src\main.cpp.o
Compiling .pio\build\esp32doit-devkit-v1\libd32\btAudio\webDSP.cpp.o
In file included from .pio/libdeps/esp32doit-devkit-v1/btAudio/src/webDSP.cpp:1:
.pio/libdeps/esp32doit-devkit-v1/btAudio/src/webDSP.h:5:9: fatal error: WebServer.h: No such file or directory
but i am sure the "WebServer.h" exists.
How would I get the current volume of the connected device?
Can I get the song info like name and artist?
Awesome project!
How did you get around the crash when BT and WIFI are enabled?
I've tried two different boards (Adafruit HUZZAH, and DOIT ESP32 DEVKIT V1) with the same result. System crashes when WIFI and BT are enabled.
Arduino 1.8.15.
I figured out how to send some AVRCP commands. Basically you just run this, replacing <command>
with one of the commands below.
esp_avrc_ct_send_passthrough_cmd(0, <command>, ESP_AVRC_PT_CMD_STATE_PRESSED);
You can see all the commands here but it seems like only the ones below work (I tried just the hex codes for other commands but my phone didn't respond to any except these. I don't know if they're not supported by the avrc library or my phone).
ESP_AVRC_PT_CMD_PLAY
ESP_AVRC_PT_CMD_STOP
ESP_AVRC_PT_CMD_PAUSE
ESP_AVRC_PT_CMD_FORWARD
ESP_AVRC_PT_CMD_BACKWARD
ESP_AVRC_PT_CMD_REWIND
ESP_AVRC_PT_CMD_FAST_FORWARD
You can see more info about that specific method here.
ESP finally released their IDE core 2.0.0, breaking a couple of my projects in the process :-(
..and it seems to have broken this library; trying to compile the vanilla advertiseBluetooth.ino
sketch with a fully updated IDE 1.8.15 results in:
/home/owen/Arduino/libraries/btAudio/src/btAudio.cpp: In member function 'void btAudio::begin()':
/home/owen/Arduino/libraries/btAudio/src/btAudio.cpp:54:28: error: 'ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE' was not declared in this scope
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/owen/Arduino/libraries/btAudio/src/btAudio.cpp:54:28: note: suggested alternative: 'ESP_BT_GENERAL_DISCOVERABLE'
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ESP_BT_GENERAL_DISCOVERABLE
/home/owen/Arduino/libraries/btAudio/src/btAudio.cpp: In member function 'void btAudio::I2S(int, int, int)':
/home/owen/Arduino/libraries/btAudio/src/btAudio.cpp:164:60: warning: 'I2S_COMM_FORMAT_I2S' is deprecated [-Wdeprecated-declarations]
.communication_format = static_cast<i2s_comm_format_t>(I2S_COMM_FORMAT_I2S|I2S_COMM_FORMAT_I2S_MSB),
^~~~~~~~~~~~~~~~~~~
In file included from /home/owen/.arduino15/packages/esp32/hardware/esp32/2.0.0/tools/sdk/esp32/include/hal/esp32/include/hal/i2s_ll.h:30,
from /home/owen/.arduino15/packages/esp32/hardware/esp32/2.0.0/tools/sdk/esp32/include/hal/include/hal/i2s_hal.h:28,
from /home/owen/.arduino15/packages/esp32/hardware/esp32/2.0.0/tools/sdk/esp32/include/driver/include/driver/i2s.h:16,
from /home/owen/Arduino/libraries/btAudio/src/btAudio.h:10,
from /home/owen/Arduino/libraries/btAudio/src/btAudio.cpp:1:
/home/owen/.arduino15/packages/esp32/hardware/esp32/2.0.0/tools/sdk/esp32/include/hal/include/hal/i2s_types.h:70:5: note: declared here
I2S_COMM_FORMAT_I2S __attribute__((deprecated)) = 0x01, /*!< I2S communication format I2S, correspond to `I2S_COMM_FORMAT_STAND_I2S`*/
^~~~~~~~~~~~~~~~~~~
/home/owen/Arduino/libraries/btAudio/src/btAudio.cpp:164:80: warning: 'I2S_COMM_FORMAT_I2S_MSB' is deprecated [-Wdeprecated-declarations]
.communication_format = static_cast<i2s_comm_format_t>(I2S_COMM_FORMAT_I2S|I2S_COMM_FORMAT_I2S_MSB),
^~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/owen/.arduino15/packages/esp32/hardware/esp32/2.0.0/tools/sdk/esp32/include/hal/esp32/include/hal/i2s_ll.h:30,
from /home/owen/.arduino15/packages/esp32/hardware/esp32/2.0.0/tools/sdk/esp32/include/hal/include/hal/i2s_hal.h:28,
from /home/owen/.arduino15/packages/esp32/hardware/esp32/2.0.0/tools/sdk/esp32/include/driver/include/driver/i2s.h:16,
from /home/owen/Arduino/libraries/btAudio/src/btAudio.h:10,
from /home/owen/Arduino/libraries/btAudio/src/btAudio.cpp:1:
/home/owen/.arduino15/packages/esp32/hardware/esp32/2.0.0/tools/sdk/esp32/include/hal/include/hal/i2s_types.h:71:5: note: declared here
I2S_COMM_FORMAT_I2S_MSB __attribute__((deprecated)) = 0x01, /*!< I2S format MSB, (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_MSB) correspond to `I2S_COMM_FORMAT_STAND_I2S`*/
^~~~~~~~~~~~~~~~~~~~~~~
/home/owen/Arduino/libraries/btAudio/src/btAudio.cpp:170:3: warning: narrowing conversion of 'btAudio::_sampleRate' from 'uint32_t' {aka 'unsigned int'} to 'int' inside { } [-Wnarrowing]
};
^
exit status 1
Error compiling for board ESP32 Dev Module.
uurgh; a quick search shows that ESP have, indeed, messed with this recently, renaming some of the defines, eg here, and I assume elsewhere too.. I didn't look much further since.. priorities. But thought I should log this here.
In case you are interested, I'm using this on a esp32 powered watch, code here, based on an example in the TTGO watch library.
Sound is pitched down, songs (played via Spotify) start slowed down but later (4-5 sec) get to their normal speed.
#include <btAudio.h>
btAudio audio = btAudio("BTSink");
void setup() {
audio.begin();
int bck = 26;
int ws = 22;
int dout = 25;
audio.I2S(bck, dout, ws);
}
void loop() {}
I use Wemos D1 mini ESP32 + PCM5102 I2S DAC Decoder Board
I'm aware that problem might be specific to my hardware or software(pipewire), but it does not persist when I use https://github.com/pschatzmann/ESP32-A2DP or https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/classic_bt/a2dp_sink
Hello Sir , M studying your Code and find it useful. Please help in one regard to use the dynamic filter for High and low pass. the code is given Below.
code
// Gaurav
#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_LEVEL1, // Interrupt level 1
.dma_buf_count = 5, // number of buffers, 128 max.
.dma_buf_len = buf_len, // 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;
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);
}
Any Clue how to plug the Microphone in any given example
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.