代码之家  ›  专栏  ›  技术社区  ›  Robin

Android使用jTransform库可视化PCM数据

  •  1
  • Robin  · 技术社区  · 6 年前

    我正在尝试显示一些PCM数据的可视化效果。 目标是显示如下内容:

    enter image description here

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

    谢谢。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Scott Stensland    6 年前

    PCM音频是模拟音频曲线的数字化简化…该时域信号可以被输入到离散傅立叶变换API调用中,将数据转换成其等效的频域…虚数和欧拉公式是你的朋友

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

    注意,当你增加音频采样数(音频曲线上的PCM点)时,你输入到傅立叶变换中,从该呼叫返回的频率分辨率越细,但是如果你的音频是一些动态信号,如音乐(而不是静态音调),这会降低时间的特异性。

    这是我在Golang中编写的一个函数,它是对dft调用的包装器,在这里我将一个标准化为浮点的pcm原始音频缓冲区馈送给它,在浮点值从-1到+1之间变化,在这里它进行离散傅立叶变换(fft)调用,然后使用compl数组计算每个频率bin的大小。从DFT返回的EX编号…一个项目的一部分,通过观看视频(一次一个图像)合成音频,然后它可以收听该音频合成输出图像…实现输出照片与输入照片基本匹配的目标……输入图像-音频-输出图像

    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
    }
    

    现在你有了一个数组,其中数组的每个元素都是这个频率仓的大小…每个频率箱由上述var incr_freq…使用最小和最大震级标准化震级…它准备好输入一个x,y图给你光谱图的可视化。

    我建议打开一些书…观看我在上面评论中提到的视频…我对傅立叶变换奇观的探索之旅从一个本科生开始就一直在进行,它充满了令人惊讶的应用,它的理论仍然是一个非常活跃的研究领域。