基于频谱图的歌曲识别故障:非起始片段无法匹配
解决音频片段非起始位置无法识别的问题
问题根源就是你定位到的那行截断代码:db_spectrogram = db_spectrogram[:, :target_length],这行直接把数据库里每首歌的频谱图砍成和目标片段一样长的开头部分,自然只能匹配起始位置的片段。
直接按下面的思路修改identify_song函数:
- 删掉那行截断代码,保留数据库歌曲的完整频谱图
- 计算每首歌频谱图的总列数,只要总长度大于等于目标片段长度,就用滑动窗口遍历所有可能的片段位置
- 对每个窗口截取的片段,和目标频谱图计算相似度,记录最高相似度对应的歌曲
给你个修改后的核心代码示例:
def identify_song(target_spectrogram, db_spectrograms): target_length = target_spectrogram.shape[1] max_similarity = -1 matched_song = None for song_name, db_spectrogram in db_spectrograms.items(): db_total_cols = db_spectrogram.shape[1] # 跳过比目标片段短的歌曲,没法匹配 if db_total_cols < target_length: continue # 遍历所有可能的起始列,滑动窗口截取片段 for start_col in range(db_total_cols - target_length + 1): # 截取当前窗口的频谱图片段 db_segment = db_spectrogram[:, start_col:start_col + target_length] # 这里用你原来的相似度计算逻辑,比如余弦相似度、MSE等 similarity = your_similarity_calculation(target_spectrogram, db_segment) # 更新最优匹配 if similarity > max_similarity: max_similarity = similarity matched_song = song_name return matched_song, max_similarity
如果觉得滑动窗口遍历太慢,可以加些优化:比如提前给频谱图做特征降维(比如提取峰值点),或者设置相似度阈值,一旦找到超过阈值的匹配就直接跳出循环,不用遍历所有窗口。
内容的提问来源于stack exchange,提问作者Cartu28
相关产品推荐
相关产品推荐

