1

有没有一种方法可以将表示灰度频谱图的矩阵(值非复杂且介于 0 和 1 之间)如下图所示的矩阵转换回声音文件,例如 wav 文件?这篇文章解释了如何使用该函数seewave使用频谱图来做到这一点。istft但是,就我而言,我看到两个需要解决的问题:

  1. 原始频谱图(由 获得signal::specgram)丢失并且矩阵维度与原始频谱图不同(即频率和时间都被上采样/或下采样),而每行和每列的精确频率和时间值是已知的
  2. 矩阵值介于 0 和 1 之间,并不像所要求的那样复杂istft

此外,原始频谱图的维度、原始波对象的采样频率以及用于获得原始频谱图的窗口长度和重叠是已知的。

谢谢!

在此处输入图像描述

4

1 回答 1

1

音频只是一条随时间摆动的曲线,这种摆动反映了您的耳膜或麦克风拾音膜……这个信号在时域中,X 轴是时间,Y 轴是曲线高度……典型的 CD 质量音频有 44,100 个样本每秒意味着您每秒捕获此音频曲线上的该点数...捕获的是音频曲线高度,而时间暗示知道每个样本都以已知的采样率捕获...因此采样率是其中之一数字音频的两个关键音频属性...位深度是另一个属性...如果您使用两个字节(16 位)来记录 CD 质量曲线高度,您会得到 2 的 16 次方(2^16 == 65536)不同的可能值来存储曲线高度

强调原始音频信号的关键在于时域(X 是时间 Y 是曲线高度)......当您将一组这些样本发送到 fft 调用时,数据会转换到频域(X 是频率 Y是幅度 [能量]),因此时间的直接维度已经消失,但已被纳入整个频域数据的概念中......在决定您输入 fft 调用的样本数量(样本窗口大小),即增加频域信号的频率分辨率(降低 incr_freq ),您需要更多的音频样本来输入 fft 调用,但是要获得频域中的时间特异性,您需要尽可能少的样本通过获得较低的频率分辨率和较低的峰值频率(奈奎斯特下限)

要生成频谱图,您可以将这个曲线高度数组(时域)的 4096 个样本的内存缓冲区输入到傅立叶变换(fft)中,傅里叶变换(fft)将返回相同数量的数组元素的数组(频域),但这次是每个元素存储一个复数,您可以从中计算幅度(能级)和相位...数组元素零是可以忽略的直流偏置...每个数组元素代表一个不同的频率,可以计算频率增量

sample_rate 为每秒 44100 个样本,以及一秒的样本( 44100 ),
这为您提供了 1 赫兹的频率增量分辨率 ... IE 每个频率箱相隔 1 赫兹

incr_freq := sample_rate / number_of_samples

nyquist_limit_index := int(number_of_samples / 2)

这是您可以遍历数组 complex_fft 的方法(在 go not r 中)

for index_fft, curr_complex := range complex_fft { // we really only use half this range + 1

    if index_fft <= nyquist_limit_index && curr_freq >= min_freq && curr_freq < max_freq {

        curr_real = real(curr_complex) // pluck out real portion of complex number
        curr_imag = imag(curr_complex) // ditto for imaginary portion

        curr_mag = 2.0 * math.Sqrt(curr_real*curr_real+curr_imag*curr_imag) / number_of_samples

        curr_theta = math.Atan2(curr_imag, curr_real)

        curr_dftt := discrete_fft{

            real:      2.0 * curr_real,
            imaginary: 2.0 * curr_imag,
            magnitude: curr_mag,
            theta:     curr_theta,
        }

随着时间的推移,您重复上述将下一组 4096 个样本馈送到 fft api 调用的过程,因此您收集了一组时域数组对及其相应的频域表示

创建你的绘图的过程已经完成了这个重复过程,这就是为什么时间显示为 X 轴的原因......在你的绘图上,每个垂直数据条代表来自单个 fft 调用的输出,其中其结果幅度显示为该垂直的暗部分条形图和图上较亮的点显示较低的能量频率......只有在生成该图的过程随着时间推移,随着图从左到右进行,数据才可用于绘制下一个垂直条,因此时间轴横跨底部的 X 轴

另一个重要的见解是要知道你可以从音频(时域)开始......填充一个样本窗口(例如 4096)并将这个数组发送到 fft 调用中以获得一个新的频率数组(频率域),每个都有它的幅度和相位......这是纯粹的魔法,然后您可以在此频域数组上执行傅里叶逆变换 (ifft) 以获得时域中的数组,该数组将匹配(第一个近似值)您的原始输入音频信号

因此,在您的情况下,在图上从左到右遍历您的数据,并且对于作为单个频域数组的每组垂直幅度值(由灰度表示)执行此傅里叶逆变换,这将为您提供原始音频信号(时间域 ) 仅用于一个非常快的时间段(由 4096 音频样本或类似定义)...此原始音频是 wav 文件的有效负载部分...对下一个垂直数据列重复此过程,直到您已经从左到右走过了整个情节......将这个有效负载缓冲区序列拼接到一个wav文件中

于 2020-10-04T13:35:29.197 回答