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

如何使用Python计算WAV文件中声音的实时频率?

获取WAV文件实时播放时的频率(Hz)入门方案

核心思路

要实现播放过程中实时计算频率,不能一次性对整个音频文件做FFT,必须采用分帧处理:将音频切成连续的小块(帧),每处理完一帧就计算当前帧的频率,同时同步播放对应片段,兼顾实时性和频率精度。

必备工具

用Python实现的话,需要这几个库:

  • scipy.io.wavfile:读取WAV文件的采样率和音频数据
  • numpy:数值计算(FFT或自相关运算)
  • pyaudio:实时播放音频并同步获取待处理的音频帧

先安装依赖:

pip install numpy scipy pyaudio

入门代码示例(基于FFT的实时频率计算)

import numpy as np
from scipy.io import wavfile
import pyaudio

# 读取WAV文件
sample_rate, audio_data = wavfile.read("your_audio.wav")

# 处理立体声转单声道(如果是立体声的话)
if len(audio_data.shape) > 1:
    audio_data = np.mean(audio_data, axis=1)

# 归一化音频数据(转成float32,适配PyAudio)
audio_data = audio_data.astype(np.float32) / np.max(np.abs(audio_data))

# 分帧参数:帧长1024(可调,越短延迟越低但频率精度越差)
frame_size = 1024
num_frames = len(audio_data) // frame_size

# 初始化PyAudio
p = pyaudio.PyAudio()

# 打开播放流
stream = p.open(
    format=pyaudio.paFloat32,
    channels=1,
    rate=sample_rate,
    output=True
)

# 逐帧处理+播放
for i in range(num_frames):
    # 提取当前帧
    frame = audio_data[i*frame_size : (i+1)*frame_size]
    
    # 播放当前帧
    stream.write(frame.tobytes())
    
    # FFT计算频率
    fft_result = np.fft.fft(frame)
    fft_magnitude = np.abs(fft_result[:frame_size//2])  # 取正频率部分
    freq_axis = np.fft.fftfreq(frame_size, 1/sample_rate)[:frame_size//2]
    
    # 找到幅值最大的频率点(忽略直流分量)
    max_idx = np.argmax(fft_magnitude[1:]) + 1
    current_freq = freq_axis[max_idx]
    
    # 打印实时频率(可替换成你需要的后续处理)
    print(f"当前频率: {current_freq:.1f} Hz")

# 清理资源
stream.stop_stream()
stream.close()
p.terminate()

关键细节说明

  1. 分帧参数调整:

    • 帧长frame_size建议取2的幂(比如512、1024、2048),FFT计算更快
    • 采样率44100Hz下,1024帧对应约23ms延迟,平衡实时性和精度
  2. 频率计算方法选择:

    • 上述代码用FFT,适合多频混合信号,能得到占比最高的频率
    • 如果是单音信号(比如乐器单音),可以用自相关法,计算量更小、延迟更低,示例代码片段:
      # 自相关法计算单频信号频率
      def get_freq_autocorrelation(frame, sample_rate):
          corr = np.correlate(frame, frame, mode='full')
          corr = corr[len(corr)//2:]
          # 找到第一个峰值(跳过直流分量的峰值)
          peak_idx = np.argmax(corr[10:]) + 10
          period = peak_idx / sample_rate
          return 1 / period if period !=0 else 0
      
    • 调用时替换FFT部分即可:current_freq = get_freq_autocorrelation(frame, sample_rate)
  3. 注意事项:

    • 如果WAV文件是16位整数格式,需要先转成float32再归一化,避免播放失真
    • 实时处理时要确保计算速度快于播放速度,否则会卡顿,可适当减小帧长或优化计算逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 05:35:14