用C#和DynamicDataDisplay.dll编写的读取.mat文件中音频信息并用动态折线图显示
//所需头文件
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using MathNet.Numerics.Data.Matlab;//两个MathNet用于读取.mat文件
using MathNet.Numerics.LinearAlgebra;
using Microsoft.Research.DynamicDataDisplay;
using Microsoft.Research.DynamicDataDisplay.DataSources;
//定义
public ObservableDataSource[] dataSource = new ObservableDataSource[2] { new ObservableDataSource(), new ObservableDataSource() };
private DispatcherTimer timer = new DispatcherTimer();
private LineGraph graph = new LineGraph();
private int i = 0;//已画的点数
private double currentSecond = 0;//当前点的横坐标
bool flag = false;//用于切换曲线测试,flag为false时显示曲线0,flag为true时显示曲线1
double[][] y;
double xaxis = 0;//plotter显示时的初始横坐标,用于曲线随x轴移动时
double[] ymax = new double[8] { 0,0,0,0,0,0,0,0 };
double yaxis;//plotter显示时的纵坐标,用于曲线随x轴移动时
double group = 0.015;//默认组距
bool stop = false;//用于曲线暂停测试,stop为true时停止画线
public MainWindow()
{
InitializeComponent();
Matrix<double> filt_data = MatlabReader.Read<double>("FrameworkData_01.mat", "filt_data");//读取.mat文件中的音频信息
y = filt_data.ToColumnArrays();//将矩阵转换为二维数组
}
/*******
* private void AnimatedPlot(object sender, EventArgs e)
* 用于构造坐标点
*******/
private void AnimatedPlot(object sender, EventArgs e)
{
double x = currentSecond;
Point[] point = new Point[2];//定义并添加需要画的新点
point[0] = new Point(x, y[0][i]);
point[1] = new Point(x, y[1][i]);
dataSource[0].AppendAsync(base.Dispatcher, point[0]);//将新点添加到队列(?)中
dataSource[1].AppendAsync(base.Dispatcher, point[1]);
i++;
//计算此时plotter需要显示的最小横坐标
if (currentSecond - group > 0)
{
xaxis = currentSecond - group;
}
else
{
xaxis = 0;
}
//计算此时plotter需要显示的最大纵坐标
for(int j = 0; j < point.Length; j++)
{
if (Math.Abs(y[j][i]) > ymax[j])
ymax[j] = Math.Abs(y[j][i]);
}
if ( !flag )
{
yaxis = ymax[0];
}
else
{
yaxis = ymax[1];
}
plotter.Viewport.Visible = new System.Windows.Rect(xaxis, -yaxis, group, 2 * yaxis);//设置plotter随x轴移动
currentSecond += 1.0 / 20000;//文件中音频采率为20000
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
timer.Interval = TimeSpan.FromSeconds(1.0/20000);//设置计时器间隔为1/20000秒
timer.Tick += new EventHandler(AnimatedPlot);//连续执行AnimatedPlot 事件实时绘制新坐标点
timer.IsEnabled = true;//开启计时器
graph = plotter.AddLineGraph(dataSource[0], Colors.Green, 2, "Percentage");//初始曲线为曲线0
plotter.Viewport.FitToView();
}
//测试用按钮函数
private void button_Click(object sender, RoutedEventArgs e)
{
/****
* 测试曲线切换
* */
//flag = !flag;
//plotter.Children.Remove(graph);//移除当前曲线
//if (flag)
//{
// graph = plotter.AddLineGraph(dataSource[1], Colors.Green, 2, "Percentage");//显示曲线1
//}
//else
//{
// graph = plotter.AddLineGraph(dataSource[0], Colors.Green, 2, "Percentage");//显示曲线2
//}
/****
* 测试曲线暂停
* */
stop = !stop;
if( stop)
{
timer.IsEnabled = false;
}
else
{
timer.IsEnabled = true;
}
}
xaml代码:
<Window x:Class="key_cam_03.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
xmlns:local="clr-namespace:key_cam_03"
mc:Ignorable="d"
Title="MainWindow" Loaded="Window_Loaded" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
Grid.RowDefinitions>
<d3:ChartPlotter x:Name="plotter" Margin="10,20,20,20" Grid.Row="1">
<d3:ChartPlotter.VerticalAxis>
<d3:VerticalAxis/>
d3:ChartPlotter.VerticalAxis>
<d3:ChartPlotter.HorizontalAxis>
<d3:HorizontalTimeSpanAxis/>
d3:ChartPlotter.HorizontalAxis>
<d3:Header Content="Data Display"/>
<d3:VerticalAxisTitle Content="sound pressure"/>
d3:ChartPlotter>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Width="75" Margin="400,0,0,0" Click="button_Click"/>
Grid>
Window>