如何通过 FFT 相移最小化周期性波形的峰峰值幅度?

信息处理 fft 声音的 阶段
2022-02-21 03:30:49

对于我的一个音乐项目,我正在播放周期性音频信号(通过循环单个周期)。不幸的是,我的一个波形听起来太安静了(即使在最大音量下)。

我正在尝试使用 FFT 来获得谐波强度,然后对每个谐波进行相移以最小化峰峰值幅度,然后放大信号。

是否有任何算法可以找到最佳相移,或者我应该使用scipy.optimize.basinhopping(或生成数千个随机相位)以获得近似结果?

2个回答

有用于确定低峰值因子信号的算法,例如:

“低自相关 (Corresp.) 的低峰值因子信号和二进制序列的合成”,M. Schroeder,1970

我已将其用于平谱信号以最小化峰峰值幅度。

但是我认为这可能是一个 XY 问题。您对可以给信号引入多少失真有限制吗?您是否尝试过使用动态范围压缩算法?有一些限制算法可以显着增加 RMS 幅度,而不会引入明显的音频伪影。

我认为 FFT 不是解决此问题的合适工具。如果您知道波形中谐波的幅度,我认为最好的方法是粗略搜索具有最小最大值的组合。一旦找到,您可以进行梯度搜索以获得最佳值,或者可能更容易,在最佳粗略搜索结果附近进行另一次蛮力精细搜索。当您找到具有最低最大值的组合(也不要忘记包括波谷)时,您可以将所有幅度相乘以使峰值达到削波极限。

希望这可以帮助,

赛德

================================================

跟进:

我很好奇用 Python 编写代码。干得好:


从数组导入数组
将 numpy 导入为 np
将 matplotlib.pyplot 导入为 plt

#=================================================
定义主():

# -  -  设置

        N = 200

        RPS = 2 * np.pi / N # 每个样本的弧度

        P = array( 'd', [0,0,0,0,0] ) # 阶段
        A = array( 'd', [0,1,1,1,1] ) # 幅度

#---- 粗略搜索

        步长 = 2 * np.pi / 20

        MP = FindSmallestPeakPhases(RPS, N, A, P, Step)

#---- 精细搜索

        步长 /= 20

        MP = FindSmallestPeakPhases(RPS, N, A, MP, Step)

#---- 更精细的搜索

        步长 /= 20

        MP = FindSmallestPeakPhases(RPS, N, A, MP, Step)

#---- 打印结果

        打印“1:”,MP[1]        
        打印“2:”,MP[2]        
        打印“3:”,MP[3]        
        打印“4:”,MP[4]        

#---- 从结果构建波

        x = np.arange(N)

        Tone1 = A[1] * np.sin( x*RPS + MP[1] )
        Tone2 = A[2] * np.sin( 2*x*RPS + MP[2] )
        Tone3 = A[3] * np.sin( 3*x*RPS + MP[3] )
        Tone4 = A[4] * np.sin( 4*x*RPS + MP[4] )

        Wave = Tone1 + Tone2 + Tone3 + Tone4

#---- 从结果中显示波形

        plt.plot(x, Wave, c='g')
        plt.show()

# -  -  出口

        打印“完成”
        返回

#=================================================
def FindSmallestPeakPhases(RPS, N, A, P, Step):

        MinPhases = 数组('d',[0,0,0,0,0])

        x = np.arange(N)

        峰值 = 1000

        Wave1 = A[1] * np.sin( x*RPS + P[1] )
        阶段 1 = P[1]
        MinPhases[1] = 阶段 1

        对于范围内的 p2 ( 1, 22 ):
         Phase2 = P[2] + ( p2 - 11 ) * 步长
         Tone2 = A[2] * np.sin(2*x*RPS + Phase2)
         Wave2 = Wave1 + Tone2

         对于范围内的 p3 ( 1, 22 ):
          Phase3 = P[3] + ( p3 - 11 ) * 步长
          Tone3 = A[3] * np.sin( 3*x*RPS + Phase3 )
          Wave3 = Wave2 + Tone3

          对于范围内的 p4 ( 1, 22 ):
           Phase4 = P[4] + ( p4 - 11 ) * 步长
           Tone4 = A[4] * np.sin( 4*x*RPS + Phase4 )
           Wave4 = Wave3 + Tone4

           最小值 = min( Wave4 )
           最大值 = 最大值(Wave4)

           如果 Max > -Min:
              AbsMax = 最大值
           别的:
              AbsMax = -Min

           如果 AbsMax < 峰值:
              峰值 = AbsMax
              MinPhases[2] = Phase2
              MinPhases[3] = Phase3
              MinPhases[4] = Phase4

        打印“峰值=”,峰值

        返回最小阶段

#=================================================
主要的()