V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
horou
V2EX  ›  程序员

做音频频率播放动效一次应该喂多少采样数据

  •  
  •   horou · 254 天前 · 1035 次点击
    这是一个创建于 254 天前的主题,其中的信息可能已经有所发展或是发生改变。

    搞了搞音频的频率动效,一次应该用多少长度的采样数据进行 fft 计算合适

    还有就是为啥每次计算出的数据前面一截(低 hz 的)总是一柱擎天呢

    13 条回复    2023-08-22 15:05:25 +08:00
    billlee
        1
    billlee  
       254 天前 via Android
    第一个柱子是直流分量,是不是值域映射错了,应该是 [-1.0, 1.0].
    horou
        2
    horou  
    OP
       254 天前
    @billlee 不只是第一个数据,前面几个都是,值我检查了,没映射错,传的采样数据是 -1.0 到 1.0 ,计算出来的 FrequencyValue 是 0.0 到 1.0
    horou
        3
    horou  
    OP
       254 天前
    @billlee
    ![Imgur]( https://imgur.com/MI62vkq.png)
    这是现在的效果
    billlee
        4
    billlee  
       254 天前 via Android
    图上没有坐标轴,用的是对数坐标吗?
    ranaanna
        5
    ranaanna  
       253 天前
    取决于你的计算平台的能力吧,计算时间限制下当然是越多越好喽。另外最好是加个 Hamming 窗来减少旁瓣。另外结果似乎也不对吧,如果画出的是频谱的幅值,不管怎么样应该是个偶函数吧,各频点幅度一般也不应该都落在 0 到 1 之间
    xiangyuecn
        6
    xiangyuecn  
       253 天前   ❤️ 1
    根据需求来,每次计算输入的采样数记为 fftSize ,比如 fftSize=1024 ; fft 计算后的结果只需要取一半,共 512 个分频率

    音频的采样率决定了频率上限,比如 sampleRate=48000 ,最大频率为 sampleRate/2=24KHz ; 512 个分频率均分这 24K ,绘制频谱图的时候相当于 x 轴,每个刻度间隔为 24000/512=46.875Hz

    所以,固定了一个 fftSize 的时候,sampleRate 变来变去时会影响 x 轴,48000 中间位置是 12KHz ,换做 16000 时中间位置是 4KHz ,因此 fftSize 的大小得根据 sampleRate 大小来定

    fftSize 具体取多大,看你需求,fftSize 越大绘制的频谱越精细,每次输入的时域数据越长(时间越长),可以使用滑动窗口来解决新数据量不够的问题,比如每次只取 50ms 新数据和老数据一起计算,很大的 fftSize 可以做到很高的帧率

    -------

    前面一截总是一柱擎天,大部分情况下属正常,声音能量主要集中在低频部分,高频部分比较少。但也不排除你的 fft 代码有问题,算出来的结果是错的。
    horou
        8
    horou  
    OP
       253 天前
    @ranaanna 用了 hann window


    @xiangyuecn 感谢大佬详细解答,还有个问题,你第二点说的意思是只固定取那些 hz 的数据吗,还是计算这个 hz 周围的平均值

    口头说不是很能表达明白意思,我直接上我的代码吧

    代码地址: https://gist.github.com/rust-play/44f0864a5855d164e919aaa0ff367b8f

    打包好的程序:链接: https://pan.baidu.com/s/1Tn-NWmTjIU3kLe-NnSNesw?pwd=oct6
    提取码:oct6
    直接把音乐文件拖到 exe 上执行

    大佬帮我看看到底效果到底是差在哪个地方
    xiangyuecn
        9
    xiangyuecn  
       253 天前
    自己研究研究吧,fft 是比较难学,现在看到代码就脑壳疼😂 相同的 fftSize+sampleRate 每次计算出来的每一位结果都对应固定的频率值,相当于 x 轴( Hz ),y 轴为每一位的值(振幅),每次计算出每个频率的振幅会发生变化,就形成了动画
    bug123
        10
    bug123  
       253 天前
    你那个图没啥问题的,每次计算最近的 512 采样点就可以,另外可以把幅度值转成 dbfs ,另外用 Hanning 窗比较好吧,不是 Hamming
    horou
        11
    horou  
    OP
       253 天前
    @xiangyuecn 好的,感谢大佬的解答加深了我对这部分的理解。
    horou
        12
    horou  
    OP
       253 天前
    @bug123 谢谢解答,现在我用的就是 hanning ,另外我这个计算出来的值是做了 Normalization 的,还有把幅度值转 dbfs 有什么好处呢,对这个不太懂。
    bug123
        13
    bug123  
       253 天前
    @horou 没啥特别好处,不转化也可以
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2198 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 15:50 · PVG 23:50 · LAX 08:50 · JFK 11:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.