ESP32 adalah mikrokontroler yang menyediakan API untuk Bluetooth A2DP yang dapat digunakan untuk menerima data suara misalnya dari Ponsel Anda dan membuatnya tersedia melalui metode panggilan balik. Outputnya adalah aliran data PCM, yang diterjemahkan dari format SBC. Dokumentasinya dapat ditemukan di sini.
I2S adalah standar antarmuka bus serial listrik yang digunakan untuk menghubungkan perangkat audio digital bersama-sama. Ini digunakan untuk mengkomunikasikan data audio PCM antara sirkuit terintegrasi dalam perangkat elektronik.
Jadi kita cukup memasukkan input dari Bluetooth ke output I2S: Contoh dari Espressif dapat ditemukan di Github.
Sayangnya contoh ini tidak membuat saya senang sehingga saya memutuskan untuk mengubahnya menjadi Perpustakaan Arduino sederhana yang sangat mudah digunakan dari IDE Perangkat Lunak Arduino.
Sesuai dengan namanya perpustakaan ini, ia mendukung protokol Bluetooth A2DP yang hanya menyediakan streaming audio!
Ini juga mendukung Audio/Video Remote Control Profile (AVRCP) bersama dengan A2DP.
Profil Hands-Free (HFP), Profil Headset (HSP) dan AVRCP yang berdiri sendiri tanpa A2DP tidak didukung!
Espressif menghentikan API I2S lama: Jadi dengan Arduino v3.0.0 (IDF v5) integrasi I2S lama saya tidak akan tersedia lagi. Sintaks lama masih berfungsi selama Anda tidak memutakhirkan.
Untuk mendukung API keluaran unik yang tidak bergantung pada versi, disarankan untuk menginstal dan menggunakan pustaka AudioTools. Jadi dokumentasi dan semua contoh telah diperbarui untuk menggunakan pendekatan baru ini.
Namun Anda juga dapat melakukan output ke kelas lain yang diwarisi dari Arduino Print: misalnya Arduino ESP32 I2SClass atau Anda dapat menggunakan panggilan balik data yang dijelaskan di bawah.
Ini dapat digunakan misalnya untuk membuat Speaker Bluetooth Anda sendiri.
Berikut adalah contoh paling sederhana yang hanya menggunakan pengaturan default yang tepat:
# include " AudioTools.h "
# include " BluetoothA2DPSink.h "
I2SStream i2s;
BluetoothA2DPSink a2dp_sink (i2s);
void setup () {
a2dp_sink. start ( " MyMusic " );
}
void loop () {
}
Ini membuat perangkat Bluetooth baru dengan nama "MyMusic" dan outputnya akan dikirim ke pin I2S default berikut yang perlu dihubungkan ke DAC eksternal:
Harap perhatikan bahwa pin default ini telah berubah dibandingkan dengan API lama!
Anda dapat menentukan pin Anda sendiri dengan mudah sebelum start
.
# include " AudioTools.h "
# include " BluetoothA2DPSink.h "
I2SStream i2s;
BluetoothA2DPSink a2dp_sink (i2s);
void setup () {
auto cfg = i2s. defaultConfig ();
cfg. pin_bck = 14 ;
cfg. pin_ws = 15 ;
cfg. pin_data = 22 ;
i2s. begin (cfg);
a2dp_sink. start ( " MyMusic " );
}
void loop () {
}
Anda juga dapat menggunakan API Arduino ESP32 I2S: Anda tidak perlu menginstal perpustakaan tambahan apa pun untuk ini.
# include " ESP_I2S.h "
# include " BluetoothA2DPSink.h "
const uint8_t I2S_SCK = 5 ; /* Audio data bit clock */
const uint8_t I2S_WS = 25 ; /* Audio data left and right clock */
const uint8_t I2S_SDOUT = 26 ; /* ESP32 audio data output (to speakers) */
I2SClass i2s;
BluetoothA2DPSink a2dp_sink (i2s);
void setup () {
i2s. setPins (I2S_SCK, I2S_WS, I2S_SDOUT);
if (!i2s. begin (I2S_MODE_STD, 44100 , I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, I2S_STD_SLOT_BOTH)) {
Serial. println ( " Failed to initialize I2S! " );
while ( 1 ); // do nothing
}
a2dp_sink. start ( " MyMusic " );
}
void loop () {}
Harap dicatat, bahwa API ini juga bergantung pada versi yang diinstal: Contoh di atas adalah untuk ESP32 >= 3.0.0!
Anda juga dapat mengirim output langsung ke DAC internal ESP32 dengan menggunakan AnalogAudioStream dari AudioTools:
# include " AudioTools.h "
# include " BluetoothA2DPSink.h "
AnalogAudioStream out;
BluetoothA2DPSink a2dp_sink (out);
void setup () {
a2dp_sink. start ( " MyMusic " );
}
void loop () {
}
Outputnya sekarang menuju ke pin DAC GPIO25 (Saluran 1) dan GPIO26 (Saluran 2).
Anda dapat diberitahu ketika sebuah paket diterima. API ini menggunakan data PCM yang biasanya diformat sebagai laju pengambilan sampel 44,1kHz, data sampel dua saluran 16-bit.
// In the setup function:
a2dp_sink.set_on_data_received(data_received_callback);
// Then somewhere in your sketch:
void data_received_callback () {
Serial. println ( " Data packet received " );
}
Atau Anda dapat mengakses paket:
// In the setup function:
a2dp_sink.set_stream_reader(read_data_stream);
// Then somewhere in your sketch:
void read_data_stream ( const uint8_t *data, uint32_t length)
{
int16_t *samples = ( int16_t *) data;
uint32_t sample_count = length/ 2 ;
// Do something with the data packet
}
Dalam metode a2dp_sink.set_stream_reader()
Anda dapat memberikan parameter opsional yang menentukan apakah Anda ingin output ke I2S aktif atau nonaktif - Jadi, Anda dapat menggunakan metode ini misalnya untuk mematikan I2S hanya dengan memanggil a2dp_sink.set_stream_reader(read_data_stream, false)
Anda dapat mendaftarkan metode yang akan dipanggil ketika sistem menerima metadata AVRC ( esp_avrc_md_attr_mask_t
). Ini sebuah contoh
void avrc_metadata_callback ( uint8_t data1, const uint8_t *data2) {
Serial. printf ( " AVRC metadata rsp: attribute id 0x%x, %s n " , data1, data2);
}
a2dp_sink.set_avrc_metadata_callback(avrc_metadata_callback);
a2dp_sink.start( " BT " );
Secara default, Anda seharusnya mendapatkan informasi yang paling penting, namun Anda dapat menyesuaikannya dengan memanggil metode set_avrc_metadata_attribute_mask
, misalnya jika Anda hanya memerlukan judul dan waktu pemutaran, Anda dapat menghubungi:
set_avrc_metadata_attribute_mask (ESP_AVRC_MD_ATTR_TITLE | ESP_AVRC_MD_ATTR_PLAYING_TIME);
sebelum Anda memulai wastafel A2DP. Perhatikan bahwa data2 sebenarnya adalah string char*, jadi meskipun ESP_AVRC_MD_ATTR_PLAYING_TIME
didokumentasikan sebagai milidetik durasi media, Anda harus menguraikannya sebelum menghitungnya. Lihat contoh metadata untuk informasi lebih lanjut.
Mirip dengan avrc_metadata_callback
, ESP IDF v4+ mendukung callback esp_avrc_rn_param_t
tertentu seperti set_avrc_rn_playstatus_callback
, set_avrc_rn_play_pos_callback
dan set_avrc_rn_track_change_callback
yang dapat digunakan untuk mendapatkan status pemutaran esp_avrc_playback_stat_t playback
, posisi pemutaran uint32_t play_pos
dan uint8_t elm_id
melacak perubahan bendera masing-masing. Lihat contoh playing_status_callbacks untuk lebih jelasnya.
Saya telah menambahkan perintah AVRC berikut, yang dapat Anda gunakan untuk 'mengontrol' Sumber A2DP Anda:
Ini dapat digunakan untuk memberi makan misalnya Speaker Bluetooth Anda dengan data audio Anda.
Kami juga dapat menghasilkan suara dan mengirimkannya misalnya ke Speaker Bluetooth.
Codec audio yang didukung di ESP32 A2DP adalah SBC: API menggunakan data PCM yang biasanya diformat sebagai laju pengambilan sampel 44,1kHz, data sampel dua saluran 16-bit.
Saat Anda memulai Sumber BluetoothA2DPS, Anda harus meneruskan nama Bluetooth yang ingin Anda sambungkan dan 'fungsi panggilan balik' yang menghasilkan data suara:
# include " BluetoothA2DPSource.h "
BluetoothA2DPSource a2dp_source;
// callback
int32_t get_sound_data (Frame *data, int32_t frameCount) {
// generate your sound data
// return the effective length (in frames) of the generated sound (which usually is identical with the requested len)
// 1 frame is 2 channels * 2 bytes = 4 bytes
return frameCount;
}
void setup () {
a2dp_source. start ( " MyMusic " , get_sound_data);
}
void loop () {
}
Dalam contoh tersebut Anda dapat menemukan implementasi yang menghasilkan suara dengan bantuan fungsi sin(). Anda juga dapat menyebutkan beberapa nama Bluetooth alternatif. Sistem hanya terhubung ke sistem pertama yang tersedia:
void setup () {
static std::vector< char *> bt_names = { " MyMusic " , " RadioPlayer " , " MusicPlayer " };
a2dp_source. start (bt_names, get_sound_data);
}
Anda juga dapat memberikan data secara langsung sebagai array sederhana uint8_t:
# include " BluetoothA2DPSource.h "
extern const uint8_t StarWars10_raw[];
extern const unsigned int StarWars10_raw_len;
BluetoothA2DPSource a2dp_source;
SoundData *music = new OneChannelSoundData(( int16_t *)StarWars30_raw, StarWars30_raw_len/ 2 );
void setup () {
a2dp_source. start ( " RadioPlayer " );
a2dp_source. write_data (music);
}
void loop () {
}
Array dapat disiapkan misalnya dengan cara berikut:
Anda mungkin ingin mengkompilasi dengan Skema Partisi: Aplikasi Besar!
Pada contoh di atas kami menyediakan data dengan satu saluran. Keuntungannya adalah menggunakan lebih sedikit ruang dibandingkan rekaman 2 saluran, yang dapat Anda gunakan dengan cara berikut:
SoundData *data = new TwoChannelSoundData((Frame*)StarWars10_raw,StarWars10_raw_len/4);
Di konstruktor Anda dapat meneruskan parameter tambahan:
TwoChannelSoundData (Frame *data, int32_t frameCount, bool loop= false );
OneChannelSoundData ( int16_t *data, int32_t frameCount, bool loop= false , ChannelInfo channelInfo=Both);
OneChannel8BitSoundData ( int8_t *data, int32_t frameCount, bool loop= false , ChannelInfo channelInfo=Both);
Library ini menggunakan logger ESP32 yang dapat Anda aktifkan di Arduino di - Tools - Core Debug Log.
Kode saat ini sepenuhnya bergantung pada ESP-IDF (yang juga disediakan oleh inti Arduino ESP32). Tidak ada ketergantungan lain dan ini termasuk Arduino API!
Oleh karena itu kami mendukung:
Namun pembatasan ini membatasi contoh yang diberikan.
Sebelum Anda mengkloning proyek, harap baca informasi berikut yang dapat ditemukan di Wiki.
Anda dapat menggunakan perpustakaan ini secara mandiri, tetapi ini adalah bagian dari proyek alat audio saya. Jadi Anda dapat dengan mudah meningkatkan fungsi ini dengan efek suara, menggunakan filter, menggunakan sink audio atau sumber audio alternatif, melakukan FFT, dll. Berikut adalah contoh sederhana bagaimana Anda dapat menganalisis data audio dengan FFT.
Saya menghabiskan banyak waktu untuk memberikan dokumentasi yang komprehensif dan lengkap. Jadi harap baca dokumentasinya terlebih dahulu dan periksa masalah serta diskusinya sebelum memposting hal baru di Github.
Buka masalah hanya untuk bug dan jika itu bukan bug, gunakan diskusi: Berikan informasi yang cukup tentang
untuk memungkinkan orang lain memahami dan mereproduksi masalah Anda.
Yang terakhir, yang terpenting, jangan kirimi saya email apa pun atau kirimkan pertanyaan apa pun di situs pribadi saya!
Dapatkan inspirasi dari proyek yang menggunakan perpustakaan ini dan bagikan proyek Anda dengan komunitas.
Untuk Arduino Anda dapat mengunduh perpustakaan sebagai zip dan memanggil include Library -> zip perpustakaan. Atau Anda dapat mengkloning proyek ini ke folder perpustakaan Arduino misalnya dengan
cd ~ /Documents/Arduino/libraries
git clone https://github.com/pschatzmann/ESP32-A2DP.git
git clone https://github.com/pschatzmann/arduino-audio-tools.git
Untuk contoh yang diberikan, Anda juga perlu menginstal perpustakaan alat audio.
Untuk kerangka lain lihat Wiki
Riwayat Perubahan dapat ditemukan di Wiki
Perangkat lunak ini benar-benar gratis, tetapi Anda dapat membuat saya bahagia dengan menghadiahi saya hadiah