From 50771c571da2b089188e85392c236ba4d95dd934 Mon Sep 17 00:00:00 2001 From: moecinnamo Date: Wed, 10 Sep 2025 17:29:05 +0800 Subject: [PATCH] modify AddAudioData --- main/.DS_Store | Bin 8196 -> 8196 bytes main/CMakeLists.txt | 2 +- main/application.cc | 91 +++++++++--------- main/boards/common/esp32_music.cc | 149 +++++++++++++----------------- 4 files changed, 114 insertions(+), 128 deletions(-) diff --git a/main/.DS_Store b/main/.DS_Store index 9d0c75c6c72e861fa9125291720bf69f0664b57e..15706c29205b058b322813355a71771dbdb5d13e 100644 GIT binary patch delta 43 zcmZp1XmOa}&nUSuU^hRjBm)Bj?_>c1$<3((i`XYN*lcE(_{Or?QuG|t#0Eoutput_sample_rate()) { - // ESP_LOGI(TAG, "Resampling music audio from %d to %d Hz", - // packet.sample_rate, codec->output_sample_rate()); - // 验证采样率参数 if (packet.sample_rate <= 0 || codec->output_sample_rate() <= 0) { ESP_LOGE(TAG, "Invalid sample rates: %d -> %d", @@ -804,51 +801,61 @@ void Application::AddAudioData(AudioStreamPacket&& packet) { return; } - std::vector resampled; - - if (packet.sample_rate > codec->output_sample_rate()) { - ESP_LOGI(TAG, "Music playback: Adjust the sampling rate from %d Hz switch to %d Hz", - codec->output_sample_rate(), packet.sample_rate); - - // 尝试动态切换采样率 - if (codec->SetOutputSampleRate(packet.sample_rate)) { - ESP_LOGI(TAG, "Successfully switched to music playback sampling rate: %d Hz", packet.sample_rate); - } else { - ESP_LOGW(TAG, "Unable to switch sampling rate, continue using current sampling rate: %d Hz", codec->output_sample_rate()); - } + // 尝试动态切换采样率 + if (codec->SetOutputSampleRate(packet.sample_rate)) { + ESP_LOGI(TAG, "Successfully switched to music playback sampling rate: %d Hz", packet.sample_rate); } else { - // 上采样:线性插值 - float upsample_ratio = codec->output_sample_rate() / static_cast(packet.sample_rate); - size_t expected_size = static_cast(pcm_data.size() * upsample_ratio + 0.5f); - resampled.reserve(expected_size); - - for (size_t i = 0; i < pcm_data.size(); ++i) { - // 添加原始样本 - resampled.push_back(pcm_data[i]); + ESP_LOGW(TAG, "Unable to switch sampling rate, continue using current sampling rate: %d Hz", codec->output_sample_rate()); + // 如果无法切换采样率,继续使用当前的采样率进行处理 + if (packet.sample_rate > codec->output_sample_rate()) { + // 下采样:简单丢弃部分样本 + float downsample_ratio = static_cast(packet.sample_rate) / codec->output_sample_rate(); + size_t expected_size = static_cast(pcm_data.size() / downsample_ratio + 0.5f); + std::vector resampled(expected_size); + size_t resampled_index = 0; - // 计算需要插值的样本数 - int interpolation_count = static_cast(upsample_ratio) - 1; - if (interpolation_count > 0 && i + 1 < pcm_data.size()) { - int16_t current = pcm_data[i]; - int16_t next = pcm_data[i + 1]; - for (int j = 1; j <= interpolation_count; ++j) { - float t = static_cast(j) / (interpolation_count + 1); - int16_t interpolated = static_cast(current + (next - current) * t); - resampled.push_back(interpolated); - } - } else if (interpolation_count > 0) { - // 最后一个样本,直接重复 - for (int j = 1; j <= interpolation_count; ++j) { - resampled.push_back(pcm_data[i]); + for (size_t i = 0; i < pcm_data.size(); ++i) { + if (i % static_cast(downsample_ratio) == 0) { + resampled[resampled_index++] = pcm_data[i]; } } + + pcm_data = std::move(resampled); + ESP_LOGI(TAG, "Downsampled %d -> %d samples (ratio: %.2f)", + pcm_data.size(), resampled.size(), downsample_ratio); + } else if (packet.sample_rate < codec->output_sample_rate()) { + // 上采样:线性插值 + float upsample_ratio = codec->output_sample_rate() / static_cast(packet.sample_rate); + size_t expected_size = static_cast(pcm_data.size() * upsample_ratio + 0.5f); + std::vector resampled(expected_size); + + for (size_t i = 0; i < pcm_data.size(); ++i) { + // 添加原始样本 + resampled[i * static_cast(upsample_ratio)] = pcm_data[i]; + + // 计算需要插值的样本数 + int interpolation_count = static_cast(upsample_ratio) - 1; + if (interpolation_count > 0 && i + 1 < pcm_data.size()) { + int16_t current = pcm_data[i]; + int16_t next = pcm_data[i + 1]; + for (int j = 1; j <= interpolation_count; ++j) { + float t = static_cast(j) / (interpolation_count + 1); + int16_t interpolated = static_cast(current + (next - current) * t); + resampled[i * static_cast(upsample_ratio) + j] = interpolated; + } + } else if (interpolation_count > 0) { + // 最后一个样本,直接重复 + for (int j = 1; j <= interpolation_count; ++j) { + resampled[i * static_cast(upsample_ratio) + j] = pcm_data[i]; + } + } + } + + pcm_data = std::move(resampled); + ESP_LOGI(TAG, "Upsampled %d -> %d samples (ratio: %.2f)", + pcm_data.size() / static_cast(upsample_ratio), pcm_data.size(), upsample_ratio); } - - ESP_LOGI(TAG, "Upsampled %d -> %d samples (ratio: %.2f)", - pcm_data.size(), resampled.size(), upsample_ratio); } - - pcm_data = std::move(resampled); } // 确保音频输出已启用 diff --git a/main/boards/common/esp32_music.cc b/main/boards/common/esp32_music.cc index b0ab54a..da1c786 100644 --- a/main/boards/common/esp32_music.cc +++ b/main/boards/common/esp32_music.cc @@ -330,9 +330,8 @@ bool Esp32Music::Download(const std::string &song_name, const std::string &artis current_song_name_ = song_name; // 第一步:请求stream_pcm接口获取音频信息 - std::string base_url = "https://music.miao-lab.top"; - // std::string full_url = base_url + "/stream_pcm?song=" + url_encode(song_name) + "&artist=" + url_encode(artist_name); - std::string full_url = base_url + "/api?msg=" + url_encode(song_name); + std::string base_url = "http://http-embedded-music.miao-lab.top:2233"; + std::string full_url = base_url + "/stream_pcm?song=" + url_encode(song_name) + "&artist=" + url_encode(artist_name); ESP_LOGI(TAG, "Request URL: %s", full_url.c_str()); @@ -383,103 +382,83 @@ bool Esp32Music::Download(const std::string &song_name, const std::string &artis cJSON *response_json = cJSON_Parse(last_downloaded_data_.c_str()); if (response_json) { - // 提取data数组 - cJSON *data_array = cJSON_GetObjectItem(response_json, "data"); + // 提取关键信息 + cJSON *artist = cJSON_GetObjectItem(response_json, "artist"); + cJSON *title = cJSON_GetObjectItem(response_json, "title"); + cJSON *audio_url = cJSON_GetObjectItem(response_json, "audio_url"); + cJSON *lyric_url = cJSON_GetObjectItem(response_json, "lyric_url"); - if (cJSON_IsArray(data_array)) + if (cJSON_IsString(artist)) { - cJSON *item = nullptr; - cJSON *min_item = nullptr; - int min_num = INT_MAX; - // 遍历data数组以找到最小num的项 - cJSON_ArrayForEach(item, data_array) + ESP_LOGI(TAG, "Artist: %s", artist->valuestring); + } + if (cJSON_IsString(title)) + { + ESP_LOGI(TAG, "Title: %s", title->valuestring); + } + + // 检查audio_url是否有效 + if (cJSON_IsString(audio_url) && audio_url->valuestring && strlen(audio_url->valuestring) > 0) + { + ESP_LOGI(TAG, "Audio URL path: %s", audio_url->valuestring); + + // 第二步:拼接完整的音频下载URL,确保对audio_url进行URL编码 + std::string audio_path = audio_url->valuestring; + + current_music_url_ = audio_path; + + ESP_LOGI(TAG, "喵波音律QQ交流群:865754861"); + ESP_LOGI(TAG, "Starting streaming playback for: %s", song_name.c_str()); + song_name_displayed_ = false; // 重置歌名显示标志 + StartStreaming(current_music_url_); + + // 处理歌词URL - 只有在歌词显示模式下才启动歌词 + if (cJSON_IsString(lyric_url) && lyric_url->valuestring && strlen(lyric_url->valuestring) > 0) { - cJSON *num = cJSON_GetObjectItem(item, "num"); - if (cJSON_IsNumber(num) && num->valueint < min_num) - { - min_num = num->valueint; - min_item = item; - } - } - if (min_item) - { - // 提取关键信息 - cJSON *artist = cJSON_GetObjectItem(min_item, "singer"); - cJSON *title = cJSON_GetObjectItem(min_item, "song"); - cJSON *music_url = cJSON_GetObjectItem(min_item, "music_url"); - cJSON *audio_url = music_url ? cJSON_GetObjectItem(music_url, "audition") : nullptr; - cJSON *lyric = cJSON_GetObjectItem(min_item, "lyric"); - cJSON *lyric_url = lyric ? cJSON_GetObjectItem(lyric, "lrc") : nullptr; - if (cJSON_IsString(artist)) - { - ESP_LOGI(TAG, "Artist: %s", artist->valuestring); - } - if (cJSON_IsString(title)) - { - ESP_LOGI(TAG, "Title: %s", title->valuestring); - } - // 检查audio_url是否有效 - if (cJSON_IsString(audio_url) && audio_url->valuestring && strlen(audio_url->valuestring) > 0) - { - ESP_LOGI(TAG, "Audio URL path: %s", audio_url->valuestring); + std::string lyric_path = lyric_url->valuestring; + current_lyric_url_ = lyric_path; - // 第二步:获取audio_url并开始流式播放 - current_music_url_ = audio_url->valuestring; + // 根据显示模式决定是否启动歌词 + if (display_mode_ == DISPLAY_MODE_LYRICS) + { + ESP_LOGI(TAG, "Loading lyrics for: %s (lyrics display mode)", song_name.c_str()); - ESP_LOGI(TAG, "喵波音律QQ交流群:865754861"); - ESP_LOGI(TAG, "Starting streaming playback for: %s", song_name.c_str()); - song_name_displayed_ = false; // 重置歌名显示标志 - StartStreaming(current_music_url_); - - // 处理歌词URL - 只有在歌词显示模式下才启动歌词 - if (cJSON_IsString(lyric_url) && lyric_url->valuestring && strlen(lyric_url->valuestring) > 0) + // 启动歌词下载和显示 + if (is_lyric_running_) { - // 直接返回歌词URL - current_lyric_url_ = lyric_url->valuestring; - - // 根据显示模式决定是否启动歌词 - if (display_mode_ == DISPLAY_MODE_LYRICS) + is_lyric_running_ = false; + if (lyric_thread_.joinable()) { - ESP_LOGI(TAG, "Loading lyrics for: %s (lyrics display mode)", song_name.c_str()); - - // 启动歌词下载和显示 - if (is_lyric_running_) - { - is_lyric_running_ = false; - if (lyric_thread_.joinable()) - { - lyric_thread_.join(); - } - } - - is_lyric_running_ = true; - current_lyric_index_ = -1; - lyrics_.clear(); - - lyric_thread_ = std::thread(&Esp32Music::LyricDisplayThread, this); - } - else - { - ESP_LOGI(TAG, "Lyric URL found but spectrum display mode is active, skipping lyrics"); + lyric_thread_.join(); } } - else - { - ESP_LOGW(TAG, "No lyric URL found for this song"); - } - cJSON_Delete(response_json); - return true; + is_lyric_running_ = true; + current_lyric_index_ = -1; + lyrics_.clear(); + + lyric_thread_ = std::thread(&Esp32Music::LyricDisplayThread, this); } else { - // audio_url为空或无效 - ESP_LOGE(TAG, "Audio URL not found or empty for song: %s", song_name.c_str()); - ESP_LOGE(TAG, "Failed to find music: 没有找到歌曲 '%s'", song_name.c_str()); - cJSON_Delete(response_json); - return false; + ESP_LOGI(TAG, "Lyric URL found but spectrum display mode is active, skipping lyrics"); } } + else + { + ESP_LOGW(TAG, "No lyric URL found for this song"); + } + + cJSON_Delete(response_json); + return true; + } + else + { + // audio_url为空或无效 + ESP_LOGE(TAG, "Audio URL not found or empty for song: %s", song_name.c_str()); + ESP_LOGE(TAG, "Failed to find music: 没有找到歌曲 '%s'", song_name.c_str()); + cJSON_Delete(response_json); + return false; } } else