Java - 如何将频率转换为复数

Posted

技术标签:

【中文标题】Java - 如何将频率转换为复数【英文标题】:Java - How to turn in frequency a complex number 【发布时间】:2018-02-24 10:53:28 【问题描述】:

我正在从 wav 音频中读取每一帧的字节数。我有一个采样率 = 44100,通道 = 2 的格式。

     byte[] buffer = new byte[(int) 1024];
     while (running)                                    
     n++;
     if (n > 400000)break;                  
     int count = 0;
     count = outDinSound.read(buffer, 0, 1024);
     if (count > 0) out.write(buffer, 0, count);      
     byte b[] = out.toByteArray();
     final int totalSize = b.length;
     int amountPossible = totalSize / 1024;
                                                      *so far all is good*

下一步是从数组中的每个值创建一个复数,然后我为这些复数调用快速傅立叶传输

          Complex[][] results = new Complex[amountPossible][];
          for (int times = 0; times < amountPossible; times++) 
                    Complex[] complex = new Complex[1024]; 
                    for (int i = 0; i < 1024; i++)      
                    complex[i] = new Complex(b[(times * 1024) + i], 0); 
          results[times] = FFT.fft(complex);
                                                                     

现在我可以像这样找出每个信号的幅度

            for (int t = 0; t < results.length; t++)     
                   for (int freq = 1; freq < 1024; freq++)  
                       magnitude =results[t][freq].abs();   
                                                       

但我的最终目标是找出频率(或该信号存在的频率)。

我使用的复杂类是那个

            public class Complex 
            private final double re; // the real part
private final double im; // the imaginary part

public Complex(double real, double imag) // create a new object with the given real and imaginary parts
re = real;
im = imag;  

   public String toString()    // return a string representation of the invoking Complex object
    if (im == 0)    return re + "";
    if (re == 0)    return im + "i";
    if (im < 0) return re + " - " + (-im) + "i";
    return re + " + " + im + "i";   
           //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     public double abs()    // return abs/modulus/magnitude and angle/phase/argument
     return Math.hypot(re, im);  // Math.sqrt(re*re + im*im)
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public double phase() 
       return Math.atan2(im, re);    // between -pi and pi
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       public Complex plus(Complex b) // return a new Complex object whose value is (this + b)
       Complex a = this; // invoking object
       double real = a.re + b.re;
       double imag = a.im + b.im;
       return new Complex(real, imag);  
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       public Complex minus(Complex b) // return a new Complex object whose value is (this - b)
       Complex a = this;
       double real = a.re - b.re;
       double imag = a.im - b.im;
       return new Complex(real, imag);  
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       public Complex times(Complex b) // return a new Complex object whose value is (this * b)
       Complex a = this;
       double real = a.re * b.re - a.im * b.im;
       double imag = a.re * b.im + a.im * b.re;
       return new Complex(real, imag);  

       public Complex times(double alpha) // scalar multiplication// scalar multiplication// return a new object whose value is (this * alpha)
       return new Complex(alpha * re, alpha * im);  
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       public Complex conjugate() // return a new Complex object whose value is the conjugate of this
       return new Complex(re, -im); 
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       public Complex reciprocal() // return a new Complex object whose value is the reciprocal of this
       double scale = re * re + im * im;
       return new Complex(re / scale, -im / scale); 
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       public double re()  
       return re;   
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       public double im() 
       return im;   

       public Complex divides(Complex b) // return a / b
       Complex a = this;
       return a.times(b.reciprocal());  
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      public Complex exp() //return a new Complex object whose value is the complex exponential of
return new Complex(Math.exp(re) * Math.cos(im), Math.exp(re)* Math.sin(im));    
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       public Complex sin() // return a new Complex object whose value is the complex sine of this
       return new Complex(Math.sin(re) * Math.cosh(im), Math.cos(re)* Math.sinh(im));   
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       public Complex cos() // return a new Complex object whose value is the complex cosine of this
       return new Complex(Math.cos(re) * Math.cosh(im), -Math.sin(re)* Math.sinh(im)); 
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       public Complex tan() // return a new Complex object whose value is the complex tangent of this
       return sin().divides(cos()); 
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       public static Complex plus(Complex a, Complex b) // a static version of plus
double real = a.re + b.re;
double imag = a.im + b.im;
Complex sum = new Complex(real, imag);
return sum; 

   

有什么想法吗?我试图把信号的罪孽,但我不能去频率部分。

【问题讨论】:

许多重复项,例如***.com/questions/16060134/… 和 ***.com/questions/7674877/… 【参考方案1】:

FFT_SIZE = FFT 的长度,在您的情况下为 complex.lengthresults[x].length1024

FFT 频率 bin 的数量,FFT_BIN_SIZE = FFT_SIZE / 2

FFT_BIN_WIDTH = 采样率 / FFT_SIZE 或奈奎斯特频率 / FFT_BIN_SIZE

for (int i = 0; i < results.length; i++) 
    for (int j = 0; j < results[i].length / 2; j++) 
          Frequency = j * FFT_BIN_WIDTH;
          Magnitude = results[i][j].abs();
    

请注意,您可以获得的最大频率是奈奎斯特频率,即采样率的一半,而 FFT 输出的后半部分是前半部分的复共轭。

【讨论】:

以上是关于Java - 如何将频率转换为复数的主要内容,如果未能解决你的问题,请参考以下文章

如何将归一化频率转换为实际频率

如何将音频剪辑转换为数组以执行 FFT?

给定一个代表值频率的熊猫系列,我如何将这些频率转换为百分比?

如何将频率分布转换为R中的概率分布

如何决定要使用多少点来做fft

我如何将文本文件转换为小写并查找字母的频率?