modify AddAudioData
This commit is contained in:
BIN
main/.DS_Store
vendored
BIN
main/.DS_Store
vendored
Binary file not shown.
@@ -19,7 +19,7 @@ set(SOURCES "audio/audio_codec.cc"
|
|||||||
"protocols/websocket_protocol.cc"
|
"protocols/websocket_protocol.cc"
|
||||||
"mcp_server.cc"
|
"mcp_server.cc"
|
||||||
"system_info.cc"
|
"system_info.cc"
|
||||||
"application.cc"
|
|
||||||
"ota.cc"
|
"ota.cc"
|
||||||
"settings.cc"
|
"settings.cc"
|
||||||
"device_state_event.cc"
|
"device_state_event.cc"
|
||||||
|
|||||||
@@ -794,9 +794,6 @@ void Application::AddAudioData(AudioStreamPacket&& packet) {
|
|||||||
|
|
||||||
// 检查采样率是否匹配,如果不匹配则进行简单重采样
|
// 检查采样率是否匹配,如果不匹配则进行简单重采样
|
||||||
if (packet.sample_rate != codec->output_sample_rate()) {
|
if (packet.sample_rate != codec->output_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) {
|
if (packet.sample_rate <= 0 || codec->output_sample_rate() <= 0) {
|
||||||
ESP_LOGE(TAG, "Invalid sample rates: %d -> %d",
|
ESP_LOGE(TAG, "Invalid sample rates: %d -> %d",
|
||||||
@@ -804,51 +801,61 @@ void Application::AddAudioData(AudioStreamPacket&& packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int16_t> resampled;
|
// 尝试动态切换采样率
|
||||||
|
if (codec->SetOutputSampleRate(packet.sample_rate)) {
|
||||||
if (packet.sample_rate > codec->output_sample_rate()) {
|
ESP_LOGI(TAG, "Successfully switched to music playback sampling rate: %d Hz", packet.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());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// 上采样:线性插值
|
ESP_LOGW(TAG, "Unable to switch sampling rate, continue using current sampling rate: %d Hz", codec->output_sample_rate());
|
||||||
float upsample_ratio = codec->output_sample_rate() / static_cast<float>(packet.sample_rate);
|
// 如果无法切换采样率,继续使用当前的采样率进行处理
|
||||||
size_t expected_size = static_cast<size_t>(pcm_data.size() * upsample_ratio + 0.5f);
|
if (packet.sample_rate > codec->output_sample_rate()) {
|
||||||
resampled.reserve(expected_size);
|
// 下采样:简单丢弃部分样本
|
||||||
|
float downsample_ratio = static_cast<float>(packet.sample_rate) / codec->output_sample_rate();
|
||||||
for (size_t i = 0; i < pcm_data.size(); ++i) {
|
size_t expected_size = static_cast<size_t>(pcm_data.size() / downsample_ratio + 0.5f);
|
||||||
// 添加原始样本
|
std::vector<int16_t> resampled(expected_size);
|
||||||
resampled.push_back(pcm_data[i]);
|
size_t resampled_index = 0;
|
||||||
|
|
||||||
// 计算需要插值的样本数
|
for (size_t i = 0; i < pcm_data.size(); ++i) {
|
||||||
int interpolation_count = static_cast<int>(upsample_ratio) - 1;
|
if (i % static_cast<size_t>(downsample_ratio) == 0) {
|
||||||
if (interpolation_count > 0 && i + 1 < pcm_data.size()) {
|
resampled[resampled_index++] = pcm_data[i];
|
||||||
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<float>(j) / (interpolation_count + 1);
|
|
||||||
int16_t interpolated = static_cast<int16_t>(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]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<float>(packet.sample_rate);
|
||||||
|
size_t expected_size = static_cast<size_t>(pcm_data.size() * upsample_ratio + 0.5f);
|
||||||
|
std::vector<int16_t> resampled(expected_size);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < pcm_data.size(); ++i) {
|
||||||
|
// 添加原始样本
|
||||||
|
resampled[i * static_cast<size_t>(upsample_ratio)] = pcm_data[i];
|
||||||
|
|
||||||
|
// 计算需要插值的样本数
|
||||||
|
int interpolation_count = static_cast<int>(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<float>(j) / (interpolation_count + 1);
|
||||||
|
int16_t interpolated = static_cast<int16_t>(current + (next - current) * t);
|
||||||
|
resampled[i * static_cast<size_t>(upsample_ratio) + j] = interpolated;
|
||||||
|
}
|
||||||
|
} else if (interpolation_count > 0) {
|
||||||
|
// 最后一个样本,直接重复
|
||||||
|
for (int j = 1; j <= interpolation_count; ++j) {
|
||||||
|
resampled[i * static_cast<size_t>(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<size_t>(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保音频输出已启用
|
// 确保音频输出已启用
|
||||||
|
|||||||
@@ -330,9 +330,8 @@ bool Esp32Music::Download(const std::string &song_name, const std::string &artis
|
|||||||
current_song_name_ = song_name;
|
current_song_name_ = song_name;
|
||||||
|
|
||||||
// 第一步:请求stream_pcm接口获取音频信息
|
// 第一步:请求stream_pcm接口获取音频信息
|
||||||
std::string base_url = "https://music.miao-lab.top";
|
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);
|
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);
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Request URL: %s", full_url.c_str());
|
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());
|
cJSON *response_json = cJSON_Parse(last_downloaded_data_.c_str());
|
||||||
if (response_json)
|
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;
|
ESP_LOGI(TAG, "Artist: %s", artist->valuestring);
|
||||||
cJSON *min_item = nullptr;
|
}
|
||||||
int min_num = INT_MAX;
|
if (cJSON_IsString(title))
|
||||||
// 遍历data数组以找到最小num的项
|
{
|
||||||
cJSON_ArrayForEach(item, data_array)
|
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");
|
std::string lyric_path = lyric_url->valuestring;
|
||||||
if (cJSON_IsNumber(num) && num->valueint < min_num)
|
current_lyric_url_ = lyric_path;
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
// 第二步:获取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());
|
if (is_lyric_running_)
|
||||||
song_name_displayed_ = false; // 重置歌名显示标志
|
|
||||||
StartStreaming(current_music_url_);
|
|
||||||
|
|
||||||
// 处理歌词URL - 只有在歌词显示模式下才启动歌词
|
|
||||||
if (cJSON_IsString(lyric_url) && lyric_url->valuestring && strlen(lyric_url->valuestring) > 0)
|
|
||||||
{
|
{
|
||||||
// 直接返回歌词URL
|
is_lyric_running_ = false;
|
||||||
current_lyric_url_ = lyric_url->valuestring;
|
if (lyric_thread_.joinable())
|
||||||
|
|
||||||
// 根据显示模式决定是否启动歌词
|
|
||||||
if (display_mode_ == DISPLAY_MODE_LYRICS)
|
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Loading lyrics for: %s (lyrics display mode)", song_name.c_str());
|
lyric_thread_.join();
|
||||||
|
|
||||||
// 启动歌词下载和显示
|
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
ESP_LOGW(TAG, "No lyric URL found for this song");
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON_Delete(response_json);
|
is_lyric_running_ = true;
|
||||||
return true;
|
current_lyric_index_ = -1;
|
||||||
|
lyrics_.clear();
|
||||||
|
|
||||||
|
lyric_thread_ = std::thread(&Esp32Music::LyricDisplayThread, this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// audio_url为空或无效
|
ESP_LOGI(TAG, "Lyric URL found but spectrum display mode is active, skipping lyrics");
|
||||||
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
|
||||||
|
{
|
||||||
|
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
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user