zl程序教程

您现在的位置是:首页 >  Python

当前栏目

用Python验证人耳能分辨的拍频上限

2023-03-20 14:55:18 时间

有些同学没能区分拍频和人耳能听到的声音频率下限20Hz的区别,在群里发表了疑惑。虽然这个问题很快就解决了,但另一个问题产生了——人耳能不能分辨7Hz以上的拍? 为了验证,首先要制作一个可以产生并合成任意频率的发生器。这个很自然地就想用程序控制扬声器,但是我只有Python的环境……

老师:可调频的发生器+电磁振荡喇叭 这个真没有,除非拆了收音机。

也没有,还得拆收音机。 我还是用python做音频输出吧。参考了python实现简单的声音文件读写,花了几分钟把这个东西做出来了。 运行后输入a、b两个波的频率,程序会将a、b频率的两个简谐波合成并保存在"a b.wav"内。

import wave
import numpy as np
import scipy.signal as signal
framerate = 44100
time = 20
t = np.arange(0, time, 1.0/framerate)
a = int(input())
b = int(input())
l = [0]*framerate*time
for i in range(framerate*time):
    l[i] = (np.cos(2*np.pi*a*t[i])+np.cos(2*np.pi*b*t[i]))*5000
    if i%100000 == 0:
        print(i)
wave_data = np.array(l)
wave_data = wave_data.astype(np.short)
f = wave.open(str(a)+" "+str(b)+".wav", "wb")
f.setnchannels(1)
f.setsampwidth(2)
f.setframerate(framerate)
f.writeframes(wave_data.tostring())
f.close()

合成波最快的方式应该是快速傅里叶,但是我懒得写。就这样硬算,20s的音频10秒就能处理完。况且由于笔记本烧了,现在用的台式机CPU是AthlonIIX4 640,前两天几十块钱买的,3G主频超到3.75G。大部分同学用的电脑肯定比我强十倍,懒得写FFT。 受限于声卡和播放设备,两个频率也不宜设置的太高或者太低。 当两列波频率差很小时,可以明显听到强弱变化,就是所谓的拍:

当两列波频率相差较大的时候,拍就很难分辨了,如题图:

那么能分辨的最高拍频是多少?我做了测验,个人认为30Hz的拍频还是可以分辨的,甚至题中的59Hz也勉强可以分辨。这个数值远大于7Hz,我认为主要原因有两点:

  1. 程序合成的是简谐波,自然界的声音都带有音色,波形很复杂,并不是简谐波。这一点可以通过改变波形验证。
  2. 采用的扬声器对声音输出做了修改。大部分耳机/音响都会对特征曲线调整以更符合人的听觉感官,不排除在这个过程中声音有所改变。