rertet

  • 2024-11-01
  • 上传了资料: 智联音响

  • 发表了主题帖: 2024 DigiKey 创意大赛】之智联音响

    本帖最后由 rertet 于 2024-11-1 09:02 编辑 一、作品简介 本环境项目模块目的是将有线音响赋值成无线wifi音响 处于同一局域网下即可实现音频传输 手机端使用酷狗音进行音乐推送       二、系统框图 三、功能说明 ESP32 评估板:负责数据处理和传输 LCD 触摸屏显示器:显示信息 手机app酷狗客户端   四、作品源码 #include "esp_log.h" #include "nvs_flash.h" #include "board.h" #include "esp_peripherals.h" #include "periph_wifi.h" #include "audio_mem.h" #include "esp_wifi.h" #include "esp_ssdp.h" #include "esp_dlna.h" #include "esp_audio.h" #include "esp_decoder.h" #include "http_stream.h" #include "i2s_stream.h" #include "media_lib_adapter.h" #include "audio_idf_version.h" #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 0)) #include "esp_netif.h" #else #include "tcpip_adapter.h" #endif static const char *TAG = "DLNA_EXAMPLE"; #define DLNA_UNIQUE_DEVICE_NAME "ESP32_DMR_8db0797a" #define DLNA_DEVICE_UUID "8db0797a-f01a-4949-8f59-51188b181809" #define DLNA_ROOT_PATH "/rootDesc.xml" static esp_audio_handle_t player = NULL; static esp_dlna_handle_t dlna_handle = NULL; static int vol, mute; static char *track_uri = NULL; static const char *trans_state = "STOPPED"; static void player_event_handler(esp_audio_state_t *state, void *ctx) { if (dlna_handle == NULL) { return ; } switch (state->status) { case AUDIO_STATUS_RUNNING: trans_state = "PLAYING"; esp_dlna_notify_avt_by_action(dlna_handle, "TransportState"); break; case AUDIO_STATUS_PAUSED: trans_state = "PAUSED_PLAYBACK"; esp_dlna_notify_avt_by_action(dlna_handle, "TransportState"); break; case AUDIO_STATUS_STOPPED: case AUDIO_STATUS_FINISHED: trans_state = "STOPPED"; esp_dlna_notify_avt_by_action(dlna_handle, "TransportState"); break; default: break; } } int renderer_request(esp_dlna_handle_t dlna, const upnp_attr_t *attr, int attr_num, char *buffer, int max_buffer_len) { int req_type; int tmp_data = 0, buffer_len = 0; int hour = 0, min = 0, sec = 0; if (attr_num != 1) { return 0; } req_type = attr->type & 0xFF; switch (req_type) { case RCS_GET_MUTE: ESP_LOGD(TAG, "get mute = %d", mute); return snprintf(buffer, max_buffer_len, "%d", mute); case RCS_SET_MUTE: mute = atoi(buffer); ESP_LOGD(TAG, "set mute = %d", mute); if (mute) { esp_audio_vol_set(player, 0); } else { esp_audio_vol_set(player, vol); } esp_dlna_notify(dlna, "RenderingControl"); return 0; case RCS_GET_VOL: esp_audio_vol_get(player, &vol); ESP_LOGI(TAG, "get vol = %d", vol); return snprintf(buffer, max_buffer_len, "%d", vol); case RCS_SET_VOL: vol = atoi(buffer); ESP_LOGI(TAG, "set vol = %d", vol); esp_audio_vol_set(player, vol); esp_dlna_notify(dlna, "RenderingControl"); return 0; case AVT_PLAY: ESP_LOGI(TAG, "Play with speed=%s trans_state %s", buffer, trans_state); esp_audio_state_t state = { 0 }; esp_audio_state_get(player, &state); if (state.status == AUDIO_STATUS_PAUSED) { esp_audio_resume(player); esp_dlna_notify(dlna, "AVTransport"); break; } else if (track_uri != NULL) { esp_audio_play(player, AUDIO_CODEC_TYPE_DECODER, track_uri, 0); esp_dlna_notify(dlna, "AVTransport"); } return 0; case AVT_STOP: ESP_LOGI(TAG, "Stop instance=%s", buffer); esp_audio_stop(player, TERMINATION_TYPE_NOW); esp_dlna_notify_avt_by_action(dlna_handle, "TransportState"); return 0; case AVT_PAUSE: ESP_LOGI(TAG, "Pause instance=%s", buffer); esp_audio_pause(player); esp_dlna_notify_avt_by_action(dlna_handle, "TransportState"); return 0; case AVT_NEXT: case AVT_PREV: esp_audio_stop(player, TERMINATION_TYPE_NOW); return 0; case AVT_SEEK: sscanf(buffer, "%d:%d:%d", &hour, &min, &sec); tmp_data = hour * 3600 + min * 60 + sec; ESP_LOGI(TAG, "Seekto %d s", tmp_data); esp_audio_seek(player, tmp_data); return 0; case AVT_SET_TRACK_URI: ESP_LOGI(TAG, "SetAVTransportURI=%s", buffer); esp_audio_state_t state_t = { 0 }; esp_audio_state_get(player, &state_t); if ((track_uri != NULL) && (state_t.status == AUDIO_STATUS_RUNNING) && strcasecmp(track_uri, buffer)) { esp_audio_stop(player, TERMINATION_TYPE_NOW); esp_dlna_notify(dlna, "AVTransport"); } free(track_uri); track_uri = NULL; if (track_uri == NULL) { asprintf(&track_uri, "%s", buffer); } return 0; case AVT_SET_TRACK_METADATA: ESP_LOGD(TAG, "CurrentURIMetaData=%s", buffer); return 0; case AVT_GET_TRACK_URI: if (track_uri != NULL) { return snprintf(buffer, max_buffer_len, "%s", track_uri); } else { return 0; } case AVT_GET_PLAY_SPEED: /* ["1"] */ return snprintf(buffer, max_buffer_len, "%d", 1); case AVT_GET_PLAY_MODE: return snprintf(buffer, max_buffer_len, "NORMAL"); case AVT_GET_TRANS_STATUS: /* ["ERROR_OCCURRED", "OK"] */ return snprintf(buffer, max_buffer_len, "OK"); case AVT_GET_TRANS_STATE: /* ["STOPPED", "PAUSED_PLAYBACK", "TRANSITIONING", "NO_MEDIA_PRESENT"] */ ESP_LOGI(TAG, "_avt_get_trans_state %s", trans_state); return snprintf(buffer, max_buffer_len, trans_state); case AVT_GET_TRACK_DURATION: case AVT_GET_MEDIA_DURATION: esp_audio_duration_get(player, &tmp_data); tmp_data /= 1000; buffer_len = snprintf(buffer, max_buffer_len, "%02d:%02d:%02d", tmp_data / 3600, tmp_data / 60, tmp_data % 60); ESP_LOGD(TAG, "_avt_get_duration %s", buffer); return buffer_len; case AVT_GET_TRACK_NO: return snprintf(buffer, max_buffer_len, "%d", 1); case AVT_GET_TRACK_METADATA: return 0; // case AVT_GET_POS_ABSTIME: case AVT_GET_POS_RELTIME: esp_audio_time_get(player, &tmp_data); tmp_data /= 1000; buffer_len = snprintf(buffer, max_buffer_len, "%02d:%02d:%02d", tmp_data / 3600, tmp_data / 60, tmp_data % 60); ESP_LOGD(TAG, "_avt_get_time %s", buffer); return buffer_len; // case AVT_GET_POS_ABSCOUNT: case AVT_GET_POS_RELCOUNT: esp_audio_pos_get(player, &tmp_data); buffer_len = snprintf(buffer, max_buffer_len, "%d", tmp_data); ESP_LOGD(TAG, "_avt_get_pos %s", buffer); return buffer_len; } return 0; } static int _http_stream_event_handle(http_stream_event_msg_t *msg) { if (msg->event_id == HTTP_STREAM_RESOLVE_ALL_TRACKS) { return ESP_OK; } if (msg->event_id == HTTP_STREAM_FINISH_TRACK) { return http_stream_next_track(msg->el); } if (msg->event_id == HTTP_STREAM_FINISH_PLAYLIST) { return http_stream_restart(msg->el); } return ESP_OK; } static void audio_player_init(void) { audio_board_handle_t board_handle = audio_board_init(); audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_DECODE, AUDIO_HAL_CTRL_START); esp_audio_cfg_t cfg = DEFAULT_ESP_AUDIO_CONFIG(); cfg.vol_handle = board_handle->audio_hal; cfg.vol_set = (audio_volume_set)audio_hal_set_volume; cfg.vol_get = (audio_volume_get)audio_hal_get_volume; cfg.prefer_type = ESP_AUDIO_PREFER_MEM; cfg.resample_rate = 48000; player = esp_audio_create(&cfg); // Create readers and add to esp_audio http_stream_cfg_t http_cfg = HTTP_STREAM_CFG_DEFAULT(); http_cfg.event_handle = _http_stream_event_handle; http_cfg.type = AUDIO_STREAM_READER; http_cfg.enable_playlist_parser = true; http_cfg.task_prio = 12; http_cfg.stack_in_ext = true; audio_element_handle_t http_stream_reader = http_stream_init(&http_cfg); esp_audio_input_stream_add(player, http_stream_reader); audio_decoder_t auto_decode[] = { DEFAULT_ESP_MP3_DECODER_CONFIG(), DEFAULT_ESP_WAV_DECODER_CONFIG(), DEFAULT_ESP_AAC_DECODER_CONFIG(), DEFAULT_ESP_M4A_DECODER_CONFIG(), DEFAULT_ESP_TS_DECODER_CONFIG(), }; esp_decoder_cfg_t auto_dec_cfg = DEFAULT_ESP_DECODER_CONFIG(); esp_audio_codec_lib_add(player, AUDIO_CODEC_TYPE_DECODER, esp_decoder_init(&auto_dec_cfg, auto_decode, 5)); // Create writers and add to esp_audio i2s_stream_cfg_t i2s_writer = I2S_STREAM_CFG_DEFAULT(); i2s_writer.type = AUDIO_STREAM_WRITER; i2s_writer.stack_in_ext = true; i2s_writer.task_core = 1; audio_element_handle_t i2s_stream_writer = i2s_stream_init(&i2s_writer); i2s_stream_set_clk(i2s_stream_writer, 48000, 16, 2); esp_audio_output_stream_add(player, i2s_stream_writer); // Set default volume esp_audio_vol_set(player, 35); } static void start_dlna() { const ssdp_service_t ssdp_service[] = { { DLNA_DEVICE_UUID, "upnp:rootdevice", NULL }, { DLNA_DEVICE_UUID, "urn:schemas-upnp-org:device:MediaRenderer:1", NULL }, { DLNA_DEVICE_UUID, "urn:schemas-upnp-org:service:ConnectionManager:1", NULL }, { DLNA_DEVICE_UUID, "urn:schemas-upnp-org:service:RenderingControl:1", NULL }, { DLNA_DEVICE_UUID, "urn:schemas-upnp-org:service:AVTransport:1", NULL }, { NULL, NULL, NULL }, }; ssdp_config_t ssdp_config = SSDP_DEFAULT_CONFIG(); ssdp_config.udn = DLNA_UNIQUE_DEVICE_NAME; ssdp_config.location = "http://${ip}"DLNA_ROOT_PATH; esp_ssdp_start(&ssdp_config, ssdp_service); static httpd_handle_t httpd = NULL; httpd_config_t httpd_config = HTTPD_DEFAULT_CONFIG(); httpd_config.max_uri_handlers = 25; httpd_config.stack_size = 6 * 1024; if (httpd_start(&httpd, &httpd_config) != ESP_OK) { ESP_LOGI(TAG, "Error starting httpd"); } extern const uint8_t logo_png_start[] asm("_binary_logo_png_start"); extern const uint8_t logo_png_end[] asm("_binary_logo_png_end"); dlna_config_t dlna_config = { .friendly_name = "ESP32 MD (ESP32 Renderer)", .uuid = (const char *)DLNA_DEVICE_UUID, .logo = { .mime_type = "image/png", .data = (const char *)logo_png_start, .size = logo_png_end - logo_png_start, }, .httpd = httpd, .httpd_port = httpd_config.server_port, .renderer_req = renderer_request, .root_path = DLNA_ROOT_PATH, .device_list = false }; dlna_handle = esp_dlna_start(&dlna_config); ESP_LOGI(TAG, "DLNA Started..."); } void app_main() { esp_log_level_set("*", ESP_LOG_INFO); esp_log_level_set(TAG, ESP_LOG_INFO); esp_log_level_set("AUDIO_ELEMENT", ESP_LOG_WARN); esp_log_level_set("AUDIO_PIPELINE", ESP_LOG_ERROR); esp_log_level_set("ESP_AUDIO_CTRL", ESP_LOG_WARN); media_lib_add_default_adapter(); esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 0)) ESP_ERROR_CHECK(esp_netif_init()); #else tcpip_adapter_init(); #endif esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG(); esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg); periph_wifi_cfg_t wifi_cfg = { .wifi_config.sta.ssid = "WiFi_8G", .wifi_config.sta.password = "IIll1122", }; esp_periph_handle_t wifi_handle = periph_wifi_init(&wifi_cfg); esp_periph_start(set, wifi_handle); periph_wifi_wait_for_connected(wifi_handle, portMAX_DELAY); audio_player_init(); esp_audio_callback_set(player, player_event_handler, NULL); start_dlna(); } 下载地址:我的下载_个人中心- - 电子工程世界EEWORLD 五、作品功能演示视频 因为需要安卓手机的酷狗音乐app,我使用的是苹果的,手上暂时,后续补上   六、项目总结 通过本项目,我们构建了一个基于esp32wifi音频传输模块使有线音响赋值无限“意义”。

  • 2024-09-04
  • 发表了主题帖: 2024 DigiKey 创意大赛】之esp32开发环境搭建

    距离收到板子已经快有一个月了,最近一直苦于这个开发环境的搭建,在公司电脑实现了vscode开发环境的搭建,在自己电脑上死活不行。暂且记分享下搭建开发环境的步骤吧。 之前没使用过这个开发环境,网上查找信息了解到安装离线包可以使用于是折腾了2天发现一个问题,通过离线包安装IDF环境可以用,直接使用win10 的命令行,在需要编译的工程目录下直接依次输入以下命令可以完成,工程配置,编译 ,烧录。(使用s3不需要按住boot烧录 使用esp32则需要按住) idf.py set-target esp32s3 选择芯片 idf.py menuconfig 配置 idf.py build 编译 idf.py -p COM39 flash 烧录 idf.py -p COM39 -b 460800 flash 烧录 idf.py -p COM39monitor 监视 但是在使用ADF时候就出问题,过程很复杂没解决,出现git clone 的问题参考这篇文章解决问题吧:ESP32 ADF windows开发环境搭建 适配ADF到ESP32A1S_esp-adf gitmodules-CSDN博客。 关于git clone 问题还有一个解决办法:使用官方工具esp-gitee-tools,具体方法 1.先从gitee上拉取辅助包esp-gitee-tools git clone https://gitee.com/EspressifSystems/esp-gitee-tools.git 2.接着我们来拉取esp-adf,记住先只拉取esp-adf(esp-idf同理),不包含子模块 git clone https://github.com/espressif/esp-adf.git 3.通过esp-gitee-tools来更新esp-idf(包括子模块) cd esp-gitee-tools ./submodule-update.sh ~/自己实际要存放的路径/esp-adf   ESP-IDF、ESP-ADF安装与配置-CSDN博客  本来不想使用vs code。 没办法使用vscode安装了一个插件,然后才跑通里面的例程,但是还有个别的没跑通。 安装方法参考:基于 VScode 搭建ESP32开发环境 esp-idf_visual studio code连接esp32-CSDN博客  在vscode是里面可以选择不在线安装,可以先离线安装好后,在使用vscode插件来找到你安装的路径(第一步骤是在线安装,第三个选项就是选择离线包)。它会自动扫描的安装文件 在使用里面demo时候有一个报错: E (3045) MEDIA_OS: Not found right xTaskCreateRestrictedPinnedToCore. Please enter IDF-PATH with "cd $IDF_PATH" and apply the IDF patch with "git apply $ADF_PATH/idf_patches/idf_v3.3_freertos.patch" first E (3065) AUDIO_THREAD: Error creating RestrictedPinnedToCore media_task E (3075) ESP_AUDIO_CTRL: Error create media_task 解决办法: git apply $ADF_PATH/idf_patches/idf_v3.3_freertos.patch 补丁路径:xx/esp_adf/idf_patches 然后就可以找一个demo使用开头的方法编译下载进去了。 网上使用esp-idf的很多使用esp-adf就很少,因为我这个项目使用的音频相关的得需要adf这个框架,总之这个环境搭建的很麻烦。                      

  • 2024-08-07
  • 发表了主题帖: 【2024 DigiKey 创意大赛】之esp32-s3-lcd开箱

      经过几天的焦急等待终于拿到esp32-s3-lcd开发板,那么一睹这个板子的风采吧 首先是他经美的外包装(看是多么的亮眼)   都已经迫不及待的打开他了。         这个做工还是相当的可以的。上电开下效果吧:   出场自带了两个演示的demo ,一个是语音控制,一个智能家居的ui控制很nice   这个界面果然很nice,即能控制,还可以切换主题,可玩性还是很高的。对了还有一个传感器,这个包装可是可以的:  完事具备下一步就是开干,期待我的成品吧    

最近访客

< 1/1 >

统计信息

已有3人来访过

  • 芯积分:24
  • 好友:--
  • 主题:3
  • 回复:0

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言