Android 使用 JTransform 库可视化 PCM 数据

Android visualize PCM data with JTransform library

我想展示一些PCM数据的可视化效果。 目标是显示如下内容:

我搜索并发现 JTransform 是正确的库。但是,我找不到如何使用这个库的好指南。如何将我的 PCM 数据转换为可用于绘制条形图的 band/frequency 数据?

非常感谢。

PCM 音频是模拟音频曲线的数字化简化...这个时域信号可以输入离散傅里叶变换 api 调用以将数据转换为其等效的频域...虚构数字和欧拉公式是你的朋友

最简单的部分是调用 fft,更多的是解析其输出... 用来自 PCM 的至少 1024(确保它是 2 的幂)点填充一个缓冲区,然后将其输入一些 fft api 调用...这将 return 返回给你它的频域等效...将文档钉在任何离散傅立叶变换 api 调用您使用...奈奎斯特极限的查找概念...掌握频率仓的概念...随时掌握每个缓冲区的样本数和采样率您的 PCM 音频

请注意,当您增加输入傅里叶变换的音频样本数量(音频曲线上的 PCM 点)时,从该调用中获得的频率分辨率 return 越精细,但是如果您的音频是一些像音乐这样的动态信号(相对于静态音调)这会降低时间特异性

这是我在 golang 中编写的一个函数,它是对 DFT 调用的包装器,我将 PCM 原始音频缓冲区归一化为浮点,从 -1 到 +1 不等,它进行离散傅立叶变换(fft) call 然后使用复数数组 return 从 DFT 计算每个频率仓的幅度...通过观看视频(一次一个图像)合成音频的项目的一部分,然后它可以收听用于合成输出图像的音频...实现了输出照片与输入照片基本匹配的目标......输入图像 -> 音频 -> 输出图像

func discrete_time_fourier_transform(aperiodic_audio_wave []float64, flow_data_spec *Flow_Spec) ([]discrete_fft, float64, float64, []float64) {

    min_freq := flow_data_spec.min_freq
    max_freq := flow_data_spec.max_freq

    //      https://www.youtube.com/watch?v=mkGsMWi_j4Q
    //      Discrete Fourier Transform - Simple Step by Step 

    var complex_fft []complex128

    complex_fft = fft.FFTReal(aperiodic_audio_wave) // input time domain ... output frequency domain of equally spaced freqs

    number_of_samples := float64(len(complex_fft))

    nyquist_limit_index := int(number_of_samples / 2)

    all_dft := make([]discrete_fft, 0) // 20171008

    /*
       0th term of complex_fft is sum of all other terms
       often called the bias shift
    */

    var curr_real, curr_imag, curr_mag, curr_theta, max_magnitude, min_magnitude float64

    max_magnitude = -999.0
    min_magnitude = 999.0
    min_magnitude = 999.0

    all_magnitudes := make([]float64, 0)

    curr_freq := 0.0
    incr_freq := flow_data_spec.sample_rate / number_of_samples

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

        // if index <= nyquist_limit_index {
        if index <= nyquist_limit_index && curr_freq >= min_freq && curr_freq < max_freq {

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

            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,
            }

            if curr_dftt.magnitude > max_magnitude {

                max_magnitude = curr_dftt.magnitude
            }

            if curr_dftt.magnitude < min_magnitude {

                min_magnitude = curr_dftt.magnitude
            }

            // ... now stow it

            all_dft = append(all_dft, curr_dftt) 

            all_magnitudes = append(all_magnitudes, curr_mag)
        }

        curr_freq += incr_freq
    }

    return all_dft, max_magnitude, min_magnitude, all_magnitudes
}

现在你有一个数组 all_magnitudes,其中数组的每个元素都是该频率仓的幅度...每个频率仓均按上述 var incr_freq 定义的频率增量均匀分布...使用 min 和 max_magnitude 对幅度进行归一化 ...它已准备好输入 X、Y 图,为您提供频谱图可视化

我建议打开一些书...观看我在上面评论中提到的视频...自从成为电子工程本科生以来,我就一直在探索傅里叶变换的奇迹,它充满了令人惊讶的应用和它的理论仍然是一个非常活跃的研究领域