Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.05.2013, 17:25   #1
dar3dev1l26
Пользователь
 
Регистрация: 06.10.2011
Сообщений: 58
Сообщение Вопрос по обратному дискретному преобразованию Фурье

Есть массив значений аудио сигнала, надо применить к нему БПФ, выделить массивы амплитуд и фаз, изменить немного массив фаз, выполнить ОБПФ с помощью начального массива амплитуд и измененного массива фаз. Проблема в том, что я не могу найти рабочуюю формулу для ОБПФ.
БПФ код, там нет ошибок.
Код:
 public class FFT
    {
         private static Complex w(int k, int N, bool b)
        {
            Complex j = new Complex(0, 1);
            if (k % N == 0) return new Complex (1,0);
            double arg; if (!b) arg = -2 * Math.PI * k / N; else arg = 2 * Math.PI * k / N;
            return new Complex(Math.Cos(arg), Math.Sin(arg));
        }

        public static Complex[] fft(Complex[] x, bool b)
        {
            Complex[] X;
            int N = x.Length;
            if (N == 2)
            {
                X = new Complex[2];
                X[0] = x[0] + x[1];
                X[1] = x[0] - x[1];
            }
            else
            {
                Complex[] x_even = new Complex[N / 2];
                Complex[] x_odd = new Complex[N / 2];
                for (int i = 0; i < N / 2; i++)
                {
                    x_even[i] = x[2 * i];
                    x_odd[i] = x[2 * i + 1];
                }
                Complex[] X_even = fft(x_even,b);
                Complex[] X_odd = fft(x_odd,b);
                X = new Complex[N];
                for (int i = 0; i < N / 2; i++)
                {
                    X[i] = X_even[i] + w(i, N,b) * X_odd[i];
                    X[i + N / 2] = X_even[i] - w(i, N,b) * X_odd[i];
                }
            }
            return X;
        }       
    }
Класс комплексных чисел:
Код:
public class Complex
    {
        private double re;
        private double im;

        public double getRe()
        {
            return this.re;
        }
        public double getIm()
        {
            return this.im;
        }
        //Constructor
        public Complex(double re, double im)
        {
            this.re = re;
            this.im = im;
        }
        //Overloaded binary + operator
        public static Complex operator +(Complex arg1, Complex arg2)
        {
            return (new Complex(arg1.re + arg2.re, arg1.im + arg2.im));
        }
        //Overloaded unary - operator
        public static Complex operator -(Complex arg1)
        {
            return (new Complex(-arg1.re, -arg1.im));
        }        
        //Overloaded binary - operator
        public static Complex operator -(Complex arg1, Complex arg2)
        {
            return (new Complex(arg1.re - arg2.re, arg1.im - arg2.im));
        }
        //Overloaded binary * operator
        public static Complex operator *(Complex arg1, Complex arg2)
        {
            return (new Complex(arg1.re * arg2.re - arg1.im * arg2.im, arg1.re * arg2.im + arg2.re * arg1.im));
        }
        //Overloaded binary / operator
        public static Complex operator /(Complex arg1, Complex arg2)
        {
            double c1, c2, d;
            d = arg2.re * arg2.re + arg2.im * arg2.im;
            if (d == 0)
            {
                return (new Complex(0, 0));
            }
            c1 = arg1.re * arg2.re + arg1.im * arg2.im;
            c2 = arg1.im * arg2.re - arg1.re * arg2.im;
            return (new Complex(c1 / d, c2 / d));
        }
        //Absolute value of a complex number. Usage: c.Abs()
        public double Abs()
        {
            return (Math.Sqrt(re * re + im * im));
        }
        //Argument of a complex number in degree. Usage: c.Arg()
        public double Arg()
        {
            double ret = 0;
            if (re != 0)
                ret = (180 / Math.PI) * Math.Atan(im / re);
            return (ret);
        }
        //Overridden ToString. Usage: c.toString()
        public override string ToString()
        {
            return (String.Format("Complex: ({0}, {1})", re, im));
        }        
    }
dar3dev1l26 вне форума Ответить с цитированием
Старый 04.05.2013, 17:26   #2
dar3dev1l26
Пользователь
 
Регистрация: 06.10.2011
Сообщений: 58
По умолчанию

Сначала я пробовал по этому примеру делать:

Код:
int n = 4;
            Complex[] arr = new Complex[n];
            Random r = new Random();            
            textBox1.Text += "=== Initialization ===" + System.Environment.NewLine;
            for (int i = 0; i < n; i++)
            {
                arr[i] = new Complex((double)r.Next(1000), 0);
                textBox1.Text += arr[i].ToString() + System.Environment.NewLine;
            }
            textBox1.Text += "=== FFT ===" + System.Environment.NewLine;
            Complex[] fft = FFT.fft(arr, false);
            for (int i = 0; i < n; i++)
                textBox1.Text += fft[i].ToString() + System.Environment.NewLine;
            textBox1.Text += "=== AMPLITUDE ===" + System.Environment.NewLine;
            double[] A = new double[n];
            for (int i = 0; i < n; i++) 
            {
                A[i] = fft[i].Abs();
                textBox1.Text += A[i].ToString() + System.Environment.NewLine;
            }
            textBox1.Text += "=== PHASE ===" + System.Environment.NewLine;
            double[] PH = new double[n];
            for (int i = 0; i < n; i++)
            {
                PH[i] = fft[i].Arg();
                textBox1.Text += PH[i].ToString() + System.Environment.NewLine;
            }
            textBox1.Text += "=== IFFT with A and PH ===" + System.Environment.NewLine;
            Complex[] test = new Complex[n];
            for (int i = 0; i < n; i++)
                test[i] = new Complex(A[i] * Math.Exp(PH[i]), 0);
            Complex[] test2 = FFT.fft(test, true);
            for (int i = 0; i < n; i++)
            {
                textBox1.Text += test2[i].ToString() + System.Environment.NewLine;
            }
Вывод:
=== Initialization ===
Complex: (769, 0)
Complex: (426, 0)
Complex: (165, 0)
Complex: (923, 0)
=== FFT ===
Complex: (2283, 0)
Complex: (604, 497)
Complex: (-415, 0)
Complex: (604, -497)
=== AMPLITUDE ===
2283
782.192431566555
415
782.192431566555
=== PHASE ===
0
39.4491769948366
0
-39.4491769948366
=== IFFT with A and PH ===
// тут должны получаться числа, такие же как в Initialization
Complex: (1.06138633985891E+20, 0)
Complex: (8366.90227825749, 1.06138633985891E+20)
Complex: (-1.06138633985891E+20, 0)
Complex: (-4630.90227825749, -1.06138633985891E+20)
Потом попробовал вот таким образом:

Код:
int n = 4;
            Complex[] arr = new Complex[n];
            Random r = new Random();            
            textBox1.Text += "=== Initialization ===" + System.Environment.NewLine;
            for (int i = 0; i < n; i++)
            {
                arr[i] = new Complex((double)r.Next(1000), 0);
                textBox1.Text += arr[i].ToString() + System.Environment.NewLine;
            }
            textBox1.Text += "=== FFT ===" + System.Environment.NewLine;
            Complex[] fft = FFT.fft(arr, false);
            for (int i = 0; i < n; i++)
                textBox1.Text += fft[i].ToString() + System.Environment.NewLine;
            textBox1.Text += "=== AMPLITUDE ===" + System.Environment.NewLine;
            double[] A = new double[n];
            for (int i = 0; i < n; i++) 
            {
                A[i] = fft[i].Abs()/n;
                textBox1.Text += A[i].ToString() + System.Environment.NewLine;
            }
            textBox1.Text += "=== PHASE ===" + System.Environment.NewLine;
            double[] PH = new double[n];
            for (int i = 0; i < n; i++)
            {
                PH[i] = fft[i].Arg();
                textBox1.Text += PH[i].ToString() + System.Environment.NewLine;
            }
            textBox1.Text += "=== IFFT with A and PH ===" + System.Environment.NewLine;
            Complex[] test = new Complex[n];
            for (int i = 0; i < n; i++)
            {
                test[i] = new Complex(n * A[i] * Math.Exp(PH[i]), 0);
                textBox1.Text += test[i].ToString() + System.Environment.NewLine;
            }
Результат:
=== Initialization ===
Complex: (980, 0)
Complex: (918, 0)
Complex: (710, 0)
Complex: (584, 0)
=== FFT ===
Complex: (3192, 0)
Complex: (270, -334)
Complex: (188, 0)
Complex: (270, 334)
=== AMPLITUDE ===
798
107.370852655644
47
107.370852655644
=== PHASE ===
0
-51.0485066610006
0
51.0485066610006
=== IFFT with A and PH ===
// в этом случает числа здесь должны совпадать с числами в FFT
Complex: (3192, 0)
Complex: (2.90309762853303E-20, 0)
Complex: (188, 0)
Complex: (6.35376496426018E+24, 0)
Как видите половина чисел совпадает, но чем больше n, тем меньше правильных результатов, при n=16 правильных всего 1. Подскажите как мне быть, больше формул я не знаю.
dar3dev1l26 вне форума Ответить с цитированием
Старый 04.05.2013, 18:23   #3
dar3dev1l26
Пользователь
 
Регистрация: 06.10.2011
Сообщений: 58
По умолчанию

=== FFT === | === IFFT with A and PH ===
Complex: (3192, 0) | Complex: (3192, 0)
Complex: (270, -334) | Complex: (2.90309762853303E-20, 0)
Complex: (188, 0) | Complex: (188, 0)
Complex: (270, 334) | Complex: (6.35376496426018E+24, 0)
Как видно, проблемы начинаются, когда мнимая часть комплексного числа присутствует в результатах рассчетов FFT, но там, где эта мнимая часть 0 фаза тоже 0, то есть нельзя просто взять и отбросить мнимую часть в результирующем массиве FFT. Иначе фазы везде будут просто 0. Не понимаю в чём тут дело, кто разбирается в комплексных числах или FFT, помогите советом плз.
dar3dev1l26 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Фурье преобразование Ria Alva C++ Builder 0 24.06.2012 18:44
Вопрос по преобразованию типов переменных (TImage и FILE) Pcrepair Общие вопросы Delphi 3 04.01.2011 15:15
Работа по преобразованию изображения smopromote Фриланс 4 22.07.2010 09:05
Преобразование Фурье fina Помощь студентам 0 17.06.2010 14:00
Фурье DeDoK Общие вопросы Delphi 0 12.09.2008 17:28