C# не отображается график на Chart
Всем привет. Написал программу, принимающее на вход wav-файл и строящий частотно-временной спектр в Chart, но не могу грамотно прописать отображение. Помогите пожалуйста! Код
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
namespace WindowsFormsApp4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Wave files (*.wav)|*.wav";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string filePath = openFileDialog.FileName;
DrawFrequencyTimeGraph(filePath);
}
}
private void DrawFrequencyTimeGraph(string filePath)
{
// Чтение файла wav
WaveFile waveFile = new WaveFile(filePath);
// Получение параметров звука
int sampleRate = waveFile.SampleRate;
int channels = waveFile.Channels;
int samplesCount = waveFile.SamplesCount;
// Размер окна для преобразования Фурье (должен быть степенью двойки)
int windowSize = 1024;
// Шаг в секундах для временной шкалы
double timeStep = 1.0;
// Количество окон для преобразования Фурье
int windowsCount = (int)Math.Ceiling((double)samplesCount / (windowSize / 2));
// Создание Chart
Chart chart = new Chart();
chart.Size = new System.Drawing.Size(800, 600);
chart.ChartAreas.Add("ChartArea1");
chart.Series.Add("Series1");
chart.ChartAreas[0].AxisX.Title = "Time (s)";
chart.ChartAreas[0].AxisY.Title = "Frequency (Hz)";
// Проход по каждому окну и применение преобразования Фурье
for (int i = 0; i < windowsCount; i++)
{
// Создание временного массива для текущего окна
Complex[] window = new Complex[windowSize];
// Заполнение временного массива данными из wav файла
for (int j = 0; j < windowSize; j++)
{
int sampleIndex = i * (windowSize / 2) + j;
if (sampleIndex < samplesCount)
{
double sampleValue = waveFile.GetSampleValue(sampleIndex);
window[j] = new Complex(sampleValue, 0);
}
else
{
window[j] = new Complex(0, 0);
}
}
// Применение преобразования Фурье
FourierTransform.FFT(window, FourierTransform.Direction.Forward);
// Отрисовка спектра частот для текущего окна
for (int j = 0; j < windowSize / 2; j++)
{
double frequency = (double)j * sampleRate / windowSize;
double amplitude = window[j].Magnitude;
// Добавление точки на график
chart.Series[0].Points.AddXY(i * timeStep, frequency, amplitude);
}
}
// Отображение графика
chart.Show();
}
}
public class WaveFile
{
private byte[] data;
private int channels;
private int sampleRate;
public WaveFile(string filePath)
{
using (BinaryReader reader = new BinaryReader(File.Open(filePath, FileMode.Open)))
{
// Чтение заголовка файла
reader.BaseStream.Seek(22, SeekOrigin.Begin);
channels = reader.ReadInt16();
reader.BaseStream.Seek(34, SeekOrigin.Begin);
sampleRate = reader.ReadInt32();
// Чтение данных
reader.BaseStream.Seek(44, SeekOrigin.Begin);
data = reader.ReadBytes((int)(reader.BaseStream.Length - 44));
}
}
public int SampleRate
{
get { return sampleRate; }
}
public int Channels
{
get { return channels; }
}
public int SamplesCount
{
get { return data.Length / (channels * 2); }
}
public double GetSampleValue(int index)
{
int sampleIndex = index * channels * 2;
// Чтение значения сэмпла в формате Little Endian
int sampleValue = data[sampleIndex] | (data[sampleIndex + 1] << 8);
// Преобразование значения в диапазон [-1, 1]
return (double)sampleValue / (Math.Pow(2, 16) / 2);
}
}
public class FourierTransform
{
public enum Direction
{
Forward,
Backward
}
public static void FFT(Complex[] data, Direction direction)
{
int n = data.Length;
if (n == 1)
return;
Complex[] even = new Complex[n / 2];
Complex[] odd = new Complex[n / 2];
for (int i = 0; i < n / 2; i++)
{
even[i] = data[2 * i];
odd[i] = data[2 * i + 1];
}
FFT(even, direction);
FFT(odd, direction);
double angle = 2 * Math.PI / n * (direction == Direction.Forward ? 1 : -1);
Complex w = new Complex(1, 0);
Complex wn = new Complex(Math.Cos(angle), Math.Sin(angle));
for (int i = 0; i < n / 2; i++)
{
Complex temp = w * odd[i];
data[i] = even[i] + temp;
data[i + n / 2] = even[i] - temp;
w *= wn;
}
}
}
}