Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Text;
- using System.Windows.Forms;
- using System.Runtime.InteropServices;
- using System.Diagnostics;
- using System.Threading;
- using System.IO;
- namespace FFT
- {
- public partial class Form1 : Form
- {
- //ilość próbek
- private int N = 0;
- //potęga dwójki równa ilości próbek
- int POTEGA = 0;
- //utworzenie dwoch wątków
- private Thread Tcpp, Tasm;
- //utworzenie stoperów do pomiaru wykonywanego wątku
- Stopwatch czasasm = new Stopwatch();
- Stopwatch czascpp = new Stopwatch();
- //zmienne służące do stworzenia interfejsu graficznego
- private Graphics GPrzed, GPo;
- private Point p = Point.Empty;
- private Pen pioro = new Pen(Color.Black);
- SolidBrush pedzel_bialy = new SolidBrush(Color.White);
- SolidBrush pedzel_czarny = new SolidBrush(Color.Black);
- //tablice na ktorych beda operowaly funkcje FFT
- double[] pktyRe_a, pktyRe_c;
- double[] pktyIm_a, pktyIm_c;
- //zmienna służąca przesunięcia rysowania wykresu
- int offsetPrzed = 0;
- int offsetPo = 0;
- //zaimportowanie funkcji dll napisanej w asemblerze
- [DllImport(@"\mojadll.dll", CallingConvention = CallingConvention.StdCall)]
- public static extern Int32 FFT_asm(double[] tabRe, double[] tabIm, int N, int POTEGA);
- //funkcja służąca do wczytania danych z pliku
- //parametrami są dwie tablice, do których zostaną wczytane dane
- unsafe static void wczytaj(double[] tabRe, double[] tabIm)
- {
- FileStream fs = new FileStream("dane.txt", FileMode.Open);
- StreamReader sr = new StreamReader(fs);
- int i, N;
- string linia = sr.ReadLine();
- N = int.Parse(linia);
- for (i = 0; i < N; i++)
- {
- linia = sr.ReadLine();
- tabRe[i] = double.Parse(linia);
- tabIm[i] = 0;
- }
- fs.Close();
- sr.Close();
- }
- //funkcja pomocnicza, która służy do obliczenia współczynnika dla FFT
- int oblicz_wspolczynnik_cpp(int tmp, int tmp_potega)
- {
- int wynik = 0, tmp2;
- for (int i = 1; i <= tmp_potega; i++)
- {
- tmp2 = tmp / 2;
- wynik = 2 * (wynik - tmp2) + tmp;
- tmp = tmp2;
- }
- return wynik;
- }
- //funkcja obliczające FFT
- unsafe void FFT_cpp(double[] Re, double[] Im, int n, int potega)
- {
- double w1, w2, w3, w4, tmp;
- int wspolczynnik, licznik_tab, il_polowek, licznik_polowka, polowka;
- //obliczenie współczynników przy wyrazach
- for (int potega_i = 0; potega_i <= (potega - 1); potega_i++)
- {
- polowka = (int)Math.Pow(2, (potega - potega_i - 1));
- licznik_tab = 0;
- il_polowek = (int)Math.Pow(2, potega_i);
- for (int i = 0; i < il_polowek; i++)
- {
- wspolczynnik = (oblicz_wspolczynnik_cpp(licznik_tab / polowka, potega));
- w1 = Math.Cos(2 * Math.PI * wspolczynnik / (double)n);
- w2 = -Math.Sin(2 * Math.PI * wspolczynnik / (double)n);
- for (int j = 0; j < polowka; j++)
- {
- licznik_polowka = licznik_tab + polowka;
- w3 = Re[licznik_polowka] * w1 - Im[licznik_polowka] * w2;
- w4 = Re[licznik_polowka] * w2 + Im[licznik_polowka] * w1;
- Re[licznik_polowka] = Re[licznik_tab] - w3;
- Im[licznik_polowka] = Im[licznik_tab] - w4;
- Re[licznik_tab] = Re[licznik_tab] + w3;
- Im[licznik_tab] = Im[licznik_tab] + w4;
- licznik_tab++;
- //j++
- }
- licznik_tab += polowka;
- //i++
- }
- //potega_i++
- }
- //poukładanie elementów w odpowiedniej kolejności
- for (int i = 0; i < n; i++)
- {
- wspolczynnik = (oblicz_wspolczynnik_cpp(i, potega));
- if (wspolczynnik >= i) continue;
- //zamiana miejsc poprzez zmienną pomocniczą (i <-> wspolczynnik)
- tmp = Re[i];
- Re[i] = Re[wspolczynnik];
- Re[wspolczynnik] = tmp;
- tmp = Im[i];
- Im[i] = Im[wspolczynnik];
- Im[wspolczynnik] = tmp;
- }
- //pomnożenie przez ostateczny współczynnik
- for (int i = 0; i < (n / 2); i++)
- Re[i] = Math.Sqrt((Re[i] * Re[i] + Im[i] * Im[i])) * 2 / (double)n;
- Re[0] = Re[0] / 2;
- }
- //pomocnicza funkcja mająca na celu inicjalizację tablicy
- unsafe void init_tab(double[] tabRe, double[] tabIm, int N)
- {
- double x;
- for (int i = 1; i <= N; i++)
- {
- x = i / (double)N;
- tabRe[i - 1] = Math.Sin(100 * x) + Math.Sin(500 * x) + Math.Sin(1000 * x) + Math.Sin(2000 * x);
- tabIm[i - 1] = 0;
- //if ((i % 30) < 15) tabRe[i - 1] += 15;
- //else tabRe[i - 1] += -15;
- }
- }
- //inicjalizacja komponentów i ich początkowych właściwości
- public Form1()
- {
- InitializeComponent();
- ImgPrzed.Image = new Bitmap(522, 150);
- ImgPo.Image = new Bitmap(522, 150);
- GPrzed = Graphics.FromImage(ImgPrzed.Image);
- GPo = Graphics.FromImage(ImgPo.Image);
- //uaktualnienie interfejsu graficznego
- komponenty1();
- }
- //rysowanie funkcji przed dokonaniu transformacji
- private void Rysuj_Click(object sender, EventArgs e)
- {
- GPrzed.SmoothingMode = SmoothingMode.HighSpeed;
- int start = 10;
- int cx = 522;
- int cy = 145;
- PointF[] pkt = new PointF[cx];
- double dx = 2.0 / cx;
- double dx1 = dx;
- double max = 0, min = 0;
- int i;
- init_tab(pktyRe_a, pktyIm_a, N);
- for (dx = dx, i = 0; i < cx; dx += dx1, i++)
- {
- if (max < pktyRe_a[i + offsetPrzed]) max = pktyRe_a[i + offsetPrzed];
- if (min > pktyRe_a[i + offsetPrzed]) min = pktyRe_a[i + offsetPrzed];
- }
- double skala_y;
- if (max == min) skala_y = cy;
- else skala_y = Math.Abs(max - min);
- double dy;
- for (int j = 0; j < cx; j++)
- {
- pkt[j].X = j + start;
- if (max == min) dy = cy / 2;
- else dy = skala_y - (pktyRe_a[j + offsetPrzed] - min);
- pkt[j].Y = Convert.ToInt32(dy * cy / skala_y);
- }
- GPrzed.DrawRectangle(pioro, 0, 0, ImgPrzed.Width, ImgPrzed.Height);
- GPrzed.FillRectangle(pedzel_bialy, 0, 0, ImgPrzed.Width, ImgPrzed.Height);
- GPrzed.DrawLines(new Pen(Color.Blue), pkt);
- Font czcionka = new Font("Microsoft Sans Serif", 8F);
- GPrzed.DrawString("" + Convert.ToString(max), czcionka, pedzel_czarny, start + 1, 4);
- GPrzed.DrawString("" + Convert.ToString(min), czcionka, pedzel_czarny, start + 1, cy - 14);
- ImgPrzed.Refresh();
- }
- //rysowanie funkcji po dokonaniu transformacji
- private void Rysuj2_Click(object sender, EventArgs e)
- {
- GPo.SmoothingMode = SmoothingMode.HighSpeed;
- int start = 12;
- int cx = 512;
- int cy = 145;
- PointF[] pkt = new PointF[cx];
- double dx = 2.0 / cx;
- double dx1 = dx;
- double max = 0, min = 0;
- int i;
- for (dx = dx, i = 0; i < cx; dx += dx1, i++)
- {
- if (max < pktyRe_a[i + offsetPo]) max = pktyRe_a[i + offsetPo];
- if (min > pktyRe_a[i + offsetPo]) min = pktyRe_a[i + offsetPo];
- }
- double skala_y;
- if (max == min) skala_y = cy;
- else skala_y = Math.Abs(max - min);
- double dy;
- for (int j = 0; j < cx; j++)
- {
- pkt[j].X = j + start;
- if (max == min) dy = cy / 2;
- else dy = skala_y - (pktyRe_a[j + offsetPo] - min);
- pkt[j].Y = Convert.ToInt32(dy * cy / skala_y);
- }
- GPo.DrawRectangle(pioro, 0, 0, ImgPo.Width, ImgPo.Height);
- GPo.FillRectangle(pedzel_bialy, 0, 0, ImgPo.Width, ImgPo.Height);
- GPo.DrawLines(new Pen(Color.Red), pkt);
- Font czcionka = new Font("Microsoft Sans Serif", 8F);
- SolidBrush kolor = new SolidBrush(Color.FromArgb(15, 15, 15));
- GPo.DrawString("" + Convert.ToString(max), czcionka, kolor, start + 1, 4);
- GPo.DrawString("" + Convert.ToString(min), czcionka, kolor, start + 1, cy - 14);
- ImgPo.Refresh();
- }
- //rysowanie na płótnie biężacej wartości tablicy oraz częstotliwości
- private void ImgPo_MouseMove(object sender, MouseEventArgs e)
- {
- if (N == 0) return;
- if (e.X > 11)
- {
- Font czcionka = new Font("Microsoft Sans Serif", 8F);
- SolidBrush kolor = new SolidBrush(Color.FromArgb(15, 15, 15));
- GPo.FillRectangle(pedzel_bialy, 512 - 94, 0, 102, 20);
- GPo.DrawRectangle(new Pen(Color.Black), 512 - 94, 0, 102, 20);
- GPo.FillRectangle(pedzel_bialy, 512 - 94, 20, 102, 20);
- GPo.DrawRectangle(new Pen(Color.Black), 512 - 94, 20, 102, 20);
- GPo.DrawString("" + Convert.ToString(pktyRe_a[e.X - 12 + offsetPo]), czcionka, kolor, 512 - 95, 4);
- GPo.DrawString("(T + " + Convert.ToString(e.X - 12 + offsetPo) + ") / 2^" + Convert.ToString(POTEGA) + " [Hz]", czcionka, kolor, 512 - 95, 24);
- ImgPo.Refresh();
- }
- }
- //zmiana wartości TextBox'a z numerem bieżącego indeksu
- private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
- {
- TNumer.Text = Convert.ToString(hScrollBarDane.Value + offsetPo);
- Font czcionka = new Font("Microsoft Sans Serif", 8F);
- SolidBrush kolor = new SolidBrush(Color.FromArgb(15, 15, 15));
- SolidBrush pedzel = new SolidBrush(Color.White);
- GPo.FillRectangle(pedzel, 512 - 93, 0, 100, 20);
- GPo.DrawRectangle(new Pen(Color.Black), 512 - 93, 0, 100, 20);
- GPo.DrawString("" + Convert.ToString(pktyRe_a[hScrollBarDane.Value + offsetPo]), czcionka, kolor, 512 - 95, 4);
- ImgPo.Refresh();
- }
- //Utworzenie wątku dla cpp
- private void FFT_cppClick(object sender, EventArgs e)
- {
- Tcpp = new Thread(BackgroundProcessingcpp);
- Tcpp.IsBackground = true;
- Tcpp.Start();
- }
- private delegate void UpdateTime(string dateTimeString);
- //uaktualnienie interfejsu podczas czasu trwania wątku
- private void UpdateTimeMethodasm(string dateTimeString)
- {
- TTimeasm.Text = dateTimeString;
- komponenty3();
- }
- //uaktualnienie interfejsu podczas czasu trwania wątku
- private void UpdateTimeMethodcpp(string dateTimeString)
- {
- TTimecpp.Text = dateTimeString;
- komponenty3();
- }
- //uruchomienie wątku używając język cpp do obliczenia FFT
- private void BackgroundProcessingcpp()
- {
- UpdateTime timeUpdater = UpdateTimeMethodcpp;
- czascpp.Reset();
- czascpp.Start();
- FFT_cpp(pktyRe_c, pktyIm_c, N, POTEGA);
- czascpp.Stop();
- TimeSpan ts = czascpp.Elapsed;
- this.BeginInvoke(timeUpdater, new object[] { ts.Ticks.ToString() });
- Tcpp.Abort();
- }
- //Utworzenie wątku dla asm
- private void FFT_asmClick(object sender, EventArgs e)
- {
- Tasm = new Thread(BackgroundProcessingasm);
- Tasm.IsBackground = true;
- Tasm.Start();
- }
- //uruchomienie wątku używając język asemblera do obliczenia FFT
- private void BackgroundProcessingasm()
- {
- UpdateTime timeUpdater = UpdateTimeMethodasm;
- czasasm.Reset();
- czasasm.Start();
- FFT_asm(pktyRe_a, pktyIm_a, N, POTEGA);
- czasasm.Stop();
- TimeSpan ts = czasasm.Elapsed;
- this.BeginInvoke(timeUpdater, new object[] { ts.Ticks.ToString() });
- Tasm.Abort();
- }
- //utworzenie dwóch powyższych wątków jednocześnie
- private void Porownaj_Click(object sender, EventArgs e)
- {
- FFT_asmClick(sender, e);
- FFT_cppClick(sender, e);
- }
- private void BWczytaj_Click(object sender, EventArgs e)
- {
- POTEGA = 11;
- N = (int)Math.Pow(2, POTEGA);
- pktyRe_a = new double[N];
- pktyIm_a = new double[N];
- pktyRe_c = new double[N];
- pktyIm_c = new double[N];
- //init_tab(pktyRe_a, pktyIm_a, N);
- //init_tab(pktyRe_c, pktyIm_c, N);
- wczytaj(pktyRe_a, pktyIm_a);
- wczytaj(pktyRe_c, pktyIm_c);
- if (N > 1024)
- {
- hScrollBarPrzed.Maximum = N / 2;
- hScrollBarPo.Maximum = N / 4;
- }
- L_n.Text = "N: " + Convert.ToString(N);
- L_potega.Text = "Potega: " + Convert.ToString(POTEGA);
- komponenty2();
- }
- //przesuwanie wykresu funkcji poprzez offset
- private void hScrollBarPrzed_Scroll(object sender, ScrollEventArgs e)
- {
- L_offsetPrzed.Text = "Offset: " + Convert.ToString(hScrollBarPrzed.Value);
- offsetPrzed = hScrollBarPrzed.Value;
- Rysuj_Click(sender, e);
- }
- //przesuwanie wykresu funkcji poprzez offset
- private void hScrollBarPo_Scroll(object sender, ScrollEventArgs e)
- {
- L_offsetPo.Text = "Offset: " + Convert.ToString(hScrollBarPo.Value);
- offsetPo = hScrollBarPo.Value;
- Rysuj2_Click(sender, e);
- }
- }
- }
Add Comment
Please, Sign In to add comment