如何将频谱图矩阵转换为WAV文件

时间:2020-10-04 12:23:01

标签: r audio signals spectrogram tuner

有没有一种方法可以将表示灰度频谱图的矩阵(值不复杂且介于0和1之间)转换为声音文件,例如下图所示的图像。 WAV文件? This post解释了如何使用numpy函数对seewave频谱图进行处理。但是,就我而言,我看到有两个问题需要解决:

  1. 原始频谱图(由istft获得)丢失,并且矩阵尺寸与原始频谱图不同(即,频率和时间都经过上/下采样),而每行和每行的准确频率和时间值列是已知的
  2. 矩阵值的范围为0到1,并且不复杂,signal::specgram要求

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

谢谢!

enter image description here

1 个答案:

答案 0 :(得分: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)将返回具有相同数量数组元素的数组(freq域)每个元素存储一个复数以计算幅度(能量水平)和相位的时间...数组元素零是可以忽略的直流偏置...每个数组元素代表一个不同的频率,频率增量可以是计算

sample_rate为每秒44100个样本,而一秒钟的样本值(44100)
这为您提供了1赫兹的频率增量分辨率... IE,每个频率间隔都相距1赫兹

incr_freq := sample_rate / number_of_samples

nyquist_limit_index := int(number_of_samples / 2)

这是您如何遍历数组complex_fft(请不要进入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),以获得时域中与您的频率(约1阶)匹配的阵列。原始输入音频信号

因此,在您的情况下,在图表上从左到右遍历数据,并针对每组垂直幅度值(由灰度表示)(这是一个频域数组)执行此傅立叶逆变换,这将为您提供原始音频信号(时域)仅在非常短的时间段(如4096个音频样本或类似信号所定义)... ...该原始音频是wav文件的有效载荷部分...对...的下一个垂直列重复此过程。数据,直到您从左到右遍历整个图...将这些有效负载缓冲区序列组合成一个wav文件

相关问题