You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python检测歌曲音频频率,实现节奏游戏的圆圈定位?

用Python实现节奏游戏的频率定位功能

完全可以用Python实现这个需求,核心是提取音频的频率特征,再映射到屏幕象限位置,下面是具体的实现思路和代码示例:

1. 音频频率提取

首先需要解析音频文件,提取分帧的频率数据。常用的专业音频处理库是librosa,适合快速提取频谱特征。

示例:提取音频帧的频率峰值

import librosa
import numpy as np

# 加载目标音频文件
audio_path = "your_song.mp3"
y, sr = librosa.load(audio_path, sr=None)  # y为音频波形数据,sr为采样率

# 用短时傅里叶变换生成频谱
n_fft = 2048
hop_length = 512  # 帧移,控制节奏检测的灵敏度
stft = librosa.stft(y, n_fft=n_fft, hop_length=hop_length)
spectrogram = np.abs(stft)

# 获取每帧能量最高的频率(峰值频率)
freqs = librosa.fft_frequencies(sr=sr, n_fft=n_fft)
peak_freqs = []
for frame in spectrogram.T:
    peak_idx = np.argmax(frame)
    peak_freq = freqs[peak_idx]
    peak_freqs.append(peak_freq)

2. 频率到屏幕位置的映射

将提取到的频率值对应到预设的屏幕象限,需要先定义频率区间和坐标规则:

  • 假设屏幕分辨率为(1920, 1080),可根据实际调整
  • 示例规则:低频(0-500Hz)对应右上象限,高频(5000Hz以上)对应左上象限,中间频率分配到下半区

示例:频率转坐标的映射函数

def freq_to_position(freq, screen_width, screen_height):
    # 定义频率分界值
    low_threshold = 500
    high_threshold = 5000
    
    # 计算X坐标:高频偏左,低频偏右,中间频率线性过渡
    if freq <= low_threshold:
        x = screen_width * 0.75
    elif freq >= high_threshold:
        x = screen_width * 0.25
    else:
        x = screen_width * (0.75 - (freq - low_threshold)/(high_threshold - low_threshold)*0.5)
    
    # 计算Y坐标:高低频在上半区,中间频率在下半区
    if freq <= low_threshold or freq >= high_threshold:
        y = screen_height * 0.25
    else:
        y = screen_height * 0.75
    
    # 加入随机偏移避免位置过于固定,提升游戏趣味性
    x += np.random.randint(-50, 50)
    y += np.random.randint(-50, 50)
    
    # 确保坐标不超出屏幕范围
    x = max(0, min(x, screen_width))
    y = max(0, min(y, screen_height))
    
    return (int(x), int(y))

3. 游戏框架整合

把音频处理和位置映射结合到游戏框架中,推荐用pygame实现2D界面:

示例:用pygame绘制对应位置的圆圈

import pygame

# 初始化pygame
pygame.init()
screen_width, screen_height = 1920, 1080
screen = pygame.display.set_mode((screen_width, screen_height))
clock = pygame.time.Clock()

# 这里复用前面提取的peak_freqs数据
# ... 省略加载音频和提取peak_freqs的代码 ...

frame_index = 0
running = True
while running:
    screen.fill((0, 0, 0))
    
    # 处理退出事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    
    # 逐帧更新圆圈位置并绘制
    if frame_index < len(peak_freqs):
        current_freq = peak_freqs[frame_index]
        circle_pos = freq_to_position(current_freq, screen_width, screen_height)
        pygame.draw.circle(screen, (255, 0, 0), circle_pos, 30)
        frame_index += 1
    
    pygame.display.flip()
    clock.tick(60)  # 控制游戏帧率

pygame.quit()

优化提示

  • 调整hop_length参数可以匹配歌曲的BPM,让圆圈出现时机更贴合节拍
  • 改用梅尔频谱替代原始频谱,提取的频率特征会更符合人耳听觉感知
  • 如果需要实时麦克风输入,可替换为pyaudio库捕获音频流并实时计算频率

内容的提问来源于stack exchange,提问作者Paker Vandy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 23:55:18