ESP32 通过蓝牙显示歌词代码示例

news2024/11/18 10:46:12

通过蓝牙协议播放音乐,有的时候需要显示歌词,这里就是a2dp库获取了歌词

值得注意的是要想正确获取到歌词,必须打开各种播放器的字幕(歌词)开关

本项目用了三个开源库 a2dp,tft_espi,xfont.

a2dp :蓝牙传输音频资料和字幕信息

tft_espi : tft 屏幕驱动

xfont : 显示汉字 ,详细使用请参考 GitHub - StarCompute/tftziku: 这是一个通过单片机在各种屏幕上显示中文的解决方案

注意,xfont的初始化必须先执行。

项目内的代码通过网易云音乐 播放正常获取到歌词。

 

项目整体开源到了: https://github.com/StarCompute/bluemusic

 

#include <Arduino.h>
// #include "AudioTools.h"
#include "a2dp/BluetoothA2DPSink.h"
#include "xfont.h"


// #define TFT_SCLK   22
// #define TFT_MOSI  21
// #define TFT_RST     25
// #define TFT_DC      14
// #define TFT_CS   	 15


XFont *_xFont;
BluetoothA2DPSink a2dp_sink;
// Then somewhere in your sketch:
void read_data_stream(const uint8_t *data, uint32_t length)
{
  i2s_write(I2S_NUM_0,data,length,NULL,0);
}
void rssi(esp_bt_gap_cb_param_t::read_rssi_delta_param &rssiParam)
{
  Serial.print("rssi value: ");
  Serial.println(rssiParam.rssi_delta);
}

String song_singer = "";
String song_album = "";
float totalSongTime=1.0;

// 显示播放的百分比,其实可以优化的更好
void avrc_rn_play_pos_callback(uint32_t play_pos) {
  Serial.printf("Play position is %d (%d seconds)\n", play_pos, (int)round(play_pos/1000.0));
  if(totalSongTime>0){
    float per=play_pos/totalSongTime*100;
    _xFont->tft.fillRect(0, 102, 400, 40, TFT_BLACK);
    _xFont->DrawChineseEx(0, 102, "" + String(per,2)+"%", TFT_SILVER,TFT_BLACK);
  }
}

void avrc_metadata_callback(uint8_t data1, const uint8_t *data2)
{
  // Serial.printf("AVRC metadata rsp: attribute id 0x%x, %s\n", data1, data2);

  String strData2 = (const char *)data2;

  if(strData2!="0")Serial.printf("data1: %d data2: %s \n",data1,strData2);
  if (data1 == 2)
  {
    // Serial.printf("歌名:%s", data2);
    if (song_singer != strData2)
    {
      _xFont->tft.fillRect(0, 2, 400, 40, TFT_BLACK);
      _xFont->DrawChineseEx(0, 2, "" + strData2,TFT_GREEN,TFT_BLACK);
     
      song_singer = strData2;
    }
  }
  if (data1 == 4)
  {
    // Serial.printf("歌手:%s", data2);
    if (song_album != strData2)
    {
      _xFont->tft.fillRect(0, 46, 400, 40, TFT_BLACK);
      _xFont->DrawChineseEx(0, 46, "" + strData2, TFT_RED,TFT_BLACK);
      song_album = strData2;
    }
  }
  if (data1 == 1)
  {
    // Serial.printf("专辑:%s", data2);
    _xFont->tft.fillRect(0, 71, 400, 30, TFT_BLACK);
    
    _xFont->DrawChineseEx(0, 71, "" + strData2, TFT_LIGHTGREY,TFT_BLACK);
  }
  if(data1==64)totalSongTime=strData2.toFloat();
  // 0x8 第几首歌
  // 0x10 总共多少首歌
  // 0x20
}

void connection_state_changed(esp_a2d_connection_state_t state, void *ptr)
{
  Serial.println(a2dp_sink.to_str(state));
}

void audio_state_changed(esp_a2d_audio_state_t state, void *ptr)
{
  Serial.println(a2dp_sink.to_str(state));
}
 
void setup()
{

  Serial.begin(115200);
    _xFont = new XFont(true);

   _xFont->DrawChineseEx(0, 2, "欢迎使用。。", TFT_GREEN);
 
  a2dp_sink.set_avrc_metadata_attribute_mask(ESP_AVRC_MD_ATTR_TITLE | ESP_AVRC_MD_ATTR_ARTIST | ESP_AVRC_MD_ATTR_ALBUM | ESP_AVRC_MD_ATTR_TRACK_NUM | ESP_AVRC_MD_ATTR_NUM_TRACKS|ESP_AVRC_MD_ATTR_PLAYING_TIME|ESP_AVRC_MD_ATTR_GENRE);
  // a2dp_sink.
  a2dp_sink.set_avrc_metadata_callback(avrc_metadata_callback);
  a2dp_sink.set_on_connection_state_changed(connection_state_changed);
  a2dp_sink.set_on_audio_state_changed(audio_state_changed);
  a2dp_sink.set_avrc_rn_play_pos_callback(avrc_rn_play_pos_callback);
  i2s_pin_config_t my_pin_config = {
        .bck_io_num = 32,//输入
        .ws_io_num = 33,//输入
        .data_out_num = 23,//输出
        .data_in_num = I2S_PIN_NO_CHANGE
    };
  a2dp_sink.set_pin_config(my_pin_config);
  a2dp_sink.start("my music");
  
   
 

}

void loop()
{
  delay(100);
}

 由于歌词内容不确定,所以使用了开源中文字库 :

GitHub - StarCompute/tftziku: 这是一个通过单片机在各种屏幕上显示中文的解决方案

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1900319.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt 网络编程 udp通信

学习目标&#xff1a;使用udp通信 前置环境 运行环境:qt creator 4.12 学习内容 UDP 协议基础知识 1、UDP(用户数据报协议)是轻量的、不可靠的、面向数据报、无连接的协议&#xff0c;用于可靠性要求不高的场合。两个应用程序之间进行UDP 通信不需先建立持久的 socket 连接…

【IT领域新生必看】解密Java中的静态方法与实例方法:小白也能轻松掌握的全方位指南

文章目录 引言什么是静态方法&#xff1f;定义和使用静态方法示例&#xff1a; 静态方法的特点示例&#xff1a; 什么是实例方法&#xff1f;定义和使用实例方法示例&#xff1a; 实例方法的特点示例&#xff1a; 静态方法与实例方法的区别作用范围示例&#xff1a; 访问权限示…

宁德时代天行发布,商用车超充时代来临

近日&#xff0c;宁德时代正式推出商用动力电池品牌——“宁德时代天行”&#xff0c;同时发布“宁德时代天行轻型商用车&#xff08;L&#xff09;-超充版”和“宁德时代天行轻型商用车&#xff08;L&#xff09;-长续航版”两款产品&#xff0c;可实现4C超充能力和500km的实况…

14-38 剑和诗人12 - RAG+ 思维链 ⇒ 检索增强思维(RAT)

在快速发展的 NLP 和 LLM 领域&#xff0c;研究人员不断探索新技术来增强这些模型的功能。其中一种备受关注的技术是检索增强生成 (RAG) 方法&#xff0c;它将 LLM 的生成能力与从外部来源检索相关信息的能力相结合。然而&#xff0c;最近一项名为检索增强思维 (RAT) 的创新通过…

计算机网络(2

计算机网络续 一. 网络编程 网络编程, 指网络上的主机, 通过不同的进程, 以编程的方式实现网络通信(或网络数据传输). 即便是同一个主机, 只要不同进程, 基于网络来传输数据, 也属于网络编程. 二. 网络编程套接字(socket) socket: 操作系统提供的网络编程的 API 称作 “soc…

免杀笔记 ----> DLL注入

这段时间我们暂时没什么事情干的话我们就继续更新我们的免杀笔记力&#xff01;&#xff01;&#xff01; &#xff1a;今天我们讲DLL注入 目录 1.DLL注入 2.直接加载DLL&#xff1f; 3.远程线程注入 获取Handle 远程申请内存空间 将我们的CS的DLL加载入内存 创建远程线…

C语言 | Leetcode C语言题解之第218题天际线问题

题目&#xff1a; 题解&#xff1a; struct pair {int first, second; };struct Heap {struct pair* heap;int heapSize;bool (*cmp)(struct pair*, struct pair*); };void init(struct Heap* obj, int n, bool (*cmp)(struct pair*, struct pair*)) {obj->heap malloc(si…

Midjourney对图片细微调整和下载保存

点击v2是对第二图片细微调整。 点击u3对第3张图片进行放大。 保存图片: 对点击u3放大的图片&#xff0c;双击 , 右键保存图片

antd通过监听change方法实现表格分页查询功能

<script setup> import {computed, onMounted, ref} from "vue"; import axios from "axios";const columns [{name: 姓名,dataIndex: name,key: name,},{name: 性别,dataIndex: gender,key: gender,},{title: 年龄,dataIndex: age,key: age,},{tit…

江苏徐州SAP代理商有哪些?怎么选择?

在数字化浪潮席卷全球的今天&#xff0c;企业对于高效、智能的管理系统需求日益迫切。SAP作为全球领先的企业管理软件解决方案提供商&#xff0c;其产品在市场上享有极高的声誉。而在江苏徐州&#xff0c;哲讯智能科技作为SAP的代理商&#xff0c;以其专业的技术实力和优质的服…

配置基于不同端口的虚拟主机

更改配置文件&#xff0c;添加三个不同端口的虚拟主机 <directory /www> allowoverride none require all granted </directory><virtualhost 192.168.209.136:80> documentroot /www servername 192.168.209.136 </virtualhost><virtualhost 192.…

idea中没有显示‘‘Spring‘‘一栏 (已解决)

第一步: 随便找一个Bean(即直接或者间接使用Component的类) 第二步: 找到左边的图标, 右键这个图标, 然后选择如下选项: 第三步: 成功 然后就成功了, 可以看到具体的bean了以及其bean的关系图等.

数据库-多表设计 多表查询

多表设计 一对多 一对多关系实现&#xff1a;在数据库表中多的一方&#xff0c;添加字段&#xff0c;来关联一的一方的主键 外键约束 -- 创建表时指定 create table 表名(字段名 数据类型,...[constraint] [外键名称] foreign key (外键字段名) references 主表…

InetAddress.getLocalHost().getHostAddress()阻塞导致整个微服务崩溃

InetAddress.getLocalHost().getHostAddress()阻塞导致整个微服务崩溃 import java.net.InetAddress;public class GetHostIp {public static void main(String[] args) {try {long start System.currentTimeMillis();String ipAddress InetAddress.getLocalHost().getHostA…

(一)优化算法-遗传算法

目录 前言 一、什么是遗传算法&#xff1f; &#xff08;一&#xff09;基本结构 &#xff08;二&#xff09;遗传操作 二、仿真过程 &#xff08;一&#xff09;主程序部分 &#xff08;二&#xff09;选择函数 &#xff08;三&#xff09;交叉函数 &#xff08;四&a…

2024年加密货币市场展望:L1、L2、LSD、Web3 和 GameFi 板块的全面分析与预测

随着区块链技术的快速发展&#xff0c;加密货币市场在2024年继续展现出蓬勃的生机和创新的潜力。本文将深入分析L1、L2、LSD、Web3和GameFi这五大板块的发展趋势和预测&#xff0c;帮助投资者和爱好者更好地理解和把握市场机遇。 一、L1&#xff1a;基础层协议的持续进化 L1&a…

最新全平台无人直播硬改XCMS系统,支持任何平台

软件功能: 改虚拟摄像头为真实摄像头&#xff0c;改真实麦克风&#xff0c;图层去重、镜头晃动、增加噪点去重、随机播放辅音&#xff0c;两条音轨帮助音频去重、随机音效、随机播放速度&#xff0c;直播源实时转播等等.防违规&#xff0c;防非实时 设备需求: 电脑&#xf…

万界星空科技机械加工行业MES解决方案

机械加工行业作为制造业的重要组成部分&#xff0c;面临着生产效率、成本控制和产品质量提升等多重挑战。为了应对这些挑战&#xff0c;引入并实施制造执行系统&#xff08;MES&#xff09;成为了行业的必然选择。本文将详细介绍一种针对机械加工行业的MES解决方案&#xff0c;…

IT入门知识第八部分《人工智能》(9/10)

1.引言 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;已成为推动技术革新的关键力量。它们不仅改变了我们与机器的互动方式&#xff0c;还极大地拓展了解决问题的可能性。本文将深入探讨人工智能和机器学习的基础&…

全新桌面编辑器

目录 前言 一、链接 ONLYOFFICE 8.1版本 官网下载链接&#xff1a; ONLYOFFICE 在线工具&#xff1a; 下载版本推荐&#xff1a; 二、使用体验 1. 界面设计&#xff1a; 2. 文档编辑功能&#xff1a; 3. 电子表格功能&#xff1a; 4. 演示文稿功能&#xff1a; 5.PDF编…