wav到FFT

本文介绍了一个使用快速傅立叶变换(FFT)进行音频信号处理的实际案例。通过读取.wav文件数据,利用FFT算法实现了频谱分析,并展示了如何将结果可视化为图形。此应用涉及信号处理与图形展示的技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下是我的理解,不保证绝对正确

1、wav出来的数据都是实部的数据,虚部就是0

2、FFT的输入数据一定要是2的N次方,不足的部分用0补足


算法不难


using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;
using System.Threading;

namespace FFT
{
    public partial class Form1 : Form
    {
        const bool leftStatus = false;
        const int dataLength = 128;        //输入数据量
        double[] rDataIn = new double[dataLength];   //输入实部
        double[] iDataIn = new double[dataLength];   //输入虚部
        double[] rDataOut = new double[dataLength];
        double[] iDataOut = new double[dataLength];

        public Form1()
        {
            InitializeComponent();
            new Thread(new ThreadStart(() =>
            {
                this.Invoke(new MethodInvoker(() => { label1.Text = leftStatus ? "左声道" : "右声道"; }));
                List<double> list = new List<double>();
                StreamReader sr = new StreamReader("data.txt", Encoding.Default);
                int m = 0;
                while (!sr.EndOfStream)
                {
                    if (leftStatus)
                    {
                        if (m % 2 == 0)
                            list.Add(double.Parse(sr.ReadLine()));
                    }
                    else
                    {
                        if (m % 2 != 0)
                            list.Add(double.Parse(sr.ReadLine()));
                    }
                    m++;
                }
                int p = 0;
                for (int i = 0; i < list.Count; i++)
                {
                    if (i % (list.Count / dataLength) == 0)
                    {
                        rDataIn[p] = list[i];
                        iDataIn[p] = 0;
                        p++;
                        if (p >= dataLength)
                        {
                            break;
                        }
                    }
                }
                sr.Close();
                FFT(ref rDataIn, ref iDataIn, ref  rDataOut, ref  iDataOut);
                Bitmap bitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);
                Graphics g = Graphics.FromImage(bitmap);
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                g.DrawLine(new Pen(Color.Black, 5), new Point(20, 20), new Point(20, 540));
                g.DrawLine(new Pen(Color.Black, 5), new Point(20, 290), new Point(1600, 290));

                int k = 1550 / dataLength;
                Point prv = new Point();
                Point next = new Point();
                for (int i = 0; i < dataLength - 1; i++)
                {
                    if (i == 0)
                    {
                        prv = new Point(30 + i * k, 290 + (int)(rDataOut[i] * 100));
                    }
                    next = new Point(30 + (i + 1) * k, 290 + (int)(rDataOut[i + 1] * 250));
                    g.DrawLine(new Pen(Color.Green, 1), prv, next);
                    prv = next;
                }
                this.pictureBox1.Image = bitmap;
            })).Start();
        }

        private void FFT(ref double[] rIn, ref  double[] iIn, ref double[] rOut, ref double[] iOut)
        {
            int length = rIn.Length;
            if (length == 1)
            {
                rOut = rIn;
                iOut = iIn;
                return;
            }
            length = length / 2;
            double[] rEvenIn = new double[length];
            double[] iEvenIn = new double[length];
            double[] rOddIn = new double[length];
            double[] iOddIn = new double[length];
            double[] rEvenOut = new double[length];
            double[] iEvenOut = new double[length];
            double[] rOddOut = new double[length];
            double[] iOddOut = new double[length];
            for (int i = 0; i < length; i++)   //奇偶位分开
            {
                rEvenIn[i] = rIn[i * 2];
                iEvenIn[i] = iIn[i * 2];
                rOddIn[i] = rIn[i * 2 + 1];
                iOddIn[i] = iIn[i * 2 + 1];
            }
            FFT(ref rEvenIn, ref iEvenIn, ref rEvenOut, ref iEvenOut);   //偶位迭代
            FFT(ref rOddIn, ref  iOddIn, ref rOddOut, ref  iOddOut);    //奇位迭代
            double rData, iData;
            for (int i = 0; i < length; i++)
            {
                rData = Math.Cos(2 * Math.PI / (length * 2) * i);
                iData = -Math.Sin(2 * Math.PI / (length * 2) * i);
                rOut[i] = rEvenOut[i] + rOddOut[i] * rData - iOddOut[i] * iData;
                iOut[i] = iEvenOut[i] + iOddOut[i] * rData + rOddOut[i] * iData;
                rOut[i + length] = rEvenOut[i] - rOddOut[i] * rData + iOddOut[i] * iData;
                iOut[i + length] = iEvenOut[i] - iOddOut[i] * rData - rOddOut[i] * iData;
            }
            rEvenIn = iEvenIn = rOddIn = iOddIn = rEvenOut = iEvenOut = rOddOut = iOddOut = null;
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            this.Width = 1650;
            this.Height = 600;
        }
    }
}






评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值