diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs
index 43f84fd..91441a2 100644
--- a/Correlator/Dialog/CheckResponseDialog.xaml.cs
+++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs
@@ -231,7 +231,7 @@
if (RedSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev1);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1);
_redResponseTimer.Start();
ReCheckButton.IsEnabled = true;
@@ -239,11 +239,11 @@
else if (RedSensorStepBar.StepIndex == 2)
{
//下发数据全部正常指令
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev1}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev1}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.RedSensorOriginalResp orderby pair.Key select pair;
@@ -266,7 +266,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev1, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev1, tags);
#endregion
}
@@ -315,18 +315,18 @@
if (BlueSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev2);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2);
_blueResponseTimer.Start();
ReCheckButton.IsEnabled = true;
}
else if (BlueSensorStepBar.StepIndex == 2)
{
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev2}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev2}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.BlueSensorOriginalResp orderby pair.Key select pair;
@@ -349,7 +349,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev2, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev2, tags);
#endregion
}
@@ -396,7 +396,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, redIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray);
}
else
{
@@ -417,7 +417,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, blueIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray);
}
};
}
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs
index 43f84fd..91441a2 100644
--- a/Correlator/Dialog/CheckResponseDialog.xaml.cs
+++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs
@@ -231,7 +231,7 @@
if (RedSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev1);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1);
_redResponseTimer.Start();
ReCheckButton.IsEnabled = true;
@@ -239,11 +239,11 @@
else if (RedSensorStepBar.StepIndex == 2)
{
//下发数据全部正常指令
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev1}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev1}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.RedSensorOriginalResp orderby pair.Key select pair;
@@ -266,7 +266,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev1, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev1, tags);
#endregion
}
@@ -315,18 +315,18 @@
if (BlueSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev2);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2);
_blueResponseTimer.Start();
ReCheckButton.IsEnabled = true;
}
else if (BlueSensorStepBar.StepIndex == 2)
{
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev2}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev2}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.BlueSensorOriginalResp orderby pair.Key select pair;
@@ -349,7 +349,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev2, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev2, tags);
#endregion
}
@@ -396,7 +396,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, redIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray);
}
else
{
@@ -417,7 +417,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, blueIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray);
}
};
}
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml b/Correlator/Dialog/SimplyAuditionDialog.xaml
index 5fd8124..cd03b74 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml
@@ -9,7 +9,7 @@
xmlns:prism="http://prismlibrary.com/"
xmlns:vm="clr-namespace:Correlator.ViewModels"
Width="600"
- Height="400"
+ Height="480"
d:DataContext="{d:DesignInstance Type=vm:SimplyAuditionDialogViewModel}"
Loaded="SimplyAuditionDialog_OnLoaded"
Unloaded="SimplyAuditionDialog_OnUnloaded"
@@ -187,10 +187,15 @@
-
+ Background="{StaticResource MainThemeColor}">
+
+
+
+
+
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs
index 43f84fd..91441a2 100644
--- a/Correlator/Dialog/CheckResponseDialog.xaml.cs
+++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs
@@ -231,7 +231,7 @@
if (RedSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev1);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1);
_redResponseTimer.Start();
ReCheckButton.IsEnabled = true;
@@ -239,11 +239,11 @@
else if (RedSensorStepBar.StepIndex == 2)
{
//下发数据全部正常指令
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev1}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev1}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.RedSensorOriginalResp orderby pair.Key select pair;
@@ -266,7 +266,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev1, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev1, tags);
#endregion
}
@@ -315,18 +315,18 @@
if (BlueSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev2);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2);
_blueResponseTimer.Start();
ReCheckButton.IsEnabled = true;
}
else if (BlueSensorStepBar.StepIndex == 2)
{
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev2}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev2}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.BlueSensorOriginalResp orderby pair.Key select pair;
@@ -349,7 +349,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev2, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev2, tags);
#endregion
}
@@ -396,7 +396,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, redIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray);
}
else
{
@@ -417,7 +417,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, blueIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray);
}
};
}
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml b/Correlator/Dialog/SimplyAuditionDialog.xaml
index 5fd8124..cd03b74 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml
@@ -9,7 +9,7 @@
xmlns:prism="http://prismlibrary.com/"
xmlns:vm="clr-namespace:Correlator.ViewModels"
Width="600"
- Height="400"
+ Height="480"
d:DataContext="{d:DesignInstance Type=vm:SimplyAuditionDialogViewModel}"
Loaded="SimplyAuditionDialog_OnLoaded"
Unloaded="SimplyAuditionDialog_OnUnloaded"
@@ -187,10 +187,15 @@
-
+ Background="{StaticResource MainThemeColor}">
+
+
+
+
+
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
index 3747ce0..41cb280 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
@@ -6,6 +7,8 @@
using System.Windows.Threading;
using Correlator.DataService;
using Correlator.Util;
+using NAudio.CoreAudioApi;
+using NAudio.Wave;
namespace Correlator.Dialog
{
@@ -16,6 +19,7 @@
{
private readonly AudioVisualizer _visualizer; // 可视化
private double[] _spectrumData; // 频谱数据
+ private readonly WasapiCapture _capture; // 音频捕获
private int _colorIndex;
private readonly Color[] _allColors;
@@ -29,29 +33,44 @@
Interval = new TimeSpan(0, 0, 0, 0, 30)
};
- public SimplyAuditionDialog(IApplicationDataService dataService, IAudioService audioService)
+ public SimplyAuditionDialog(IApplicationDataService dataService)
{
InitializeComponent();
- // _visualizer = dataService.GetAudioVisualizer(256);
- // _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
- //
- // audioService.AudioVisualizer = _visualizer;
- //
- // _dataTimer.Tick += DataTimer_Tick;
- // _drawingTimer.Tick += DrawingTimer_Tick;
+ _capture = new WasapiLoopbackCapture(); // 捕获电脑发出的声音
+ _visualizer = dataService.GetAudioVisualizer(512);
+ _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
+
+ _capture.WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(7500, 1);
+ _capture.DataAvailable += delegate(object o, WaveInEventArgs args)
+ {
+ var length = args.BytesRecorded / 4; // 采样的数量 (每一个采样是 4 字节)
+ var result = new double[length];
+
+ for (var i = 0; i < length; i++)
+ {
+ result[i] = BitConverter.ToSingle(args.Buffer, i * 4); // 取出采样值
+ }
+
+ _visualizer.PushSampleData(result); // 将新的采样存储到 可视化器 中
+ };
+
+ _dataTimer.Tick += DataTimer_Tick;
+ _drawingTimer.Tick += DrawingTimer_Tick;
}
private void SimplyAuditionDialog_OnLoaded(object sender, RoutedEventArgs e)
{
- // _dataTimer.Start();
- // _drawingTimer.Start();
+ _capture.StartRecording();
+ _dataTimer.Start();
+ _drawingTimer.Start();
}
private void SimplyAuditionDialog_OnUnloaded(object sender, RoutedEventArgs e)
{
- // _drawingTimer.Stop();
- // _dataTimer.Stop();
+ _drawingTimer.Stop();
+ _dataTimer.Stop();
+ _capture.StopRecording();
}
///
@@ -62,7 +81,7 @@
private void DataTimer_Tick(object sender, EventArgs e)
{
var newSpectrumData = _visualizer.GetSpectrumData(); // 从可视化器中获取频谱数据
- newSpectrumData = AudioVisualizer.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
+ newSpectrumData = AudioDataHub.Get.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
if (_spectrumData == null) // 如果已经存储的频谱数据为空, 则把新的频谱数据直接赋值上去
{
@@ -92,80 +111,90 @@
var color1 = _allColors[_colorIndex % _allColors.Length];
var color2 = _allColors[(_colorIndex + 200) % _allColors.Length];
- DrawGradientStrips(
- StripsPath, color1, color2,
- _spectrumData, _spectrumData.Length,
- StripsPath.ActualWidth, 0, StripsPath.ActualHeight,
- 2, -StripsPath.ActualHeight * 200
+ var bassArea = AudioDataHub.Get.TakeSpectrumOfFrequency(
+ _spectrumData, RuntimeCache.AudioSampleRate, 250
+ );
+ var bassScale = bassArea.Average() * 100; //低音区
+
+ //波形曲线
+ var curveBrush = new SolidColorBrush(color1);
+ DrawCurve(
+ SampleWavePath, curveBrush,
+ _visualizer.SampleData, _visualizer.SampleData.Length,
+ SampleWavePanel.ActualWidth, 0, SampleWavePanel.ActualHeight / 2,
+ Math.Min(SampleWavePanel.ActualHeight / 2, 50)
+ );
+
+ //四周边框
+ DrawGradientBorder(
+ TopBorder, BottomBorder, LeftBorder, RightBorder,
+ Color.FromArgb(0, color1.R, color1.G, color1.B), color2,
+ SampleWavePanel.ActualWidth / 3, bassScale
);
}
///
- /// 绘制渐变的条形
+ /// 画曲线
///
- /// 绘图目标
- /// 下方颜色
- /// 上方颜色
- /// 频谱数据
- /// 条形的数量
- /// 绘图的宽度
- /// 绘图的起始 X 坐标
- /// 绘图的起始 Y 坐标
- /// 条形与条形之间的间隔(像素)
- /// 控制波形图波峰高度
- private void DrawGradientStrips(
- Path stripsPath, Color bottomColor, Color topColor, double[] spectrumData,
- int stripCount, double drawingWidth, double xOffset, double yOffset, double spacing, double scale
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 控制波形图波峰高度和波谷深度
+ private void DrawCurve(
+ Path wavePath, Brush brush, double[] spectrumData, int pointCount, double drawingWidth,
+ double xOffset, double yOffset, double scale
)
{
- //竖条宽度
- var stripWidth = (drawingWidth - spacing * stripCount) / stripCount;
- var pointArray = new Point[stripCount];
-
- for (var i = 0; i < stripCount; i++)
+ var pointArray = new Point[pointCount];
+ for (var i = 0; i < pointCount; i++)
{
- var x = stripWidth * i + spacing * i + xOffset;
- var y = spectrumData[i * spectrumData.Length / stripCount] * scale; // height
- //给所有频谱位置赋值
+ var x = i * drawingWidth / pointCount + xOffset;
+ var y = spectrumData[i * spectrumData.Length / pointCount] * scale + yOffset;
pointArray[i] = new Point(x, y);
}
- //生成一系列频谱竖条
- var geometry = new GeometryGroup();
- foreach (var point in pointArray)
+ var figure = new PathFigure
{
- var height = point.Y;
+ StartPoint = pointArray[0]
+ };
+ figure.Segments.Add(new PolyLineSegment(pointArray, true));
- if (height < 0)
- {
- height = -height;
- }
+ wavePath.Data = new PathGeometry { Figures = { figure } };
+ wavePath.Stroke = brush;
+ }
- //每根竖条的四个角坐标
- var endPoints = new[]
- {
- new Point(point.X, point.Y + yOffset), //左下角
- new Point(point.X, point.Y + height + yOffset), //左上角
- new Point(point.X + stripWidth, point.Y + height + yOffset), //右上角
- new Point(point.X + stripWidth, point.Y + yOffset) //右下角
- };
+ ///
+ /// 画四周渐变边框
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 画图宽度
+ /// 高低音转化比例
+ private void DrawGradientBorder(
+ Rectangle topBorder, Rectangle bottomBorder, Rectangle leftBorder,
+ Rectangle rightBorder, Color inner, Color outer, double width, double bassScale
+ )
+ {
+ //边框粗细根据音频高低音变化
+ var thickness = (int)(width * bassScale);
- var figure = new PathFigure
- {
- StartPoint = endPoints[0]
- };
+ topBorder.Height = thickness;
+ bottomBorder.Height = thickness;
+ leftBorder.Width = thickness;
+ rightBorder.Width = thickness;
- figure.Segments.Add(new PolyLineSegment(endPoints, false));
- geometry.Children.Add(new PathGeometry { Figures = { figure } });
- }
-
- stripsPath.Data = geometry;
-
- //设置频谱竖条的渐变色
- var linearGradientBrush = new LinearGradientBrush(
- bottomColor, topColor, new Point(0, 0), new Point(0, 1)
- );
- stripsPath.Fill = linearGradientBrush;
+ topBorder.Fill = new LinearGradientBrush(outer, inner, 90);
+ bottomBorder.Fill = new LinearGradientBrush(inner, outer, 90);
+ leftBorder.Fill = new LinearGradientBrush(outer, inner, 0);
+ rightBorder.Fill = new LinearGradientBrush(inner, outer, 0);
}
}
}
\ No newline at end of file
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs
index 43f84fd..91441a2 100644
--- a/Correlator/Dialog/CheckResponseDialog.xaml.cs
+++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs
@@ -231,7 +231,7 @@
if (RedSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev1);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1);
_redResponseTimer.Start();
ReCheckButton.IsEnabled = true;
@@ -239,11 +239,11 @@
else if (RedSensorStepBar.StepIndex == 2)
{
//下发数据全部正常指令
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev1}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev1}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.RedSensorOriginalResp orderby pair.Key select pair;
@@ -266,7 +266,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev1, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev1, tags);
#endregion
}
@@ -315,18 +315,18 @@
if (BlueSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev2);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2);
_blueResponseTimer.Start();
ReCheckButton.IsEnabled = true;
}
else if (BlueSensorStepBar.StepIndex == 2)
{
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev2}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev2}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.BlueSensorOriginalResp orderby pair.Key select pair;
@@ -349,7 +349,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev2, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev2, tags);
#endregion
}
@@ -396,7 +396,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, redIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray);
}
else
{
@@ -417,7 +417,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, blueIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray);
}
};
}
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml b/Correlator/Dialog/SimplyAuditionDialog.xaml
index 5fd8124..cd03b74 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml
@@ -9,7 +9,7 @@
xmlns:prism="http://prismlibrary.com/"
xmlns:vm="clr-namespace:Correlator.ViewModels"
Width="600"
- Height="400"
+ Height="480"
d:DataContext="{d:DesignInstance Type=vm:SimplyAuditionDialogViewModel}"
Loaded="SimplyAuditionDialog_OnLoaded"
Unloaded="SimplyAuditionDialog_OnUnloaded"
@@ -187,10 +187,15 @@
-
+ Background="{StaticResource MainThemeColor}">
+
+
+
+
+
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
index 3747ce0..41cb280 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
@@ -6,6 +7,8 @@
using System.Windows.Threading;
using Correlator.DataService;
using Correlator.Util;
+using NAudio.CoreAudioApi;
+using NAudio.Wave;
namespace Correlator.Dialog
{
@@ -16,6 +19,7 @@
{
private readonly AudioVisualizer _visualizer; // 可视化
private double[] _spectrumData; // 频谱数据
+ private readonly WasapiCapture _capture; // 音频捕获
private int _colorIndex;
private readonly Color[] _allColors;
@@ -29,29 +33,44 @@
Interval = new TimeSpan(0, 0, 0, 0, 30)
};
- public SimplyAuditionDialog(IApplicationDataService dataService, IAudioService audioService)
+ public SimplyAuditionDialog(IApplicationDataService dataService)
{
InitializeComponent();
- // _visualizer = dataService.GetAudioVisualizer(256);
- // _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
- //
- // audioService.AudioVisualizer = _visualizer;
- //
- // _dataTimer.Tick += DataTimer_Tick;
- // _drawingTimer.Tick += DrawingTimer_Tick;
+ _capture = new WasapiLoopbackCapture(); // 捕获电脑发出的声音
+ _visualizer = dataService.GetAudioVisualizer(512);
+ _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
+
+ _capture.WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(7500, 1);
+ _capture.DataAvailable += delegate(object o, WaveInEventArgs args)
+ {
+ var length = args.BytesRecorded / 4; // 采样的数量 (每一个采样是 4 字节)
+ var result = new double[length];
+
+ for (var i = 0; i < length; i++)
+ {
+ result[i] = BitConverter.ToSingle(args.Buffer, i * 4); // 取出采样值
+ }
+
+ _visualizer.PushSampleData(result); // 将新的采样存储到 可视化器 中
+ };
+
+ _dataTimer.Tick += DataTimer_Tick;
+ _drawingTimer.Tick += DrawingTimer_Tick;
}
private void SimplyAuditionDialog_OnLoaded(object sender, RoutedEventArgs e)
{
- // _dataTimer.Start();
- // _drawingTimer.Start();
+ _capture.StartRecording();
+ _dataTimer.Start();
+ _drawingTimer.Start();
}
private void SimplyAuditionDialog_OnUnloaded(object sender, RoutedEventArgs e)
{
- // _drawingTimer.Stop();
- // _dataTimer.Stop();
+ _drawingTimer.Stop();
+ _dataTimer.Stop();
+ _capture.StopRecording();
}
///
@@ -62,7 +81,7 @@
private void DataTimer_Tick(object sender, EventArgs e)
{
var newSpectrumData = _visualizer.GetSpectrumData(); // 从可视化器中获取频谱数据
- newSpectrumData = AudioVisualizer.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
+ newSpectrumData = AudioDataHub.Get.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
if (_spectrumData == null) // 如果已经存储的频谱数据为空, 则把新的频谱数据直接赋值上去
{
@@ -92,80 +111,90 @@
var color1 = _allColors[_colorIndex % _allColors.Length];
var color2 = _allColors[(_colorIndex + 200) % _allColors.Length];
- DrawGradientStrips(
- StripsPath, color1, color2,
- _spectrumData, _spectrumData.Length,
- StripsPath.ActualWidth, 0, StripsPath.ActualHeight,
- 2, -StripsPath.ActualHeight * 200
+ var bassArea = AudioDataHub.Get.TakeSpectrumOfFrequency(
+ _spectrumData, RuntimeCache.AudioSampleRate, 250
+ );
+ var bassScale = bassArea.Average() * 100; //低音区
+
+ //波形曲线
+ var curveBrush = new SolidColorBrush(color1);
+ DrawCurve(
+ SampleWavePath, curveBrush,
+ _visualizer.SampleData, _visualizer.SampleData.Length,
+ SampleWavePanel.ActualWidth, 0, SampleWavePanel.ActualHeight / 2,
+ Math.Min(SampleWavePanel.ActualHeight / 2, 50)
+ );
+
+ //四周边框
+ DrawGradientBorder(
+ TopBorder, BottomBorder, LeftBorder, RightBorder,
+ Color.FromArgb(0, color1.R, color1.G, color1.B), color2,
+ SampleWavePanel.ActualWidth / 3, bassScale
);
}
///
- /// 绘制渐变的条形
+ /// 画曲线
///
- /// 绘图目标
- /// 下方颜色
- /// 上方颜色
- /// 频谱数据
- /// 条形的数量
- /// 绘图的宽度
- /// 绘图的起始 X 坐标
- /// 绘图的起始 Y 坐标
- /// 条形与条形之间的间隔(像素)
- /// 控制波形图波峰高度
- private void DrawGradientStrips(
- Path stripsPath, Color bottomColor, Color topColor, double[] spectrumData,
- int stripCount, double drawingWidth, double xOffset, double yOffset, double spacing, double scale
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 控制波形图波峰高度和波谷深度
+ private void DrawCurve(
+ Path wavePath, Brush brush, double[] spectrumData, int pointCount, double drawingWidth,
+ double xOffset, double yOffset, double scale
)
{
- //竖条宽度
- var stripWidth = (drawingWidth - spacing * stripCount) / stripCount;
- var pointArray = new Point[stripCount];
-
- for (var i = 0; i < stripCount; i++)
+ var pointArray = new Point[pointCount];
+ for (var i = 0; i < pointCount; i++)
{
- var x = stripWidth * i + spacing * i + xOffset;
- var y = spectrumData[i * spectrumData.Length / stripCount] * scale; // height
- //给所有频谱位置赋值
+ var x = i * drawingWidth / pointCount + xOffset;
+ var y = spectrumData[i * spectrumData.Length / pointCount] * scale + yOffset;
pointArray[i] = new Point(x, y);
}
- //生成一系列频谱竖条
- var geometry = new GeometryGroup();
- foreach (var point in pointArray)
+ var figure = new PathFigure
{
- var height = point.Y;
+ StartPoint = pointArray[0]
+ };
+ figure.Segments.Add(new PolyLineSegment(pointArray, true));
- if (height < 0)
- {
- height = -height;
- }
+ wavePath.Data = new PathGeometry { Figures = { figure } };
+ wavePath.Stroke = brush;
+ }
- //每根竖条的四个角坐标
- var endPoints = new[]
- {
- new Point(point.X, point.Y + yOffset), //左下角
- new Point(point.X, point.Y + height + yOffset), //左上角
- new Point(point.X + stripWidth, point.Y + height + yOffset), //右上角
- new Point(point.X + stripWidth, point.Y + yOffset) //右下角
- };
+ ///
+ /// 画四周渐变边框
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 画图宽度
+ /// 高低音转化比例
+ private void DrawGradientBorder(
+ Rectangle topBorder, Rectangle bottomBorder, Rectangle leftBorder,
+ Rectangle rightBorder, Color inner, Color outer, double width, double bassScale
+ )
+ {
+ //边框粗细根据音频高低音变化
+ var thickness = (int)(width * bassScale);
- var figure = new PathFigure
- {
- StartPoint = endPoints[0]
- };
+ topBorder.Height = thickness;
+ bottomBorder.Height = thickness;
+ leftBorder.Width = thickness;
+ rightBorder.Width = thickness;
- figure.Segments.Add(new PolyLineSegment(endPoints, false));
- geometry.Children.Add(new PathGeometry { Figures = { figure } });
- }
-
- stripsPath.Data = geometry;
-
- //设置频谱竖条的渐变色
- var linearGradientBrush = new LinearGradientBrush(
- bottomColor, topColor, new Point(0, 0), new Point(0, 1)
- );
- stripsPath.Fill = linearGradientBrush;
+ topBorder.Fill = new LinearGradientBrush(outer, inner, 90);
+ bottomBorder.Fill = new LinearGradientBrush(inner, outer, 90);
+ leftBorder.Fill = new LinearGradientBrush(outer, inner, 0);
+ rightBorder.Fill = new LinearGradientBrush(inner, outer, 0);
}
}
}
\ No newline at end of file
diff --git a/Correlator/SensorHubTag/DevCode.cs b/Correlator/SensorHubTag/DevCode.cs
deleted file mode 100644
index afd5e8f..0000000
--- a/Correlator/SensorHubTag/DevCode.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Correlator.SensorHubTag
-{
- public static class DevCode
- {
- public static string Dev1 => "211700082201";
-
- public static string Dev2 => "211700082202";
- }
-}
\ No newline at end of file
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs
index 43f84fd..91441a2 100644
--- a/Correlator/Dialog/CheckResponseDialog.xaml.cs
+++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs
@@ -231,7 +231,7 @@
if (RedSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev1);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1);
_redResponseTimer.Start();
ReCheckButton.IsEnabled = true;
@@ -239,11 +239,11 @@
else if (RedSensorStepBar.StepIndex == 2)
{
//下发数据全部正常指令
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev1}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev1}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.RedSensorOriginalResp orderby pair.Key select pair;
@@ -266,7 +266,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev1, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev1, tags);
#endregion
}
@@ -315,18 +315,18 @@
if (BlueSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev2);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2);
_blueResponseTimer.Start();
ReCheckButton.IsEnabled = true;
}
else if (BlueSensorStepBar.StepIndex == 2)
{
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev2}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev2}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.BlueSensorOriginalResp orderby pair.Key select pair;
@@ -349,7 +349,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev2, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev2, tags);
#endregion
}
@@ -396,7 +396,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, redIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray);
}
else
{
@@ -417,7 +417,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, blueIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray);
}
};
}
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml b/Correlator/Dialog/SimplyAuditionDialog.xaml
index 5fd8124..cd03b74 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml
@@ -9,7 +9,7 @@
xmlns:prism="http://prismlibrary.com/"
xmlns:vm="clr-namespace:Correlator.ViewModels"
Width="600"
- Height="400"
+ Height="480"
d:DataContext="{d:DesignInstance Type=vm:SimplyAuditionDialogViewModel}"
Loaded="SimplyAuditionDialog_OnLoaded"
Unloaded="SimplyAuditionDialog_OnUnloaded"
@@ -187,10 +187,15 @@
-
+ Background="{StaticResource MainThemeColor}">
+
+
+
+
+
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
index 3747ce0..41cb280 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
@@ -6,6 +7,8 @@
using System.Windows.Threading;
using Correlator.DataService;
using Correlator.Util;
+using NAudio.CoreAudioApi;
+using NAudio.Wave;
namespace Correlator.Dialog
{
@@ -16,6 +19,7 @@
{
private readonly AudioVisualizer _visualizer; // 可视化
private double[] _spectrumData; // 频谱数据
+ private readonly WasapiCapture _capture; // 音频捕获
private int _colorIndex;
private readonly Color[] _allColors;
@@ -29,29 +33,44 @@
Interval = new TimeSpan(0, 0, 0, 0, 30)
};
- public SimplyAuditionDialog(IApplicationDataService dataService, IAudioService audioService)
+ public SimplyAuditionDialog(IApplicationDataService dataService)
{
InitializeComponent();
- // _visualizer = dataService.GetAudioVisualizer(256);
- // _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
- //
- // audioService.AudioVisualizer = _visualizer;
- //
- // _dataTimer.Tick += DataTimer_Tick;
- // _drawingTimer.Tick += DrawingTimer_Tick;
+ _capture = new WasapiLoopbackCapture(); // 捕获电脑发出的声音
+ _visualizer = dataService.GetAudioVisualizer(512);
+ _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
+
+ _capture.WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(7500, 1);
+ _capture.DataAvailable += delegate(object o, WaveInEventArgs args)
+ {
+ var length = args.BytesRecorded / 4; // 采样的数量 (每一个采样是 4 字节)
+ var result = new double[length];
+
+ for (var i = 0; i < length; i++)
+ {
+ result[i] = BitConverter.ToSingle(args.Buffer, i * 4); // 取出采样值
+ }
+
+ _visualizer.PushSampleData(result); // 将新的采样存储到 可视化器 中
+ };
+
+ _dataTimer.Tick += DataTimer_Tick;
+ _drawingTimer.Tick += DrawingTimer_Tick;
}
private void SimplyAuditionDialog_OnLoaded(object sender, RoutedEventArgs e)
{
- // _dataTimer.Start();
- // _drawingTimer.Start();
+ _capture.StartRecording();
+ _dataTimer.Start();
+ _drawingTimer.Start();
}
private void SimplyAuditionDialog_OnUnloaded(object sender, RoutedEventArgs e)
{
- // _drawingTimer.Stop();
- // _dataTimer.Stop();
+ _drawingTimer.Stop();
+ _dataTimer.Stop();
+ _capture.StopRecording();
}
///
@@ -62,7 +81,7 @@
private void DataTimer_Tick(object sender, EventArgs e)
{
var newSpectrumData = _visualizer.GetSpectrumData(); // 从可视化器中获取频谱数据
- newSpectrumData = AudioVisualizer.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
+ newSpectrumData = AudioDataHub.Get.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
if (_spectrumData == null) // 如果已经存储的频谱数据为空, 则把新的频谱数据直接赋值上去
{
@@ -92,80 +111,90 @@
var color1 = _allColors[_colorIndex % _allColors.Length];
var color2 = _allColors[(_colorIndex + 200) % _allColors.Length];
- DrawGradientStrips(
- StripsPath, color1, color2,
- _spectrumData, _spectrumData.Length,
- StripsPath.ActualWidth, 0, StripsPath.ActualHeight,
- 2, -StripsPath.ActualHeight * 200
+ var bassArea = AudioDataHub.Get.TakeSpectrumOfFrequency(
+ _spectrumData, RuntimeCache.AudioSampleRate, 250
+ );
+ var bassScale = bassArea.Average() * 100; //低音区
+
+ //波形曲线
+ var curveBrush = new SolidColorBrush(color1);
+ DrawCurve(
+ SampleWavePath, curveBrush,
+ _visualizer.SampleData, _visualizer.SampleData.Length,
+ SampleWavePanel.ActualWidth, 0, SampleWavePanel.ActualHeight / 2,
+ Math.Min(SampleWavePanel.ActualHeight / 2, 50)
+ );
+
+ //四周边框
+ DrawGradientBorder(
+ TopBorder, BottomBorder, LeftBorder, RightBorder,
+ Color.FromArgb(0, color1.R, color1.G, color1.B), color2,
+ SampleWavePanel.ActualWidth / 3, bassScale
);
}
///
- /// 绘制渐变的条形
+ /// 画曲线
///
- /// 绘图目标
- /// 下方颜色
- /// 上方颜色
- /// 频谱数据
- /// 条形的数量
- /// 绘图的宽度
- /// 绘图的起始 X 坐标
- /// 绘图的起始 Y 坐标
- /// 条形与条形之间的间隔(像素)
- /// 控制波形图波峰高度
- private void DrawGradientStrips(
- Path stripsPath, Color bottomColor, Color topColor, double[] spectrumData,
- int stripCount, double drawingWidth, double xOffset, double yOffset, double spacing, double scale
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 控制波形图波峰高度和波谷深度
+ private void DrawCurve(
+ Path wavePath, Brush brush, double[] spectrumData, int pointCount, double drawingWidth,
+ double xOffset, double yOffset, double scale
)
{
- //竖条宽度
- var stripWidth = (drawingWidth - spacing * stripCount) / stripCount;
- var pointArray = new Point[stripCount];
-
- for (var i = 0; i < stripCount; i++)
+ var pointArray = new Point[pointCount];
+ for (var i = 0; i < pointCount; i++)
{
- var x = stripWidth * i + spacing * i + xOffset;
- var y = spectrumData[i * spectrumData.Length / stripCount] * scale; // height
- //给所有频谱位置赋值
+ var x = i * drawingWidth / pointCount + xOffset;
+ var y = spectrumData[i * spectrumData.Length / pointCount] * scale + yOffset;
pointArray[i] = new Point(x, y);
}
- //生成一系列频谱竖条
- var geometry = new GeometryGroup();
- foreach (var point in pointArray)
+ var figure = new PathFigure
{
- var height = point.Y;
+ StartPoint = pointArray[0]
+ };
+ figure.Segments.Add(new PolyLineSegment(pointArray, true));
- if (height < 0)
- {
- height = -height;
- }
+ wavePath.Data = new PathGeometry { Figures = { figure } };
+ wavePath.Stroke = brush;
+ }
- //每根竖条的四个角坐标
- var endPoints = new[]
- {
- new Point(point.X, point.Y + yOffset), //左下角
- new Point(point.X, point.Y + height + yOffset), //左上角
- new Point(point.X + stripWidth, point.Y + height + yOffset), //右上角
- new Point(point.X + stripWidth, point.Y + yOffset) //右下角
- };
+ ///
+ /// 画四周渐变边框
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 画图宽度
+ /// 高低音转化比例
+ private void DrawGradientBorder(
+ Rectangle topBorder, Rectangle bottomBorder, Rectangle leftBorder,
+ Rectangle rightBorder, Color inner, Color outer, double width, double bassScale
+ )
+ {
+ //边框粗细根据音频高低音变化
+ var thickness = (int)(width * bassScale);
- var figure = new PathFigure
- {
- StartPoint = endPoints[0]
- };
+ topBorder.Height = thickness;
+ bottomBorder.Height = thickness;
+ leftBorder.Width = thickness;
+ rightBorder.Width = thickness;
- figure.Segments.Add(new PolyLineSegment(endPoints, false));
- geometry.Children.Add(new PathGeometry { Figures = { figure } });
- }
-
- stripsPath.Data = geometry;
-
- //设置频谱竖条的渐变色
- var linearGradientBrush = new LinearGradientBrush(
- bottomColor, topColor, new Point(0, 0), new Point(0, 1)
- );
- stripsPath.Fill = linearGradientBrush;
+ topBorder.Fill = new LinearGradientBrush(outer, inner, 90);
+ bottomBorder.Fill = new LinearGradientBrush(inner, outer, 90);
+ leftBorder.Fill = new LinearGradientBrush(outer, inner, 0);
+ rightBorder.Fill = new LinearGradientBrush(inner, outer, 0);
}
}
}
\ No newline at end of file
diff --git a/Correlator/SensorHubTag/DevCode.cs b/Correlator/SensorHubTag/DevCode.cs
deleted file mode 100644
index afd5e8f..0000000
--- a/Correlator/SensorHubTag/DevCode.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Correlator.SensorHubTag
-{
- public static class DevCode
- {
- public static string Dev1 => "211700082201";
-
- public static string Dev2 => "211700082202";
- }
-}
\ No newline at end of file
diff --git a/Correlator/Util/AudioDataHub.cs b/Correlator/Util/AudioDataHub.cs
new file mode 100644
index 0000000..72d62ea
--- /dev/null
+++ b/Correlator/Util/AudioDataHub.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+
+namespace Correlator.Util
+{
+ ///
+ /// 音频可视化数据处理
+ ///
+ public class AudioDataHub
+ {
+ #region 懒汉单例模式
+
+ private static readonly Lazy Lazy = new Lazy(() => new AudioDataHub());
+
+ public static AudioDataHub Get => Lazy.Value;
+
+
+ private AudioDataHub()
+ {
+ }
+
+ #endregion
+
+ private double[] _smoothResult;
+
+ public double[] TakeSpectrumOfFrequency(double[] spectrum, double sampleRate, double frequency)
+ {
+ var frequencyPerSample = sampleRate / spectrum.Length;
+
+ var lengthInNeed = (int)Math.Min(frequency / frequencyPerSample, spectrum.Length);
+ var result = new double[lengthInNeed];
+ Array.Copy(spectrum, 0, result, 0, lengthInNeed);
+ return result;
+ }
+
+ ///
+ /// 简单的数据模糊
+ ///
+ /// 数据
+ /// 模糊半径
+ /// 结果
+ public double[] MakeSmooth(double[] data, int radius)
+ {
+ var weights = GetWeights(radius);
+ var buffer = new double[1 + radius * 2];
+
+ _smoothResult = new double[data.Length];
+ if (data.Length < radius)
+ {
+ data.Average();
+ _smoothResult.SetValue(data, 0);
+ return _smoothResult;
+ }
+
+ for (var i = 0; i < radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = radius; i < data.Length - radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[j] = data[i - j];
+ }
+
+ buffer[radius] = data[i];
+
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + j + 1] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = data.Length - radius; i < data.Length; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i - j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ return _smoothResult;
+ }
+
+ private double[] GetWeights(int radius)
+ {
+ double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
+
+ var len = 1 + radius * 2; // 长度
+ var end = len - 1; // 最后的索引
+ var radiusF = (double)radius; // 半径浮点数
+ var weights = new double[len]; // 权重
+
+ for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
+ {
+ weights[radius + i] = Gaussian(i / radiusF);
+ }
+
+ for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
+ {
+ weights[i] = weights[end - i];
+ }
+
+ var total = weights.Sum();
+ for (var i = 0; i < len; i++) // 使权重合为 0
+ {
+ weights[i] /= total;
+ }
+
+ return weights;
+ }
+
+ private void ApplyWeights(double[] buffer, double[] weights)
+ {
+ var len = buffer.Length;
+ for (var i = 0; i < len; i++)
+ {
+ buffer[i] *= weights[i];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs
index 43f84fd..91441a2 100644
--- a/Correlator/Dialog/CheckResponseDialog.xaml.cs
+++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs
@@ -231,7 +231,7 @@
if (RedSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev1);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1);
_redResponseTimer.Start();
ReCheckButton.IsEnabled = true;
@@ -239,11 +239,11 @@
else if (RedSensorStepBar.StepIndex == 2)
{
//下发数据全部正常指令
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev1}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev1}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.RedSensorOriginalResp orderby pair.Key select pair;
@@ -266,7 +266,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev1, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev1, tags);
#endregion
}
@@ -315,18 +315,18 @@
if (BlueSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev2);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2);
_blueResponseTimer.Start();
ReCheckButton.IsEnabled = true;
}
else if (BlueSensorStepBar.StepIndex == 2)
{
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev2}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev2}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.BlueSensorOriginalResp orderby pair.Key select pair;
@@ -349,7 +349,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev2, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev2, tags);
#endregion
}
@@ -396,7 +396,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, redIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray);
}
else
{
@@ -417,7 +417,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, blueIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray);
}
};
}
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml b/Correlator/Dialog/SimplyAuditionDialog.xaml
index 5fd8124..cd03b74 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml
@@ -9,7 +9,7 @@
xmlns:prism="http://prismlibrary.com/"
xmlns:vm="clr-namespace:Correlator.ViewModels"
Width="600"
- Height="400"
+ Height="480"
d:DataContext="{d:DesignInstance Type=vm:SimplyAuditionDialogViewModel}"
Loaded="SimplyAuditionDialog_OnLoaded"
Unloaded="SimplyAuditionDialog_OnUnloaded"
@@ -187,10 +187,15 @@
-
+ Background="{StaticResource MainThemeColor}">
+
+
+
+
+
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
index 3747ce0..41cb280 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
@@ -6,6 +7,8 @@
using System.Windows.Threading;
using Correlator.DataService;
using Correlator.Util;
+using NAudio.CoreAudioApi;
+using NAudio.Wave;
namespace Correlator.Dialog
{
@@ -16,6 +19,7 @@
{
private readonly AudioVisualizer _visualizer; // 可视化
private double[] _spectrumData; // 频谱数据
+ private readonly WasapiCapture _capture; // 音频捕获
private int _colorIndex;
private readonly Color[] _allColors;
@@ -29,29 +33,44 @@
Interval = new TimeSpan(0, 0, 0, 0, 30)
};
- public SimplyAuditionDialog(IApplicationDataService dataService, IAudioService audioService)
+ public SimplyAuditionDialog(IApplicationDataService dataService)
{
InitializeComponent();
- // _visualizer = dataService.GetAudioVisualizer(256);
- // _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
- //
- // audioService.AudioVisualizer = _visualizer;
- //
- // _dataTimer.Tick += DataTimer_Tick;
- // _drawingTimer.Tick += DrawingTimer_Tick;
+ _capture = new WasapiLoopbackCapture(); // 捕获电脑发出的声音
+ _visualizer = dataService.GetAudioVisualizer(512);
+ _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
+
+ _capture.WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(7500, 1);
+ _capture.DataAvailable += delegate(object o, WaveInEventArgs args)
+ {
+ var length = args.BytesRecorded / 4; // 采样的数量 (每一个采样是 4 字节)
+ var result = new double[length];
+
+ for (var i = 0; i < length; i++)
+ {
+ result[i] = BitConverter.ToSingle(args.Buffer, i * 4); // 取出采样值
+ }
+
+ _visualizer.PushSampleData(result); // 将新的采样存储到 可视化器 中
+ };
+
+ _dataTimer.Tick += DataTimer_Tick;
+ _drawingTimer.Tick += DrawingTimer_Tick;
}
private void SimplyAuditionDialog_OnLoaded(object sender, RoutedEventArgs e)
{
- // _dataTimer.Start();
- // _drawingTimer.Start();
+ _capture.StartRecording();
+ _dataTimer.Start();
+ _drawingTimer.Start();
}
private void SimplyAuditionDialog_OnUnloaded(object sender, RoutedEventArgs e)
{
- // _drawingTimer.Stop();
- // _dataTimer.Stop();
+ _drawingTimer.Stop();
+ _dataTimer.Stop();
+ _capture.StopRecording();
}
///
@@ -62,7 +81,7 @@
private void DataTimer_Tick(object sender, EventArgs e)
{
var newSpectrumData = _visualizer.GetSpectrumData(); // 从可视化器中获取频谱数据
- newSpectrumData = AudioVisualizer.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
+ newSpectrumData = AudioDataHub.Get.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
if (_spectrumData == null) // 如果已经存储的频谱数据为空, 则把新的频谱数据直接赋值上去
{
@@ -92,80 +111,90 @@
var color1 = _allColors[_colorIndex % _allColors.Length];
var color2 = _allColors[(_colorIndex + 200) % _allColors.Length];
- DrawGradientStrips(
- StripsPath, color1, color2,
- _spectrumData, _spectrumData.Length,
- StripsPath.ActualWidth, 0, StripsPath.ActualHeight,
- 2, -StripsPath.ActualHeight * 200
+ var bassArea = AudioDataHub.Get.TakeSpectrumOfFrequency(
+ _spectrumData, RuntimeCache.AudioSampleRate, 250
+ );
+ var bassScale = bassArea.Average() * 100; //低音区
+
+ //波形曲线
+ var curveBrush = new SolidColorBrush(color1);
+ DrawCurve(
+ SampleWavePath, curveBrush,
+ _visualizer.SampleData, _visualizer.SampleData.Length,
+ SampleWavePanel.ActualWidth, 0, SampleWavePanel.ActualHeight / 2,
+ Math.Min(SampleWavePanel.ActualHeight / 2, 50)
+ );
+
+ //四周边框
+ DrawGradientBorder(
+ TopBorder, BottomBorder, LeftBorder, RightBorder,
+ Color.FromArgb(0, color1.R, color1.G, color1.B), color2,
+ SampleWavePanel.ActualWidth / 3, bassScale
);
}
///
- /// 绘制渐变的条形
+ /// 画曲线
///
- /// 绘图目标
- /// 下方颜色
- /// 上方颜色
- /// 频谱数据
- /// 条形的数量
- /// 绘图的宽度
- /// 绘图的起始 X 坐标
- /// 绘图的起始 Y 坐标
- /// 条形与条形之间的间隔(像素)
- /// 控制波形图波峰高度
- private void DrawGradientStrips(
- Path stripsPath, Color bottomColor, Color topColor, double[] spectrumData,
- int stripCount, double drawingWidth, double xOffset, double yOffset, double spacing, double scale
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 控制波形图波峰高度和波谷深度
+ private void DrawCurve(
+ Path wavePath, Brush brush, double[] spectrumData, int pointCount, double drawingWidth,
+ double xOffset, double yOffset, double scale
)
{
- //竖条宽度
- var stripWidth = (drawingWidth - spacing * stripCount) / stripCount;
- var pointArray = new Point[stripCount];
-
- for (var i = 0; i < stripCount; i++)
+ var pointArray = new Point[pointCount];
+ for (var i = 0; i < pointCount; i++)
{
- var x = stripWidth * i + spacing * i + xOffset;
- var y = spectrumData[i * spectrumData.Length / stripCount] * scale; // height
- //给所有频谱位置赋值
+ var x = i * drawingWidth / pointCount + xOffset;
+ var y = spectrumData[i * spectrumData.Length / pointCount] * scale + yOffset;
pointArray[i] = new Point(x, y);
}
- //生成一系列频谱竖条
- var geometry = new GeometryGroup();
- foreach (var point in pointArray)
+ var figure = new PathFigure
{
- var height = point.Y;
+ StartPoint = pointArray[0]
+ };
+ figure.Segments.Add(new PolyLineSegment(pointArray, true));
- if (height < 0)
- {
- height = -height;
- }
+ wavePath.Data = new PathGeometry { Figures = { figure } };
+ wavePath.Stroke = brush;
+ }
- //每根竖条的四个角坐标
- var endPoints = new[]
- {
- new Point(point.X, point.Y + yOffset), //左下角
- new Point(point.X, point.Y + height + yOffset), //左上角
- new Point(point.X + stripWidth, point.Y + height + yOffset), //右上角
- new Point(point.X + stripWidth, point.Y + yOffset) //右下角
- };
+ ///
+ /// 画四周渐变边框
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 画图宽度
+ /// 高低音转化比例
+ private void DrawGradientBorder(
+ Rectangle topBorder, Rectangle bottomBorder, Rectangle leftBorder,
+ Rectangle rightBorder, Color inner, Color outer, double width, double bassScale
+ )
+ {
+ //边框粗细根据音频高低音变化
+ var thickness = (int)(width * bassScale);
- var figure = new PathFigure
- {
- StartPoint = endPoints[0]
- };
+ topBorder.Height = thickness;
+ bottomBorder.Height = thickness;
+ leftBorder.Width = thickness;
+ rightBorder.Width = thickness;
- figure.Segments.Add(new PolyLineSegment(endPoints, false));
- geometry.Children.Add(new PathGeometry { Figures = { figure } });
- }
-
- stripsPath.Data = geometry;
-
- //设置频谱竖条的渐变色
- var linearGradientBrush = new LinearGradientBrush(
- bottomColor, topColor, new Point(0, 0), new Point(0, 1)
- );
- stripsPath.Fill = linearGradientBrush;
+ topBorder.Fill = new LinearGradientBrush(outer, inner, 90);
+ bottomBorder.Fill = new LinearGradientBrush(inner, outer, 90);
+ leftBorder.Fill = new LinearGradientBrush(outer, inner, 0);
+ rightBorder.Fill = new LinearGradientBrush(inner, outer, 0);
}
}
}
\ No newline at end of file
diff --git a/Correlator/SensorHubTag/DevCode.cs b/Correlator/SensorHubTag/DevCode.cs
deleted file mode 100644
index afd5e8f..0000000
--- a/Correlator/SensorHubTag/DevCode.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Correlator.SensorHubTag
-{
- public static class DevCode
- {
- public static string Dev1 => "211700082201";
-
- public static string Dev2 => "211700082202";
- }
-}
\ No newline at end of file
diff --git a/Correlator/Util/AudioDataHub.cs b/Correlator/Util/AudioDataHub.cs
new file mode 100644
index 0000000..72d62ea
--- /dev/null
+++ b/Correlator/Util/AudioDataHub.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+
+namespace Correlator.Util
+{
+ ///
+ /// 音频可视化数据处理
+ ///
+ public class AudioDataHub
+ {
+ #region 懒汉单例模式
+
+ private static readonly Lazy Lazy = new Lazy(() => new AudioDataHub());
+
+ public static AudioDataHub Get => Lazy.Value;
+
+
+ private AudioDataHub()
+ {
+ }
+
+ #endregion
+
+ private double[] _smoothResult;
+
+ public double[] TakeSpectrumOfFrequency(double[] spectrum, double sampleRate, double frequency)
+ {
+ var frequencyPerSample = sampleRate / spectrum.Length;
+
+ var lengthInNeed = (int)Math.Min(frequency / frequencyPerSample, spectrum.Length);
+ var result = new double[lengthInNeed];
+ Array.Copy(spectrum, 0, result, 0, lengthInNeed);
+ return result;
+ }
+
+ ///
+ /// 简单的数据模糊
+ ///
+ /// 数据
+ /// 模糊半径
+ /// 结果
+ public double[] MakeSmooth(double[] data, int radius)
+ {
+ var weights = GetWeights(radius);
+ var buffer = new double[1 + radius * 2];
+
+ _smoothResult = new double[data.Length];
+ if (data.Length < radius)
+ {
+ data.Average();
+ _smoothResult.SetValue(data, 0);
+ return _smoothResult;
+ }
+
+ for (var i = 0; i < radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = radius; i < data.Length - radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[j] = data[i - j];
+ }
+
+ buffer[radius] = data[i];
+
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + j + 1] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = data.Length - radius; i < data.Length; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i - j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ return _smoothResult;
+ }
+
+ private double[] GetWeights(int radius)
+ {
+ double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
+
+ var len = 1 + radius * 2; // 长度
+ var end = len - 1; // 最后的索引
+ var radiusF = (double)radius; // 半径浮点数
+ var weights = new double[len]; // 权重
+
+ for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
+ {
+ weights[radius + i] = Gaussian(i / radiusF);
+ }
+
+ for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
+ {
+ weights[i] = weights[end - i];
+ }
+
+ var total = weights.Sum();
+ for (var i = 0; i < len; i++) // 使权重合为 0
+ {
+ weights[i] /= total;
+ }
+
+ return weights;
+ }
+
+ private void ApplyWeights(double[] buffer, double[] weights)
+ {
+ var len = buffer.Length;
+ for (var i = 0; i < len; i++)
+ {
+ buffer[i] *= weights[i];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Correlator/Util/AudioVisualizer.cs b/Correlator/Util/AudioVisualizer.cs
index 9a888f5..393f7df 100644
--- a/Correlator/Util/AudioVisualizer.cs
+++ b/Correlator/Util/AudioVisualizer.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using FftSharp;
using FftSharp.Windows;
using Complex = System.Numerics.Complex;
@@ -13,6 +12,8 @@
///
public double[] SampleData { get; }
+ private Complex[] _data;
+
///
///
///
@@ -63,126 +64,27 @@
public double[] GetSpectrumData()
{
var len = SampleData.Length;
- var data = new Complex[len];
-
+ _data = new Complex[len];
+
for (var i = 0; i < len; i++)
{
- data[i] = new Complex(SampleData[i], 0);
+ _data[i] = new Complex(SampleData[i], 0);
}
-
- FFT.Forward(data);
-
+
+ FFT.Forward(_data);
+
var halfLen = len / 2;
var result = new double[halfLen]; // 傅里叶变换结果左右对称, 只需要取一半
for (var i = 0; i < halfLen; i++)
{
- result[i] = data[i].Magnitude / len;
+ result[i] = _data[i].Magnitude / len;
}
-
+
var window = new Bartlett();
window.Create(halfLen);
window.ApplyInPlace(result);
-
+
return result;
}
-
- ///
- /// 简单的数据模糊
- ///
- /// 数据
- /// 模糊半径
- /// 结果
- public static double[] MakeSmooth(double[] data, int radius)
- {
- var weights = GetWeights(radius);
- var buffer = new double[1 + radius * 2];
-
- var result = new double[data.Length];
- if (data.Length < radius)
- {
- data.Average();
- result.SetValue(data, 0);
- return result;
- }
-
- for (var i = 0; i < radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = radius; i < data.Length - radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[j] = data[i - j];
- }
-
- buffer[radius] = data[i];
-
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + j + 1] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = data.Length - radius; i < data.Length; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i - j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- return result;
- }
-
- private static double[] GetWeights(int radius)
- {
- double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
-
- var len = 1 + radius * 2; // 长度
- var end = len - 1; // 最后的索引
- var radiusF = (double)radius; // 半径浮点数
- var weights = new double[len]; // 权重
-
- for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
- {
- weights[radius + i] = Gaussian(i / radiusF);
- }
-
- for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
- {
- weights[i] = weights[end - i];
- }
-
- var total = weights.Sum();
- for (var i = 0; i < len; i++) // 使权重合为 0
- {
- weights[i] /= total;
- }
-
- return weights;
- }
-
- private static void ApplyWeights(double[] buffer, double[] weights)
- {
- var len = buffer.Length;
- for (var i = 0; i < len; i++)
- {
- buffer[i] *= weights[i];
- }
- }
}
}
\ No newline at end of file
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs
index 43f84fd..91441a2 100644
--- a/Correlator/Dialog/CheckResponseDialog.xaml.cs
+++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs
@@ -231,7 +231,7 @@
if (RedSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev1);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1);
_redResponseTimer.Start();
ReCheckButton.IsEnabled = true;
@@ -239,11 +239,11 @@
else if (RedSensorStepBar.StepIndex == 2)
{
//下发数据全部正常指令
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev1}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev1}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.RedSensorOriginalResp orderby pair.Key select pair;
@@ -266,7 +266,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev1, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev1, tags);
#endregion
}
@@ -315,18 +315,18 @@
if (BlueSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev2);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2);
_blueResponseTimer.Start();
ReCheckButton.IsEnabled = true;
}
else if (BlueSensorStepBar.StepIndex == 2)
{
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev2}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev2}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.BlueSensorOriginalResp orderby pair.Key select pair;
@@ -349,7 +349,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev2, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev2, tags);
#endregion
}
@@ -396,7 +396,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, redIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray);
}
else
{
@@ -417,7 +417,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, blueIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray);
}
};
}
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml b/Correlator/Dialog/SimplyAuditionDialog.xaml
index 5fd8124..cd03b74 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml
@@ -9,7 +9,7 @@
xmlns:prism="http://prismlibrary.com/"
xmlns:vm="clr-namespace:Correlator.ViewModels"
Width="600"
- Height="400"
+ Height="480"
d:DataContext="{d:DesignInstance Type=vm:SimplyAuditionDialogViewModel}"
Loaded="SimplyAuditionDialog_OnLoaded"
Unloaded="SimplyAuditionDialog_OnUnloaded"
@@ -187,10 +187,15 @@
-
+ Background="{StaticResource MainThemeColor}">
+
+
+
+
+
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
index 3747ce0..41cb280 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
@@ -6,6 +7,8 @@
using System.Windows.Threading;
using Correlator.DataService;
using Correlator.Util;
+using NAudio.CoreAudioApi;
+using NAudio.Wave;
namespace Correlator.Dialog
{
@@ -16,6 +19,7 @@
{
private readonly AudioVisualizer _visualizer; // 可视化
private double[] _spectrumData; // 频谱数据
+ private readonly WasapiCapture _capture; // 音频捕获
private int _colorIndex;
private readonly Color[] _allColors;
@@ -29,29 +33,44 @@
Interval = new TimeSpan(0, 0, 0, 0, 30)
};
- public SimplyAuditionDialog(IApplicationDataService dataService, IAudioService audioService)
+ public SimplyAuditionDialog(IApplicationDataService dataService)
{
InitializeComponent();
- // _visualizer = dataService.GetAudioVisualizer(256);
- // _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
- //
- // audioService.AudioVisualizer = _visualizer;
- //
- // _dataTimer.Tick += DataTimer_Tick;
- // _drawingTimer.Tick += DrawingTimer_Tick;
+ _capture = new WasapiLoopbackCapture(); // 捕获电脑发出的声音
+ _visualizer = dataService.GetAudioVisualizer(512);
+ _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
+
+ _capture.WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(7500, 1);
+ _capture.DataAvailable += delegate(object o, WaveInEventArgs args)
+ {
+ var length = args.BytesRecorded / 4; // 采样的数量 (每一个采样是 4 字节)
+ var result = new double[length];
+
+ for (var i = 0; i < length; i++)
+ {
+ result[i] = BitConverter.ToSingle(args.Buffer, i * 4); // 取出采样值
+ }
+
+ _visualizer.PushSampleData(result); // 将新的采样存储到 可视化器 中
+ };
+
+ _dataTimer.Tick += DataTimer_Tick;
+ _drawingTimer.Tick += DrawingTimer_Tick;
}
private void SimplyAuditionDialog_OnLoaded(object sender, RoutedEventArgs e)
{
- // _dataTimer.Start();
- // _drawingTimer.Start();
+ _capture.StartRecording();
+ _dataTimer.Start();
+ _drawingTimer.Start();
}
private void SimplyAuditionDialog_OnUnloaded(object sender, RoutedEventArgs e)
{
- // _drawingTimer.Stop();
- // _dataTimer.Stop();
+ _drawingTimer.Stop();
+ _dataTimer.Stop();
+ _capture.StopRecording();
}
///
@@ -62,7 +81,7 @@
private void DataTimer_Tick(object sender, EventArgs e)
{
var newSpectrumData = _visualizer.GetSpectrumData(); // 从可视化器中获取频谱数据
- newSpectrumData = AudioVisualizer.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
+ newSpectrumData = AudioDataHub.Get.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
if (_spectrumData == null) // 如果已经存储的频谱数据为空, 则把新的频谱数据直接赋值上去
{
@@ -92,80 +111,90 @@
var color1 = _allColors[_colorIndex % _allColors.Length];
var color2 = _allColors[(_colorIndex + 200) % _allColors.Length];
- DrawGradientStrips(
- StripsPath, color1, color2,
- _spectrumData, _spectrumData.Length,
- StripsPath.ActualWidth, 0, StripsPath.ActualHeight,
- 2, -StripsPath.ActualHeight * 200
+ var bassArea = AudioDataHub.Get.TakeSpectrumOfFrequency(
+ _spectrumData, RuntimeCache.AudioSampleRate, 250
+ );
+ var bassScale = bassArea.Average() * 100; //低音区
+
+ //波形曲线
+ var curveBrush = new SolidColorBrush(color1);
+ DrawCurve(
+ SampleWavePath, curveBrush,
+ _visualizer.SampleData, _visualizer.SampleData.Length,
+ SampleWavePanel.ActualWidth, 0, SampleWavePanel.ActualHeight / 2,
+ Math.Min(SampleWavePanel.ActualHeight / 2, 50)
+ );
+
+ //四周边框
+ DrawGradientBorder(
+ TopBorder, BottomBorder, LeftBorder, RightBorder,
+ Color.FromArgb(0, color1.R, color1.G, color1.B), color2,
+ SampleWavePanel.ActualWidth / 3, bassScale
);
}
///
- /// 绘制渐变的条形
+ /// 画曲线
///
- /// 绘图目标
- /// 下方颜色
- /// 上方颜色
- /// 频谱数据
- /// 条形的数量
- /// 绘图的宽度
- /// 绘图的起始 X 坐标
- /// 绘图的起始 Y 坐标
- /// 条形与条形之间的间隔(像素)
- /// 控制波形图波峰高度
- private void DrawGradientStrips(
- Path stripsPath, Color bottomColor, Color topColor, double[] spectrumData,
- int stripCount, double drawingWidth, double xOffset, double yOffset, double spacing, double scale
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 控制波形图波峰高度和波谷深度
+ private void DrawCurve(
+ Path wavePath, Brush brush, double[] spectrumData, int pointCount, double drawingWidth,
+ double xOffset, double yOffset, double scale
)
{
- //竖条宽度
- var stripWidth = (drawingWidth - spacing * stripCount) / stripCount;
- var pointArray = new Point[stripCount];
-
- for (var i = 0; i < stripCount; i++)
+ var pointArray = new Point[pointCount];
+ for (var i = 0; i < pointCount; i++)
{
- var x = stripWidth * i + spacing * i + xOffset;
- var y = spectrumData[i * spectrumData.Length / stripCount] * scale; // height
- //给所有频谱位置赋值
+ var x = i * drawingWidth / pointCount + xOffset;
+ var y = spectrumData[i * spectrumData.Length / pointCount] * scale + yOffset;
pointArray[i] = new Point(x, y);
}
- //生成一系列频谱竖条
- var geometry = new GeometryGroup();
- foreach (var point in pointArray)
+ var figure = new PathFigure
{
- var height = point.Y;
+ StartPoint = pointArray[0]
+ };
+ figure.Segments.Add(new PolyLineSegment(pointArray, true));
- if (height < 0)
- {
- height = -height;
- }
+ wavePath.Data = new PathGeometry { Figures = { figure } };
+ wavePath.Stroke = brush;
+ }
- //每根竖条的四个角坐标
- var endPoints = new[]
- {
- new Point(point.X, point.Y + yOffset), //左下角
- new Point(point.X, point.Y + height + yOffset), //左上角
- new Point(point.X + stripWidth, point.Y + height + yOffset), //右上角
- new Point(point.X + stripWidth, point.Y + yOffset) //右下角
- };
+ ///
+ /// 画四周渐变边框
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 画图宽度
+ /// 高低音转化比例
+ private void DrawGradientBorder(
+ Rectangle topBorder, Rectangle bottomBorder, Rectangle leftBorder,
+ Rectangle rightBorder, Color inner, Color outer, double width, double bassScale
+ )
+ {
+ //边框粗细根据音频高低音变化
+ var thickness = (int)(width * bassScale);
- var figure = new PathFigure
- {
- StartPoint = endPoints[0]
- };
+ topBorder.Height = thickness;
+ bottomBorder.Height = thickness;
+ leftBorder.Width = thickness;
+ rightBorder.Width = thickness;
- figure.Segments.Add(new PolyLineSegment(endPoints, false));
- geometry.Children.Add(new PathGeometry { Figures = { figure } });
- }
-
- stripsPath.Data = geometry;
-
- //设置频谱竖条的渐变色
- var linearGradientBrush = new LinearGradientBrush(
- bottomColor, topColor, new Point(0, 0), new Point(0, 1)
- );
- stripsPath.Fill = linearGradientBrush;
+ topBorder.Fill = new LinearGradientBrush(outer, inner, 90);
+ bottomBorder.Fill = new LinearGradientBrush(inner, outer, 90);
+ leftBorder.Fill = new LinearGradientBrush(outer, inner, 0);
+ rightBorder.Fill = new LinearGradientBrush(inner, outer, 0);
}
}
}
\ No newline at end of file
diff --git a/Correlator/SensorHubTag/DevCode.cs b/Correlator/SensorHubTag/DevCode.cs
deleted file mode 100644
index afd5e8f..0000000
--- a/Correlator/SensorHubTag/DevCode.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Correlator.SensorHubTag
-{
- public static class DevCode
- {
- public static string Dev1 => "211700082201";
-
- public static string Dev2 => "211700082202";
- }
-}
\ No newline at end of file
diff --git a/Correlator/Util/AudioDataHub.cs b/Correlator/Util/AudioDataHub.cs
new file mode 100644
index 0000000..72d62ea
--- /dev/null
+++ b/Correlator/Util/AudioDataHub.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+
+namespace Correlator.Util
+{
+ ///
+ /// 音频可视化数据处理
+ ///
+ public class AudioDataHub
+ {
+ #region 懒汉单例模式
+
+ private static readonly Lazy Lazy = new Lazy(() => new AudioDataHub());
+
+ public static AudioDataHub Get => Lazy.Value;
+
+
+ private AudioDataHub()
+ {
+ }
+
+ #endregion
+
+ private double[] _smoothResult;
+
+ public double[] TakeSpectrumOfFrequency(double[] spectrum, double sampleRate, double frequency)
+ {
+ var frequencyPerSample = sampleRate / spectrum.Length;
+
+ var lengthInNeed = (int)Math.Min(frequency / frequencyPerSample, spectrum.Length);
+ var result = new double[lengthInNeed];
+ Array.Copy(spectrum, 0, result, 0, lengthInNeed);
+ return result;
+ }
+
+ ///
+ /// 简单的数据模糊
+ ///
+ /// 数据
+ /// 模糊半径
+ /// 结果
+ public double[] MakeSmooth(double[] data, int radius)
+ {
+ var weights = GetWeights(radius);
+ var buffer = new double[1 + radius * 2];
+
+ _smoothResult = new double[data.Length];
+ if (data.Length < radius)
+ {
+ data.Average();
+ _smoothResult.SetValue(data, 0);
+ return _smoothResult;
+ }
+
+ for (var i = 0; i < radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = radius; i < data.Length - radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[j] = data[i - j];
+ }
+
+ buffer[radius] = data[i];
+
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + j + 1] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = data.Length - radius; i < data.Length; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i - j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ return _smoothResult;
+ }
+
+ private double[] GetWeights(int radius)
+ {
+ double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
+
+ var len = 1 + radius * 2; // 长度
+ var end = len - 1; // 最后的索引
+ var radiusF = (double)radius; // 半径浮点数
+ var weights = new double[len]; // 权重
+
+ for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
+ {
+ weights[radius + i] = Gaussian(i / radiusF);
+ }
+
+ for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
+ {
+ weights[i] = weights[end - i];
+ }
+
+ var total = weights.Sum();
+ for (var i = 0; i < len; i++) // 使权重合为 0
+ {
+ weights[i] /= total;
+ }
+
+ return weights;
+ }
+
+ private void ApplyWeights(double[] buffer, double[] weights)
+ {
+ var len = buffer.Length;
+ for (var i = 0; i < len; i++)
+ {
+ buffer[i] *= weights[i];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Correlator/Util/AudioVisualizer.cs b/Correlator/Util/AudioVisualizer.cs
index 9a888f5..393f7df 100644
--- a/Correlator/Util/AudioVisualizer.cs
+++ b/Correlator/Util/AudioVisualizer.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using FftSharp;
using FftSharp.Windows;
using Complex = System.Numerics.Complex;
@@ -13,6 +12,8 @@
///
public double[] SampleData { get; }
+ private Complex[] _data;
+
///
///
///
@@ -63,126 +64,27 @@
public double[] GetSpectrumData()
{
var len = SampleData.Length;
- var data = new Complex[len];
-
+ _data = new Complex[len];
+
for (var i = 0; i < len; i++)
{
- data[i] = new Complex(SampleData[i], 0);
+ _data[i] = new Complex(SampleData[i], 0);
}
-
- FFT.Forward(data);
-
+
+ FFT.Forward(_data);
+
var halfLen = len / 2;
var result = new double[halfLen]; // 傅里叶变换结果左右对称, 只需要取一半
for (var i = 0; i < halfLen; i++)
{
- result[i] = data[i].Magnitude / len;
+ result[i] = _data[i].Magnitude / len;
}
-
+
var window = new Bartlett();
window.Create(halfLen);
window.ApplyInPlace(result);
-
+
return result;
}
-
- ///
- /// 简单的数据模糊
- ///
- /// 数据
- /// 模糊半径
- /// 结果
- public static double[] MakeSmooth(double[] data, int radius)
- {
- var weights = GetWeights(radius);
- var buffer = new double[1 + radius * 2];
-
- var result = new double[data.Length];
- if (data.Length < radius)
- {
- data.Average();
- result.SetValue(data, 0);
- return result;
- }
-
- for (var i = 0; i < radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = radius; i < data.Length - radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[j] = data[i - j];
- }
-
- buffer[radius] = data[i];
-
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + j + 1] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = data.Length - radius; i < data.Length; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i - j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- return result;
- }
-
- private static double[] GetWeights(int radius)
- {
- double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
-
- var len = 1 + radius * 2; // 长度
- var end = len - 1; // 最后的索引
- var radiusF = (double)radius; // 半径浮点数
- var weights = new double[len]; // 权重
-
- for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
- {
- weights[radius + i] = Gaussian(i / radiusF);
- }
-
- for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
- {
- weights[i] = weights[end - i];
- }
-
- var total = weights.Sum();
- for (var i = 0; i < len; i++) // 使权重合为 0
- {
- weights[i] /= total;
- }
-
- return weights;
- }
-
- private static void ApplyWeights(double[] buffer, double[] weights)
- {
- var len = buffer.Length;
- for (var i = 0; i < len; i++)
- {
- buffer[i] *= weights[i];
- }
- }
}
}
\ No newline at end of file
diff --git a/Correlator/Util/RuntimeCache.cs b/Correlator/Util/RuntimeCache.cs
index 468ca7f..4a1e94e 100644
--- a/Correlator/Util/RuntimeCache.cs
+++ b/Correlator/Util/RuntimeCache.cs
@@ -86,5 +86,15 @@
/// 采样率
///
public const int AudioSampleRate = 7500;
+
+ ///
+ /// 设备1(红色的)
+ ///
+ public static string Dev1 => "211700082201";
+
+ ///
+ /// 设备2(蓝色的)
+ ///
+ public static string Dev2 => "211700082202";
}
}
\ No newline at end of file
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs
index 43f84fd..91441a2 100644
--- a/Correlator/Dialog/CheckResponseDialog.xaml.cs
+++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs
@@ -231,7 +231,7 @@
if (RedSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev1);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1);
_redResponseTimer.Start();
ReCheckButton.IsEnabled = true;
@@ -239,11 +239,11 @@
else if (RedSensorStepBar.StepIndex == 2)
{
//下发数据全部正常指令
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev1}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev1}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.RedSensorOriginalResp orderby pair.Key select pair;
@@ -266,7 +266,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev1, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev1, tags);
#endregion
}
@@ -315,18 +315,18 @@
if (BlueSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev2);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2);
_blueResponseTimer.Start();
ReCheckButton.IsEnabled = true;
}
else if (BlueSensorStepBar.StepIndex == 2)
{
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev2}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev2}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.BlueSensorOriginalResp orderby pair.Key select pair;
@@ -349,7 +349,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev2, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev2, tags);
#endregion
}
@@ -396,7 +396,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, redIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray);
}
else
{
@@ -417,7 +417,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, blueIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray);
}
};
}
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml b/Correlator/Dialog/SimplyAuditionDialog.xaml
index 5fd8124..cd03b74 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml
@@ -9,7 +9,7 @@
xmlns:prism="http://prismlibrary.com/"
xmlns:vm="clr-namespace:Correlator.ViewModels"
Width="600"
- Height="400"
+ Height="480"
d:DataContext="{d:DesignInstance Type=vm:SimplyAuditionDialogViewModel}"
Loaded="SimplyAuditionDialog_OnLoaded"
Unloaded="SimplyAuditionDialog_OnUnloaded"
@@ -187,10 +187,15 @@
-
+ Background="{StaticResource MainThemeColor}">
+
+
+
+
+
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
index 3747ce0..41cb280 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
@@ -6,6 +7,8 @@
using System.Windows.Threading;
using Correlator.DataService;
using Correlator.Util;
+using NAudio.CoreAudioApi;
+using NAudio.Wave;
namespace Correlator.Dialog
{
@@ -16,6 +19,7 @@
{
private readonly AudioVisualizer _visualizer; // 可视化
private double[] _spectrumData; // 频谱数据
+ private readonly WasapiCapture _capture; // 音频捕获
private int _colorIndex;
private readonly Color[] _allColors;
@@ -29,29 +33,44 @@
Interval = new TimeSpan(0, 0, 0, 0, 30)
};
- public SimplyAuditionDialog(IApplicationDataService dataService, IAudioService audioService)
+ public SimplyAuditionDialog(IApplicationDataService dataService)
{
InitializeComponent();
- // _visualizer = dataService.GetAudioVisualizer(256);
- // _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
- //
- // audioService.AudioVisualizer = _visualizer;
- //
- // _dataTimer.Tick += DataTimer_Tick;
- // _drawingTimer.Tick += DrawingTimer_Tick;
+ _capture = new WasapiLoopbackCapture(); // 捕获电脑发出的声音
+ _visualizer = dataService.GetAudioVisualizer(512);
+ _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
+
+ _capture.WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(7500, 1);
+ _capture.DataAvailable += delegate(object o, WaveInEventArgs args)
+ {
+ var length = args.BytesRecorded / 4; // 采样的数量 (每一个采样是 4 字节)
+ var result = new double[length];
+
+ for (var i = 0; i < length; i++)
+ {
+ result[i] = BitConverter.ToSingle(args.Buffer, i * 4); // 取出采样值
+ }
+
+ _visualizer.PushSampleData(result); // 将新的采样存储到 可视化器 中
+ };
+
+ _dataTimer.Tick += DataTimer_Tick;
+ _drawingTimer.Tick += DrawingTimer_Tick;
}
private void SimplyAuditionDialog_OnLoaded(object sender, RoutedEventArgs e)
{
- // _dataTimer.Start();
- // _drawingTimer.Start();
+ _capture.StartRecording();
+ _dataTimer.Start();
+ _drawingTimer.Start();
}
private void SimplyAuditionDialog_OnUnloaded(object sender, RoutedEventArgs e)
{
- // _drawingTimer.Stop();
- // _dataTimer.Stop();
+ _drawingTimer.Stop();
+ _dataTimer.Stop();
+ _capture.StopRecording();
}
///
@@ -62,7 +81,7 @@
private void DataTimer_Tick(object sender, EventArgs e)
{
var newSpectrumData = _visualizer.GetSpectrumData(); // 从可视化器中获取频谱数据
- newSpectrumData = AudioVisualizer.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
+ newSpectrumData = AudioDataHub.Get.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
if (_spectrumData == null) // 如果已经存储的频谱数据为空, 则把新的频谱数据直接赋值上去
{
@@ -92,80 +111,90 @@
var color1 = _allColors[_colorIndex % _allColors.Length];
var color2 = _allColors[(_colorIndex + 200) % _allColors.Length];
- DrawGradientStrips(
- StripsPath, color1, color2,
- _spectrumData, _spectrumData.Length,
- StripsPath.ActualWidth, 0, StripsPath.ActualHeight,
- 2, -StripsPath.ActualHeight * 200
+ var bassArea = AudioDataHub.Get.TakeSpectrumOfFrequency(
+ _spectrumData, RuntimeCache.AudioSampleRate, 250
+ );
+ var bassScale = bassArea.Average() * 100; //低音区
+
+ //波形曲线
+ var curveBrush = new SolidColorBrush(color1);
+ DrawCurve(
+ SampleWavePath, curveBrush,
+ _visualizer.SampleData, _visualizer.SampleData.Length,
+ SampleWavePanel.ActualWidth, 0, SampleWavePanel.ActualHeight / 2,
+ Math.Min(SampleWavePanel.ActualHeight / 2, 50)
+ );
+
+ //四周边框
+ DrawGradientBorder(
+ TopBorder, BottomBorder, LeftBorder, RightBorder,
+ Color.FromArgb(0, color1.R, color1.G, color1.B), color2,
+ SampleWavePanel.ActualWidth / 3, bassScale
);
}
///
- /// 绘制渐变的条形
+ /// 画曲线
///
- /// 绘图目标
- /// 下方颜色
- /// 上方颜色
- /// 频谱数据
- /// 条形的数量
- /// 绘图的宽度
- /// 绘图的起始 X 坐标
- /// 绘图的起始 Y 坐标
- /// 条形与条形之间的间隔(像素)
- /// 控制波形图波峰高度
- private void DrawGradientStrips(
- Path stripsPath, Color bottomColor, Color topColor, double[] spectrumData,
- int stripCount, double drawingWidth, double xOffset, double yOffset, double spacing, double scale
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 控制波形图波峰高度和波谷深度
+ private void DrawCurve(
+ Path wavePath, Brush brush, double[] spectrumData, int pointCount, double drawingWidth,
+ double xOffset, double yOffset, double scale
)
{
- //竖条宽度
- var stripWidth = (drawingWidth - spacing * stripCount) / stripCount;
- var pointArray = new Point[stripCount];
-
- for (var i = 0; i < stripCount; i++)
+ var pointArray = new Point[pointCount];
+ for (var i = 0; i < pointCount; i++)
{
- var x = stripWidth * i + spacing * i + xOffset;
- var y = spectrumData[i * spectrumData.Length / stripCount] * scale; // height
- //给所有频谱位置赋值
+ var x = i * drawingWidth / pointCount + xOffset;
+ var y = spectrumData[i * spectrumData.Length / pointCount] * scale + yOffset;
pointArray[i] = new Point(x, y);
}
- //生成一系列频谱竖条
- var geometry = new GeometryGroup();
- foreach (var point in pointArray)
+ var figure = new PathFigure
{
- var height = point.Y;
+ StartPoint = pointArray[0]
+ };
+ figure.Segments.Add(new PolyLineSegment(pointArray, true));
- if (height < 0)
- {
- height = -height;
- }
+ wavePath.Data = new PathGeometry { Figures = { figure } };
+ wavePath.Stroke = brush;
+ }
- //每根竖条的四个角坐标
- var endPoints = new[]
- {
- new Point(point.X, point.Y + yOffset), //左下角
- new Point(point.X, point.Y + height + yOffset), //左上角
- new Point(point.X + stripWidth, point.Y + height + yOffset), //右上角
- new Point(point.X + stripWidth, point.Y + yOffset) //右下角
- };
+ ///
+ /// 画四周渐变边框
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 画图宽度
+ /// 高低音转化比例
+ private void DrawGradientBorder(
+ Rectangle topBorder, Rectangle bottomBorder, Rectangle leftBorder,
+ Rectangle rightBorder, Color inner, Color outer, double width, double bassScale
+ )
+ {
+ //边框粗细根据音频高低音变化
+ var thickness = (int)(width * bassScale);
- var figure = new PathFigure
- {
- StartPoint = endPoints[0]
- };
+ topBorder.Height = thickness;
+ bottomBorder.Height = thickness;
+ leftBorder.Width = thickness;
+ rightBorder.Width = thickness;
- figure.Segments.Add(new PolyLineSegment(endPoints, false));
- geometry.Children.Add(new PathGeometry { Figures = { figure } });
- }
-
- stripsPath.Data = geometry;
-
- //设置频谱竖条的渐变色
- var linearGradientBrush = new LinearGradientBrush(
- bottomColor, topColor, new Point(0, 0), new Point(0, 1)
- );
- stripsPath.Fill = linearGradientBrush;
+ topBorder.Fill = new LinearGradientBrush(outer, inner, 90);
+ bottomBorder.Fill = new LinearGradientBrush(inner, outer, 90);
+ leftBorder.Fill = new LinearGradientBrush(outer, inner, 0);
+ rightBorder.Fill = new LinearGradientBrush(inner, outer, 0);
}
}
}
\ No newline at end of file
diff --git a/Correlator/SensorHubTag/DevCode.cs b/Correlator/SensorHubTag/DevCode.cs
deleted file mode 100644
index afd5e8f..0000000
--- a/Correlator/SensorHubTag/DevCode.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Correlator.SensorHubTag
-{
- public static class DevCode
- {
- public static string Dev1 => "211700082201";
-
- public static string Dev2 => "211700082202";
- }
-}
\ No newline at end of file
diff --git a/Correlator/Util/AudioDataHub.cs b/Correlator/Util/AudioDataHub.cs
new file mode 100644
index 0000000..72d62ea
--- /dev/null
+++ b/Correlator/Util/AudioDataHub.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+
+namespace Correlator.Util
+{
+ ///
+ /// 音频可视化数据处理
+ ///
+ public class AudioDataHub
+ {
+ #region 懒汉单例模式
+
+ private static readonly Lazy Lazy = new Lazy(() => new AudioDataHub());
+
+ public static AudioDataHub Get => Lazy.Value;
+
+
+ private AudioDataHub()
+ {
+ }
+
+ #endregion
+
+ private double[] _smoothResult;
+
+ public double[] TakeSpectrumOfFrequency(double[] spectrum, double sampleRate, double frequency)
+ {
+ var frequencyPerSample = sampleRate / spectrum.Length;
+
+ var lengthInNeed = (int)Math.Min(frequency / frequencyPerSample, spectrum.Length);
+ var result = new double[lengthInNeed];
+ Array.Copy(spectrum, 0, result, 0, lengthInNeed);
+ return result;
+ }
+
+ ///
+ /// 简单的数据模糊
+ ///
+ /// 数据
+ /// 模糊半径
+ /// 结果
+ public double[] MakeSmooth(double[] data, int radius)
+ {
+ var weights = GetWeights(radius);
+ var buffer = new double[1 + radius * 2];
+
+ _smoothResult = new double[data.Length];
+ if (data.Length < radius)
+ {
+ data.Average();
+ _smoothResult.SetValue(data, 0);
+ return _smoothResult;
+ }
+
+ for (var i = 0; i < radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = radius; i < data.Length - radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[j] = data[i - j];
+ }
+
+ buffer[radius] = data[i];
+
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + j + 1] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = data.Length - radius; i < data.Length; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i - j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ return _smoothResult;
+ }
+
+ private double[] GetWeights(int radius)
+ {
+ double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
+
+ var len = 1 + radius * 2; // 长度
+ var end = len - 1; // 最后的索引
+ var radiusF = (double)radius; // 半径浮点数
+ var weights = new double[len]; // 权重
+
+ for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
+ {
+ weights[radius + i] = Gaussian(i / radiusF);
+ }
+
+ for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
+ {
+ weights[i] = weights[end - i];
+ }
+
+ var total = weights.Sum();
+ for (var i = 0; i < len; i++) // 使权重合为 0
+ {
+ weights[i] /= total;
+ }
+
+ return weights;
+ }
+
+ private void ApplyWeights(double[] buffer, double[] weights)
+ {
+ var len = buffer.Length;
+ for (var i = 0; i < len; i++)
+ {
+ buffer[i] *= weights[i];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Correlator/Util/AudioVisualizer.cs b/Correlator/Util/AudioVisualizer.cs
index 9a888f5..393f7df 100644
--- a/Correlator/Util/AudioVisualizer.cs
+++ b/Correlator/Util/AudioVisualizer.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using FftSharp;
using FftSharp.Windows;
using Complex = System.Numerics.Complex;
@@ -13,6 +12,8 @@
///
public double[] SampleData { get; }
+ private Complex[] _data;
+
///
///
///
@@ -63,126 +64,27 @@
public double[] GetSpectrumData()
{
var len = SampleData.Length;
- var data = new Complex[len];
-
+ _data = new Complex[len];
+
for (var i = 0; i < len; i++)
{
- data[i] = new Complex(SampleData[i], 0);
+ _data[i] = new Complex(SampleData[i], 0);
}
-
- FFT.Forward(data);
-
+
+ FFT.Forward(_data);
+
var halfLen = len / 2;
var result = new double[halfLen]; // 傅里叶变换结果左右对称, 只需要取一半
for (var i = 0; i < halfLen; i++)
{
- result[i] = data[i].Magnitude / len;
+ result[i] = _data[i].Magnitude / len;
}
-
+
var window = new Bartlett();
window.Create(halfLen);
window.ApplyInPlace(result);
-
+
return result;
}
-
- ///
- /// 简单的数据模糊
- ///
- /// 数据
- /// 模糊半径
- /// 结果
- public static double[] MakeSmooth(double[] data, int radius)
- {
- var weights = GetWeights(radius);
- var buffer = new double[1 + radius * 2];
-
- var result = new double[data.Length];
- if (data.Length < radius)
- {
- data.Average();
- result.SetValue(data, 0);
- return result;
- }
-
- for (var i = 0; i < radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = radius; i < data.Length - radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[j] = data[i - j];
- }
-
- buffer[radius] = data[i];
-
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + j + 1] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = data.Length - radius; i < data.Length; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i - j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- return result;
- }
-
- private static double[] GetWeights(int radius)
- {
- double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
-
- var len = 1 + radius * 2; // 长度
- var end = len - 1; // 最后的索引
- var radiusF = (double)radius; // 半径浮点数
- var weights = new double[len]; // 权重
-
- for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
- {
- weights[radius + i] = Gaussian(i / radiusF);
- }
-
- for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
- {
- weights[i] = weights[end - i];
- }
-
- var total = weights.Sum();
- for (var i = 0; i < len; i++) // 使权重合为 0
- {
- weights[i] /= total;
- }
-
- return weights;
- }
-
- private static void ApplyWeights(double[] buffer, double[] weights)
- {
- var len = buffer.Length;
- for (var i = 0; i < len; i++)
- {
- buffer[i] *= weights[i];
- }
- }
}
}
\ No newline at end of file
diff --git a/Correlator/Util/RuntimeCache.cs b/Correlator/Util/RuntimeCache.cs
index 468ca7f..4a1e94e 100644
--- a/Correlator/Util/RuntimeCache.cs
+++ b/Correlator/Util/RuntimeCache.cs
@@ -86,5 +86,15 @@
/// 采样率
///
public const int AudioSampleRate = 7500;
+
+ ///
+ /// 设备1(红色的)
+ ///
+ public static string Dev1 => "211700082201";
+
+ ///
+ /// 设备2(蓝色的)
+ ///
+ public static string Dev2 => "211700082202";
}
}
\ No newline at end of file
diff --git a/Correlator/ViewModels/ImportResponseDialogViewModel.cs b/Correlator/ViewModels/ImportResponseDialogViewModel.cs
index 5b6c1f3..af9c398 100644
--- a/Correlator/ViewModels/ImportResponseDialogViewModel.cs
+++ b/Correlator/ViewModels/ImportResponseDialogViewModel.cs
@@ -286,7 +286,7 @@
Thread.Sleep(10);
}
- _dataModel.DevCode = DevCode.Dev1;
+ _dataModel.DevCode = RuntimeCache.Dev1;
_dataModel.LeftReceiveDataTime = DateTime.Now;
_dataModel.LeftDeviceDataArray = totalData.ToArray();
}
@@ -312,7 +312,7 @@
Thread.Sleep(10);
}
- _dataModel.DevCode = DevCode.Dev2;
+ _dataModel.DevCode = RuntimeCache.Dev2;
_dataModel.RightReceiveDataTime = DateTime.Now;
_dataModel.RightDeviceDataArray = totalData.ToArray();
}
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs
index 43f84fd..91441a2 100644
--- a/Correlator/Dialog/CheckResponseDialog.xaml.cs
+++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs
@@ -231,7 +231,7 @@
if (RedSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev1);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1);
_redResponseTimer.Start();
ReCheckButton.IsEnabled = true;
@@ -239,11 +239,11 @@
else if (RedSensorStepBar.StepIndex == 2)
{
//下发数据全部正常指令
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev1}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev1}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.RedSensorOriginalResp orderby pair.Key select pair;
@@ -266,7 +266,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev1, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev1, tags);
#endregion
}
@@ -315,18 +315,18 @@
if (BlueSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev2);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2);
_blueResponseTimer.Start();
ReCheckButton.IsEnabled = true;
}
else if (BlueSensorStepBar.StepIndex == 2)
{
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev2}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev2}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.BlueSensorOriginalResp orderby pair.Key select pair;
@@ -349,7 +349,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev2, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev2, tags);
#endregion
}
@@ -396,7 +396,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, redIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray);
}
else
{
@@ -417,7 +417,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, blueIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray);
}
};
}
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml b/Correlator/Dialog/SimplyAuditionDialog.xaml
index 5fd8124..cd03b74 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml
@@ -9,7 +9,7 @@
xmlns:prism="http://prismlibrary.com/"
xmlns:vm="clr-namespace:Correlator.ViewModels"
Width="600"
- Height="400"
+ Height="480"
d:DataContext="{d:DesignInstance Type=vm:SimplyAuditionDialogViewModel}"
Loaded="SimplyAuditionDialog_OnLoaded"
Unloaded="SimplyAuditionDialog_OnUnloaded"
@@ -187,10 +187,15 @@
-
+ Background="{StaticResource MainThemeColor}">
+
+
+
+
+
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
index 3747ce0..41cb280 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
@@ -6,6 +7,8 @@
using System.Windows.Threading;
using Correlator.DataService;
using Correlator.Util;
+using NAudio.CoreAudioApi;
+using NAudio.Wave;
namespace Correlator.Dialog
{
@@ -16,6 +19,7 @@
{
private readonly AudioVisualizer _visualizer; // 可视化
private double[] _spectrumData; // 频谱数据
+ private readonly WasapiCapture _capture; // 音频捕获
private int _colorIndex;
private readonly Color[] _allColors;
@@ -29,29 +33,44 @@
Interval = new TimeSpan(0, 0, 0, 0, 30)
};
- public SimplyAuditionDialog(IApplicationDataService dataService, IAudioService audioService)
+ public SimplyAuditionDialog(IApplicationDataService dataService)
{
InitializeComponent();
- // _visualizer = dataService.GetAudioVisualizer(256);
- // _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
- //
- // audioService.AudioVisualizer = _visualizer;
- //
- // _dataTimer.Tick += DataTimer_Tick;
- // _drawingTimer.Tick += DrawingTimer_Tick;
+ _capture = new WasapiLoopbackCapture(); // 捕获电脑发出的声音
+ _visualizer = dataService.GetAudioVisualizer(512);
+ _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
+
+ _capture.WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(7500, 1);
+ _capture.DataAvailable += delegate(object o, WaveInEventArgs args)
+ {
+ var length = args.BytesRecorded / 4; // 采样的数量 (每一个采样是 4 字节)
+ var result = new double[length];
+
+ for (var i = 0; i < length; i++)
+ {
+ result[i] = BitConverter.ToSingle(args.Buffer, i * 4); // 取出采样值
+ }
+
+ _visualizer.PushSampleData(result); // 将新的采样存储到 可视化器 中
+ };
+
+ _dataTimer.Tick += DataTimer_Tick;
+ _drawingTimer.Tick += DrawingTimer_Tick;
}
private void SimplyAuditionDialog_OnLoaded(object sender, RoutedEventArgs e)
{
- // _dataTimer.Start();
- // _drawingTimer.Start();
+ _capture.StartRecording();
+ _dataTimer.Start();
+ _drawingTimer.Start();
}
private void SimplyAuditionDialog_OnUnloaded(object sender, RoutedEventArgs e)
{
- // _drawingTimer.Stop();
- // _dataTimer.Stop();
+ _drawingTimer.Stop();
+ _dataTimer.Stop();
+ _capture.StopRecording();
}
///
@@ -62,7 +81,7 @@
private void DataTimer_Tick(object sender, EventArgs e)
{
var newSpectrumData = _visualizer.GetSpectrumData(); // 从可视化器中获取频谱数据
- newSpectrumData = AudioVisualizer.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
+ newSpectrumData = AudioDataHub.Get.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
if (_spectrumData == null) // 如果已经存储的频谱数据为空, 则把新的频谱数据直接赋值上去
{
@@ -92,80 +111,90 @@
var color1 = _allColors[_colorIndex % _allColors.Length];
var color2 = _allColors[(_colorIndex + 200) % _allColors.Length];
- DrawGradientStrips(
- StripsPath, color1, color2,
- _spectrumData, _spectrumData.Length,
- StripsPath.ActualWidth, 0, StripsPath.ActualHeight,
- 2, -StripsPath.ActualHeight * 200
+ var bassArea = AudioDataHub.Get.TakeSpectrumOfFrequency(
+ _spectrumData, RuntimeCache.AudioSampleRate, 250
+ );
+ var bassScale = bassArea.Average() * 100; //低音区
+
+ //波形曲线
+ var curveBrush = new SolidColorBrush(color1);
+ DrawCurve(
+ SampleWavePath, curveBrush,
+ _visualizer.SampleData, _visualizer.SampleData.Length,
+ SampleWavePanel.ActualWidth, 0, SampleWavePanel.ActualHeight / 2,
+ Math.Min(SampleWavePanel.ActualHeight / 2, 50)
+ );
+
+ //四周边框
+ DrawGradientBorder(
+ TopBorder, BottomBorder, LeftBorder, RightBorder,
+ Color.FromArgb(0, color1.R, color1.G, color1.B), color2,
+ SampleWavePanel.ActualWidth / 3, bassScale
);
}
///
- /// 绘制渐变的条形
+ /// 画曲线
///
- /// 绘图目标
- /// 下方颜色
- /// 上方颜色
- /// 频谱数据
- /// 条形的数量
- /// 绘图的宽度
- /// 绘图的起始 X 坐标
- /// 绘图的起始 Y 坐标
- /// 条形与条形之间的间隔(像素)
- /// 控制波形图波峰高度
- private void DrawGradientStrips(
- Path stripsPath, Color bottomColor, Color topColor, double[] spectrumData,
- int stripCount, double drawingWidth, double xOffset, double yOffset, double spacing, double scale
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 控制波形图波峰高度和波谷深度
+ private void DrawCurve(
+ Path wavePath, Brush brush, double[] spectrumData, int pointCount, double drawingWidth,
+ double xOffset, double yOffset, double scale
)
{
- //竖条宽度
- var stripWidth = (drawingWidth - spacing * stripCount) / stripCount;
- var pointArray = new Point[stripCount];
-
- for (var i = 0; i < stripCount; i++)
+ var pointArray = new Point[pointCount];
+ for (var i = 0; i < pointCount; i++)
{
- var x = stripWidth * i + spacing * i + xOffset;
- var y = spectrumData[i * spectrumData.Length / stripCount] * scale; // height
- //给所有频谱位置赋值
+ var x = i * drawingWidth / pointCount + xOffset;
+ var y = spectrumData[i * spectrumData.Length / pointCount] * scale + yOffset;
pointArray[i] = new Point(x, y);
}
- //生成一系列频谱竖条
- var geometry = new GeometryGroup();
- foreach (var point in pointArray)
+ var figure = new PathFigure
{
- var height = point.Y;
+ StartPoint = pointArray[0]
+ };
+ figure.Segments.Add(new PolyLineSegment(pointArray, true));
- if (height < 0)
- {
- height = -height;
- }
+ wavePath.Data = new PathGeometry { Figures = { figure } };
+ wavePath.Stroke = brush;
+ }
- //每根竖条的四个角坐标
- var endPoints = new[]
- {
- new Point(point.X, point.Y + yOffset), //左下角
- new Point(point.X, point.Y + height + yOffset), //左上角
- new Point(point.X + stripWidth, point.Y + height + yOffset), //右上角
- new Point(point.X + stripWidth, point.Y + yOffset) //右下角
- };
+ ///
+ /// 画四周渐变边框
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 画图宽度
+ /// 高低音转化比例
+ private void DrawGradientBorder(
+ Rectangle topBorder, Rectangle bottomBorder, Rectangle leftBorder,
+ Rectangle rightBorder, Color inner, Color outer, double width, double bassScale
+ )
+ {
+ //边框粗细根据音频高低音变化
+ var thickness = (int)(width * bassScale);
- var figure = new PathFigure
- {
- StartPoint = endPoints[0]
- };
+ topBorder.Height = thickness;
+ bottomBorder.Height = thickness;
+ leftBorder.Width = thickness;
+ rightBorder.Width = thickness;
- figure.Segments.Add(new PolyLineSegment(endPoints, false));
- geometry.Children.Add(new PathGeometry { Figures = { figure } });
- }
-
- stripsPath.Data = geometry;
-
- //设置频谱竖条的渐变色
- var linearGradientBrush = new LinearGradientBrush(
- bottomColor, topColor, new Point(0, 0), new Point(0, 1)
- );
- stripsPath.Fill = linearGradientBrush;
+ topBorder.Fill = new LinearGradientBrush(outer, inner, 90);
+ bottomBorder.Fill = new LinearGradientBrush(inner, outer, 90);
+ leftBorder.Fill = new LinearGradientBrush(outer, inner, 0);
+ rightBorder.Fill = new LinearGradientBrush(inner, outer, 0);
}
}
}
\ No newline at end of file
diff --git a/Correlator/SensorHubTag/DevCode.cs b/Correlator/SensorHubTag/DevCode.cs
deleted file mode 100644
index afd5e8f..0000000
--- a/Correlator/SensorHubTag/DevCode.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Correlator.SensorHubTag
-{
- public static class DevCode
- {
- public static string Dev1 => "211700082201";
-
- public static string Dev2 => "211700082202";
- }
-}
\ No newline at end of file
diff --git a/Correlator/Util/AudioDataHub.cs b/Correlator/Util/AudioDataHub.cs
new file mode 100644
index 0000000..72d62ea
--- /dev/null
+++ b/Correlator/Util/AudioDataHub.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+
+namespace Correlator.Util
+{
+ ///
+ /// 音频可视化数据处理
+ ///
+ public class AudioDataHub
+ {
+ #region 懒汉单例模式
+
+ private static readonly Lazy Lazy = new Lazy(() => new AudioDataHub());
+
+ public static AudioDataHub Get => Lazy.Value;
+
+
+ private AudioDataHub()
+ {
+ }
+
+ #endregion
+
+ private double[] _smoothResult;
+
+ public double[] TakeSpectrumOfFrequency(double[] spectrum, double sampleRate, double frequency)
+ {
+ var frequencyPerSample = sampleRate / spectrum.Length;
+
+ var lengthInNeed = (int)Math.Min(frequency / frequencyPerSample, spectrum.Length);
+ var result = new double[lengthInNeed];
+ Array.Copy(spectrum, 0, result, 0, lengthInNeed);
+ return result;
+ }
+
+ ///
+ /// 简单的数据模糊
+ ///
+ /// 数据
+ /// 模糊半径
+ /// 结果
+ public double[] MakeSmooth(double[] data, int radius)
+ {
+ var weights = GetWeights(radius);
+ var buffer = new double[1 + radius * 2];
+
+ _smoothResult = new double[data.Length];
+ if (data.Length < radius)
+ {
+ data.Average();
+ _smoothResult.SetValue(data, 0);
+ return _smoothResult;
+ }
+
+ for (var i = 0; i < radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = radius; i < data.Length - radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[j] = data[i - j];
+ }
+
+ buffer[radius] = data[i];
+
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + j + 1] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = data.Length - radius; i < data.Length; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i - j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ return _smoothResult;
+ }
+
+ private double[] GetWeights(int radius)
+ {
+ double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
+
+ var len = 1 + radius * 2; // 长度
+ var end = len - 1; // 最后的索引
+ var radiusF = (double)radius; // 半径浮点数
+ var weights = new double[len]; // 权重
+
+ for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
+ {
+ weights[radius + i] = Gaussian(i / radiusF);
+ }
+
+ for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
+ {
+ weights[i] = weights[end - i];
+ }
+
+ var total = weights.Sum();
+ for (var i = 0; i < len; i++) // 使权重合为 0
+ {
+ weights[i] /= total;
+ }
+
+ return weights;
+ }
+
+ private void ApplyWeights(double[] buffer, double[] weights)
+ {
+ var len = buffer.Length;
+ for (var i = 0; i < len; i++)
+ {
+ buffer[i] *= weights[i];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Correlator/Util/AudioVisualizer.cs b/Correlator/Util/AudioVisualizer.cs
index 9a888f5..393f7df 100644
--- a/Correlator/Util/AudioVisualizer.cs
+++ b/Correlator/Util/AudioVisualizer.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using FftSharp;
using FftSharp.Windows;
using Complex = System.Numerics.Complex;
@@ -13,6 +12,8 @@
///
public double[] SampleData { get; }
+ private Complex[] _data;
+
///
///
///
@@ -63,126 +64,27 @@
public double[] GetSpectrumData()
{
var len = SampleData.Length;
- var data = new Complex[len];
-
+ _data = new Complex[len];
+
for (var i = 0; i < len; i++)
{
- data[i] = new Complex(SampleData[i], 0);
+ _data[i] = new Complex(SampleData[i], 0);
}
-
- FFT.Forward(data);
-
+
+ FFT.Forward(_data);
+
var halfLen = len / 2;
var result = new double[halfLen]; // 傅里叶变换结果左右对称, 只需要取一半
for (var i = 0; i < halfLen; i++)
{
- result[i] = data[i].Magnitude / len;
+ result[i] = _data[i].Magnitude / len;
}
-
+
var window = new Bartlett();
window.Create(halfLen);
window.ApplyInPlace(result);
-
+
return result;
}
-
- ///
- /// 简单的数据模糊
- ///
- /// 数据
- /// 模糊半径
- /// 结果
- public static double[] MakeSmooth(double[] data, int radius)
- {
- var weights = GetWeights(radius);
- var buffer = new double[1 + radius * 2];
-
- var result = new double[data.Length];
- if (data.Length < radius)
- {
- data.Average();
- result.SetValue(data, 0);
- return result;
- }
-
- for (var i = 0; i < radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = radius; i < data.Length - radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[j] = data[i - j];
- }
-
- buffer[radius] = data[i];
-
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + j + 1] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = data.Length - radius; i < data.Length; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i - j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- return result;
- }
-
- private static double[] GetWeights(int radius)
- {
- double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
-
- var len = 1 + radius * 2; // 长度
- var end = len - 1; // 最后的索引
- var radiusF = (double)radius; // 半径浮点数
- var weights = new double[len]; // 权重
-
- for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
- {
- weights[radius + i] = Gaussian(i / radiusF);
- }
-
- for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
- {
- weights[i] = weights[end - i];
- }
-
- var total = weights.Sum();
- for (var i = 0; i < len; i++) // 使权重合为 0
- {
- weights[i] /= total;
- }
-
- return weights;
- }
-
- private static void ApplyWeights(double[] buffer, double[] weights)
- {
- var len = buffer.Length;
- for (var i = 0; i < len; i++)
- {
- buffer[i] *= weights[i];
- }
- }
}
}
\ No newline at end of file
diff --git a/Correlator/Util/RuntimeCache.cs b/Correlator/Util/RuntimeCache.cs
index 468ca7f..4a1e94e 100644
--- a/Correlator/Util/RuntimeCache.cs
+++ b/Correlator/Util/RuntimeCache.cs
@@ -86,5 +86,15 @@
/// 采样率
///
public const int AudioSampleRate = 7500;
+
+ ///
+ /// 设备1(红色的)
+ ///
+ public static string Dev1 => "211700082201";
+
+ ///
+ /// 设备2(蓝色的)
+ ///
+ public static string Dev2 => "211700082202";
}
}
\ No newline at end of file
diff --git a/Correlator/ViewModels/ImportResponseDialogViewModel.cs b/Correlator/ViewModels/ImportResponseDialogViewModel.cs
index 5b6c1f3..af9c398 100644
--- a/Correlator/ViewModels/ImportResponseDialogViewModel.cs
+++ b/Correlator/ViewModels/ImportResponseDialogViewModel.cs
@@ -286,7 +286,7 @@
Thread.Sleep(10);
}
- _dataModel.DevCode = DevCode.Dev1;
+ _dataModel.DevCode = RuntimeCache.Dev1;
_dataModel.LeftReceiveDataTime = DateTime.Now;
_dataModel.LeftDeviceDataArray = totalData.ToArray();
}
@@ -312,7 +312,7 @@
Thread.Sleep(10);
}
- _dataModel.DevCode = DevCode.Dev2;
+ _dataModel.DevCode = RuntimeCache.Dev2;
_dataModel.RightReceiveDataTime = DateTime.Now;
_dataModel.RightDeviceDataArray = totalData.ToArray();
}
diff --git a/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs b/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs
index d1f6f4c..9322765 100644
--- a/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs
+++ b/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs
@@ -129,8 +129,8 @@
}
else
{
- CommandSender.SendSoundCollectCmd(serialPortService.Sp, DevCode.Dev1);
- audioService.Start(DevCode.Dev1);
+ CommandSender.SendSoundCollectCmd(serialPortService.Sp, RuntimeCache.Dev1);
+ audioService.Start(RuntimeCache.Dev1);
IsRedRecording = true;
}
});
@@ -178,8 +178,8 @@
}
else
{
- CommandSender.SendSoundCollectCmd(serialPortService.Sp, DevCode.Dev2);
- audioService.Start(DevCode.Dev2);
+ CommandSender.SendSoundCollectCmd(serialPortService.Sp, RuntimeCache.Dev2);
+ audioService.Start(RuntimeCache.Dev2);
IsBlueRecording = true;
}
});
@@ -192,7 +192,7 @@
///
private void StopRedSensor(ISerialPortService serialPortService, IAudioService audioService)
{
- CommandSender.SendSoundStopCmd(serialPortService.Sp, DevCode.Dev1);
+ CommandSender.SendSoundStopCmd(serialPortService.Sp, RuntimeCache.Dev1);
audioService.Stop();
IsRedRecording = false;
RuntimeCache.SoundCaches.SaveSoundData();
@@ -205,7 +205,7 @@
///
private void StopBlueSensor(ISerialPortService serialPortService, IAudioService audioService)
{
- CommandSender.SendSoundStopCmd(serialPortService.Sp, DevCode.Dev2);
+ CommandSender.SendSoundStopCmd(serialPortService.Sp, RuntimeCache.Dev2);
audioService.Stop();
IsBlueRecording = false;
RuntimeCache.SoundCaches.SaveSoundData();
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs
index 43f84fd..91441a2 100644
--- a/Correlator/Dialog/CheckResponseDialog.xaml.cs
+++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs
@@ -231,7 +231,7 @@
if (RedSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev1);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1);
_redResponseTimer.Start();
ReCheckButton.IsEnabled = true;
@@ -239,11 +239,11 @@
else if (RedSensorStepBar.StepIndex == 2)
{
//下发数据全部正常指令
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev1}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev1}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.RedSensorOriginalResp orderby pair.Key select pair;
@@ -266,7 +266,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev1, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev1, tags);
#endregion
}
@@ -315,18 +315,18 @@
if (BlueSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev2);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2);
_blueResponseTimer.Start();
ReCheckButton.IsEnabled = true;
}
else if (BlueSensorStepBar.StepIndex == 2)
{
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev2}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev2}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.BlueSensorOriginalResp orderby pair.Key select pair;
@@ -349,7 +349,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev2, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev2, tags);
#endregion
}
@@ -396,7 +396,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, redIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray);
}
else
{
@@ -417,7 +417,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, blueIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray);
}
};
}
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml b/Correlator/Dialog/SimplyAuditionDialog.xaml
index 5fd8124..cd03b74 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml
@@ -9,7 +9,7 @@
xmlns:prism="http://prismlibrary.com/"
xmlns:vm="clr-namespace:Correlator.ViewModels"
Width="600"
- Height="400"
+ Height="480"
d:DataContext="{d:DesignInstance Type=vm:SimplyAuditionDialogViewModel}"
Loaded="SimplyAuditionDialog_OnLoaded"
Unloaded="SimplyAuditionDialog_OnUnloaded"
@@ -187,10 +187,15 @@
-
+ Background="{StaticResource MainThemeColor}">
+
+
+
+
+
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
index 3747ce0..41cb280 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
@@ -6,6 +7,8 @@
using System.Windows.Threading;
using Correlator.DataService;
using Correlator.Util;
+using NAudio.CoreAudioApi;
+using NAudio.Wave;
namespace Correlator.Dialog
{
@@ -16,6 +19,7 @@
{
private readonly AudioVisualizer _visualizer; // 可视化
private double[] _spectrumData; // 频谱数据
+ private readonly WasapiCapture _capture; // 音频捕获
private int _colorIndex;
private readonly Color[] _allColors;
@@ -29,29 +33,44 @@
Interval = new TimeSpan(0, 0, 0, 0, 30)
};
- public SimplyAuditionDialog(IApplicationDataService dataService, IAudioService audioService)
+ public SimplyAuditionDialog(IApplicationDataService dataService)
{
InitializeComponent();
- // _visualizer = dataService.GetAudioVisualizer(256);
- // _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
- //
- // audioService.AudioVisualizer = _visualizer;
- //
- // _dataTimer.Tick += DataTimer_Tick;
- // _drawingTimer.Tick += DrawingTimer_Tick;
+ _capture = new WasapiLoopbackCapture(); // 捕获电脑发出的声音
+ _visualizer = dataService.GetAudioVisualizer(512);
+ _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
+
+ _capture.WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(7500, 1);
+ _capture.DataAvailable += delegate(object o, WaveInEventArgs args)
+ {
+ var length = args.BytesRecorded / 4; // 采样的数量 (每一个采样是 4 字节)
+ var result = new double[length];
+
+ for (var i = 0; i < length; i++)
+ {
+ result[i] = BitConverter.ToSingle(args.Buffer, i * 4); // 取出采样值
+ }
+
+ _visualizer.PushSampleData(result); // 将新的采样存储到 可视化器 中
+ };
+
+ _dataTimer.Tick += DataTimer_Tick;
+ _drawingTimer.Tick += DrawingTimer_Tick;
}
private void SimplyAuditionDialog_OnLoaded(object sender, RoutedEventArgs e)
{
- // _dataTimer.Start();
- // _drawingTimer.Start();
+ _capture.StartRecording();
+ _dataTimer.Start();
+ _drawingTimer.Start();
}
private void SimplyAuditionDialog_OnUnloaded(object sender, RoutedEventArgs e)
{
- // _drawingTimer.Stop();
- // _dataTimer.Stop();
+ _drawingTimer.Stop();
+ _dataTimer.Stop();
+ _capture.StopRecording();
}
///
@@ -62,7 +81,7 @@
private void DataTimer_Tick(object sender, EventArgs e)
{
var newSpectrumData = _visualizer.GetSpectrumData(); // 从可视化器中获取频谱数据
- newSpectrumData = AudioVisualizer.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
+ newSpectrumData = AudioDataHub.Get.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
if (_spectrumData == null) // 如果已经存储的频谱数据为空, 则把新的频谱数据直接赋值上去
{
@@ -92,80 +111,90 @@
var color1 = _allColors[_colorIndex % _allColors.Length];
var color2 = _allColors[(_colorIndex + 200) % _allColors.Length];
- DrawGradientStrips(
- StripsPath, color1, color2,
- _spectrumData, _spectrumData.Length,
- StripsPath.ActualWidth, 0, StripsPath.ActualHeight,
- 2, -StripsPath.ActualHeight * 200
+ var bassArea = AudioDataHub.Get.TakeSpectrumOfFrequency(
+ _spectrumData, RuntimeCache.AudioSampleRate, 250
+ );
+ var bassScale = bassArea.Average() * 100; //低音区
+
+ //波形曲线
+ var curveBrush = new SolidColorBrush(color1);
+ DrawCurve(
+ SampleWavePath, curveBrush,
+ _visualizer.SampleData, _visualizer.SampleData.Length,
+ SampleWavePanel.ActualWidth, 0, SampleWavePanel.ActualHeight / 2,
+ Math.Min(SampleWavePanel.ActualHeight / 2, 50)
+ );
+
+ //四周边框
+ DrawGradientBorder(
+ TopBorder, BottomBorder, LeftBorder, RightBorder,
+ Color.FromArgb(0, color1.R, color1.G, color1.B), color2,
+ SampleWavePanel.ActualWidth / 3, bassScale
);
}
///
- /// 绘制渐变的条形
+ /// 画曲线
///
- /// 绘图目标
- /// 下方颜色
- /// 上方颜色
- /// 频谱数据
- /// 条形的数量
- /// 绘图的宽度
- /// 绘图的起始 X 坐标
- /// 绘图的起始 Y 坐标
- /// 条形与条形之间的间隔(像素)
- /// 控制波形图波峰高度
- private void DrawGradientStrips(
- Path stripsPath, Color bottomColor, Color topColor, double[] spectrumData,
- int stripCount, double drawingWidth, double xOffset, double yOffset, double spacing, double scale
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 控制波形图波峰高度和波谷深度
+ private void DrawCurve(
+ Path wavePath, Brush brush, double[] spectrumData, int pointCount, double drawingWidth,
+ double xOffset, double yOffset, double scale
)
{
- //竖条宽度
- var stripWidth = (drawingWidth - spacing * stripCount) / stripCount;
- var pointArray = new Point[stripCount];
-
- for (var i = 0; i < stripCount; i++)
+ var pointArray = new Point[pointCount];
+ for (var i = 0; i < pointCount; i++)
{
- var x = stripWidth * i + spacing * i + xOffset;
- var y = spectrumData[i * spectrumData.Length / stripCount] * scale; // height
- //给所有频谱位置赋值
+ var x = i * drawingWidth / pointCount + xOffset;
+ var y = spectrumData[i * spectrumData.Length / pointCount] * scale + yOffset;
pointArray[i] = new Point(x, y);
}
- //生成一系列频谱竖条
- var geometry = new GeometryGroup();
- foreach (var point in pointArray)
+ var figure = new PathFigure
{
- var height = point.Y;
+ StartPoint = pointArray[0]
+ };
+ figure.Segments.Add(new PolyLineSegment(pointArray, true));
- if (height < 0)
- {
- height = -height;
- }
+ wavePath.Data = new PathGeometry { Figures = { figure } };
+ wavePath.Stroke = brush;
+ }
- //每根竖条的四个角坐标
- var endPoints = new[]
- {
- new Point(point.X, point.Y + yOffset), //左下角
- new Point(point.X, point.Y + height + yOffset), //左上角
- new Point(point.X + stripWidth, point.Y + height + yOffset), //右上角
- new Point(point.X + stripWidth, point.Y + yOffset) //右下角
- };
+ ///
+ /// 画四周渐变边框
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 画图宽度
+ /// 高低音转化比例
+ private void DrawGradientBorder(
+ Rectangle topBorder, Rectangle bottomBorder, Rectangle leftBorder,
+ Rectangle rightBorder, Color inner, Color outer, double width, double bassScale
+ )
+ {
+ //边框粗细根据音频高低音变化
+ var thickness = (int)(width * bassScale);
- var figure = new PathFigure
- {
- StartPoint = endPoints[0]
- };
+ topBorder.Height = thickness;
+ bottomBorder.Height = thickness;
+ leftBorder.Width = thickness;
+ rightBorder.Width = thickness;
- figure.Segments.Add(new PolyLineSegment(endPoints, false));
- geometry.Children.Add(new PathGeometry { Figures = { figure } });
- }
-
- stripsPath.Data = geometry;
-
- //设置频谱竖条的渐变色
- var linearGradientBrush = new LinearGradientBrush(
- bottomColor, topColor, new Point(0, 0), new Point(0, 1)
- );
- stripsPath.Fill = linearGradientBrush;
+ topBorder.Fill = new LinearGradientBrush(outer, inner, 90);
+ bottomBorder.Fill = new LinearGradientBrush(inner, outer, 90);
+ leftBorder.Fill = new LinearGradientBrush(outer, inner, 0);
+ rightBorder.Fill = new LinearGradientBrush(inner, outer, 0);
}
}
}
\ No newline at end of file
diff --git a/Correlator/SensorHubTag/DevCode.cs b/Correlator/SensorHubTag/DevCode.cs
deleted file mode 100644
index afd5e8f..0000000
--- a/Correlator/SensorHubTag/DevCode.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Correlator.SensorHubTag
-{
- public static class DevCode
- {
- public static string Dev1 => "211700082201";
-
- public static string Dev2 => "211700082202";
- }
-}
\ No newline at end of file
diff --git a/Correlator/Util/AudioDataHub.cs b/Correlator/Util/AudioDataHub.cs
new file mode 100644
index 0000000..72d62ea
--- /dev/null
+++ b/Correlator/Util/AudioDataHub.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+
+namespace Correlator.Util
+{
+ ///
+ /// 音频可视化数据处理
+ ///
+ public class AudioDataHub
+ {
+ #region 懒汉单例模式
+
+ private static readonly Lazy Lazy = new Lazy(() => new AudioDataHub());
+
+ public static AudioDataHub Get => Lazy.Value;
+
+
+ private AudioDataHub()
+ {
+ }
+
+ #endregion
+
+ private double[] _smoothResult;
+
+ public double[] TakeSpectrumOfFrequency(double[] spectrum, double sampleRate, double frequency)
+ {
+ var frequencyPerSample = sampleRate / spectrum.Length;
+
+ var lengthInNeed = (int)Math.Min(frequency / frequencyPerSample, spectrum.Length);
+ var result = new double[lengthInNeed];
+ Array.Copy(spectrum, 0, result, 0, lengthInNeed);
+ return result;
+ }
+
+ ///
+ /// 简单的数据模糊
+ ///
+ /// 数据
+ /// 模糊半径
+ /// 结果
+ public double[] MakeSmooth(double[] data, int radius)
+ {
+ var weights = GetWeights(radius);
+ var buffer = new double[1 + radius * 2];
+
+ _smoothResult = new double[data.Length];
+ if (data.Length < radius)
+ {
+ data.Average();
+ _smoothResult.SetValue(data, 0);
+ return _smoothResult;
+ }
+
+ for (var i = 0; i < radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = radius; i < data.Length - radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[j] = data[i - j];
+ }
+
+ buffer[radius] = data[i];
+
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + j + 1] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = data.Length - radius; i < data.Length; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i - j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ return _smoothResult;
+ }
+
+ private double[] GetWeights(int radius)
+ {
+ double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
+
+ var len = 1 + radius * 2; // 长度
+ var end = len - 1; // 最后的索引
+ var radiusF = (double)radius; // 半径浮点数
+ var weights = new double[len]; // 权重
+
+ for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
+ {
+ weights[radius + i] = Gaussian(i / radiusF);
+ }
+
+ for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
+ {
+ weights[i] = weights[end - i];
+ }
+
+ var total = weights.Sum();
+ for (var i = 0; i < len; i++) // 使权重合为 0
+ {
+ weights[i] /= total;
+ }
+
+ return weights;
+ }
+
+ private void ApplyWeights(double[] buffer, double[] weights)
+ {
+ var len = buffer.Length;
+ for (var i = 0; i < len; i++)
+ {
+ buffer[i] *= weights[i];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Correlator/Util/AudioVisualizer.cs b/Correlator/Util/AudioVisualizer.cs
index 9a888f5..393f7df 100644
--- a/Correlator/Util/AudioVisualizer.cs
+++ b/Correlator/Util/AudioVisualizer.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using FftSharp;
using FftSharp.Windows;
using Complex = System.Numerics.Complex;
@@ -13,6 +12,8 @@
///
public double[] SampleData { get; }
+ private Complex[] _data;
+
///
///
///
@@ -63,126 +64,27 @@
public double[] GetSpectrumData()
{
var len = SampleData.Length;
- var data = new Complex[len];
-
+ _data = new Complex[len];
+
for (var i = 0; i < len; i++)
{
- data[i] = new Complex(SampleData[i], 0);
+ _data[i] = new Complex(SampleData[i], 0);
}
-
- FFT.Forward(data);
-
+
+ FFT.Forward(_data);
+
var halfLen = len / 2;
var result = new double[halfLen]; // 傅里叶变换结果左右对称, 只需要取一半
for (var i = 0; i < halfLen; i++)
{
- result[i] = data[i].Magnitude / len;
+ result[i] = _data[i].Magnitude / len;
}
-
+
var window = new Bartlett();
window.Create(halfLen);
window.ApplyInPlace(result);
-
+
return result;
}
-
- ///
- /// 简单的数据模糊
- ///
- /// 数据
- /// 模糊半径
- /// 结果
- public static double[] MakeSmooth(double[] data, int radius)
- {
- var weights = GetWeights(radius);
- var buffer = new double[1 + radius * 2];
-
- var result = new double[data.Length];
- if (data.Length < radius)
- {
- data.Average();
- result.SetValue(data, 0);
- return result;
- }
-
- for (var i = 0; i < radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = radius; i < data.Length - radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[j] = data[i - j];
- }
-
- buffer[radius] = data[i];
-
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + j + 1] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = data.Length - radius; i < data.Length; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i - j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- return result;
- }
-
- private static double[] GetWeights(int radius)
- {
- double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
-
- var len = 1 + radius * 2; // 长度
- var end = len - 1; // 最后的索引
- var radiusF = (double)radius; // 半径浮点数
- var weights = new double[len]; // 权重
-
- for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
- {
- weights[radius + i] = Gaussian(i / radiusF);
- }
-
- for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
- {
- weights[i] = weights[end - i];
- }
-
- var total = weights.Sum();
- for (var i = 0; i < len; i++) // 使权重合为 0
- {
- weights[i] /= total;
- }
-
- return weights;
- }
-
- private static void ApplyWeights(double[] buffer, double[] weights)
- {
- var len = buffer.Length;
- for (var i = 0; i < len; i++)
- {
- buffer[i] *= weights[i];
- }
- }
}
}
\ No newline at end of file
diff --git a/Correlator/Util/RuntimeCache.cs b/Correlator/Util/RuntimeCache.cs
index 468ca7f..4a1e94e 100644
--- a/Correlator/Util/RuntimeCache.cs
+++ b/Correlator/Util/RuntimeCache.cs
@@ -86,5 +86,15 @@
/// 采样率
///
public const int AudioSampleRate = 7500;
+
+ ///
+ /// 设备1(红色的)
+ ///
+ public static string Dev1 => "211700082201";
+
+ ///
+ /// 设备2(蓝色的)
+ ///
+ public static string Dev2 => "211700082202";
}
}
\ No newline at end of file
diff --git a/Correlator/ViewModels/ImportResponseDialogViewModel.cs b/Correlator/ViewModels/ImportResponseDialogViewModel.cs
index 5b6c1f3..af9c398 100644
--- a/Correlator/ViewModels/ImportResponseDialogViewModel.cs
+++ b/Correlator/ViewModels/ImportResponseDialogViewModel.cs
@@ -286,7 +286,7 @@
Thread.Sleep(10);
}
- _dataModel.DevCode = DevCode.Dev1;
+ _dataModel.DevCode = RuntimeCache.Dev1;
_dataModel.LeftReceiveDataTime = DateTime.Now;
_dataModel.LeftDeviceDataArray = totalData.ToArray();
}
@@ -312,7 +312,7 @@
Thread.Sleep(10);
}
- _dataModel.DevCode = DevCode.Dev2;
+ _dataModel.DevCode = RuntimeCache.Dev2;
_dataModel.RightReceiveDataTime = DateTime.Now;
_dataModel.RightDeviceDataArray = totalData.ToArray();
}
diff --git a/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs b/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs
index d1f6f4c..9322765 100644
--- a/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs
+++ b/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs
@@ -129,8 +129,8 @@
}
else
{
- CommandSender.SendSoundCollectCmd(serialPortService.Sp, DevCode.Dev1);
- audioService.Start(DevCode.Dev1);
+ CommandSender.SendSoundCollectCmd(serialPortService.Sp, RuntimeCache.Dev1);
+ audioService.Start(RuntimeCache.Dev1);
IsRedRecording = true;
}
});
@@ -178,8 +178,8 @@
}
else
{
- CommandSender.SendSoundCollectCmd(serialPortService.Sp, DevCode.Dev2);
- audioService.Start(DevCode.Dev2);
+ CommandSender.SendSoundCollectCmd(serialPortService.Sp, RuntimeCache.Dev2);
+ audioService.Start(RuntimeCache.Dev2);
IsBlueRecording = true;
}
});
@@ -192,7 +192,7 @@
///
private void StopRedSensor(ISerialPortService serialPortService, IAudioService audioService)
{
- CommandSender.SendSoundStopCmd(serialPortService.Sp, DevCode.Dev1);
+ CommandSender.SendSoundStopCmd(serialPortService.Sp, RuntimeCache.Dev1);
audioService.Stop();
IsRedRecording = false;
RuntimeCache.SoundCaches.SaveSoundData();
@@ -205,7 +205,7 @@
///
private void StopBlueSensor(ISerialPortService serialPortService, IAudioService audioService)
{
- CommandSender.SendSoundStopCmd(serialPortService.Sp, DevCode.Dev2);
+ CommandSender.SendSoundStopCmd(serialPortService.Sp, RuntimeCache.Dev2);
audioService.Stop();
IsBlueRecording = false;
RuntimeCache.SoundCaches.SaveSoundData();
diff --git a/Correlator/Views/AudioFileView.xaml.cs b/Correlator/Views/AudioFileView.xaml.cs
index 76e7f1b..b59a84f 100644
--- a/Correlator/Views/AudioFileView.xaml.cs
+++ b/Correlator/Views/AudioFileView.xaml.cs
@@ -77,7 +77,7 @@
private void DataTimer_Tick(object sender, EventArgs e)
{
var newSpectrumData = _visualizer.GetSpectrumData(); // 从可视化器中获取频谱数据
- newSpectrumData = AudioVisualizer.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
+ newSpectrumData = AudioDataHub.Get.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
if (_spectrumData == null) // 如果已经存储的频谱数据为空, 则把新的频谱数据直接赋值上去
{
diff --git a/Correlator/Correlator.csproj b/Correlator/Correlator.csproj
index b4a4553..8163935 100644
--- a/Correlator/Correlator.csproj
+++ b/Correlator/Correlator.csproj
@@ -251,7 +251,6 @@
-
@@ -262,6 +261,7 @@
+
diff --git a/Correlator/DataService/AudioServiceImpl.cs b/Correlator/DataService/AudioServiceImpl.cs
index 9227651..f5dbe51 100644
--- a/Correlator/DataService/AudioServiceImpl.cs
+++ b/Correlator/DataService/AudioServiceImpl.cs
@@ -1,5 +1,4 @@
using System;
-using Correlator.SensorHubTag;
using Correlator.Util;
using NAudio.Wave;
@@ -12,18 +11,19 @@
private BufferedWaveProvider _waveProvider;
private readonly WaveFormat _waveFormat = new WaveFormat(7500, 24, 1);
+ public WaveOutEvent Wave { get; set; } = new WaveOutEvent();
+
public void Start(string deviceCode)
{
_isStopped = false;
_waveProvider = new BufferedWaveProvider(_waveFormat);
- var waveOut = new WaveOut();
- waveOut.Init(_waveProvider);
+ Wave.Init(_waveProvider);
string fileName;
var audioDir = DirectoryManager.GetAudioDir();
var time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
- if (deviceCode == DevCode.Dev1)
+ if (deviceCode == RuntimeCache.Dev1)
{
//红色传感器听音
fileName = $"{audioDir}/听音_红_{time}.wav";
@@ -36,7 +36,7 @@
_waveFileWriter = new WaveFileWriter(fileName, _waveFormat);
- waveOut.Play();
+ Wave.Play();
}
//缓存声波数据已经是后台线程了(处于线程池中)
@@ -47,18 +47,23 @@
return;
}
- _waveProvider?.AddSamples(pcm, 0, pcm.Length);
- _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ try
+ {
+ _waveProvider?.AddSamples(pcm, 0, pcm.Length);
+ _waveFileWriter?.Write(pcm, 0, pcm.Length);
+ }
+ catch (InvalidOperationException)
+ {
+ _waveProvider?.ClearBuffer();
+ }
}
public void Stop()
{
_isStopped = true;
-
+ Wave.Stop();
_waveProvider.ClearBuffer();
_waveFileWriter.Dispose();
}
-
- // public AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/IAudioService.cs b/Correlator/DataService/IAudioService.cs
index 83609b2..f6e157a 100644
--- a/Correlator/DataService/IAudioService.cs
+++ b/Correlator/DataService/IAudioService.cs
@@ -1,7 +1,11 @@
-namespace Correlator.DataService
+using NAudio.Wave;
+
+namespace Correlator.DataService
{
public interface IAudioService
{
+ WaveOutEvent Wave { get; set; }
+
///
/// 开始听音
///
@@ -18,7 +22,5 @@
/// 结束听音
///
void Stop();
-
- // AudioVisualizer AudioVisualizer { get; set; }
}
}
\ No newline at end of file
diff --git a/Correlator/DataService/SerialPortServiceImpl.cs b/Correlator/DataService/SerialPortServiceImpl.cs
index 0a7e32f..824eccb 100644
--- a/Correlator/DataService/SerialPortServiceImpl.cs
+++ b/Correlator/DataService/SerialPortServiceImpl.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO.Ports;
-using System.Text;
using System.Threading;
using System.Windows;
using Correlator.Events;
@@ -131,7 +130,7 @@
}
//发送消息更新界面
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
_eventAggregator.GetEvent().Publish(_devStatus);
}
@@ -173,7 +172,7 @@
var response = BitConverter.ToString(receivedData).Replace("-", "");
//收集数据
- if (deviceId.Equals(DevCode.Dev1))
+ if (deviceId.Equals(RuntimeCache.Dev1))
{
//原始数据
RuntimeCache.RedSensorOriginalResp.Add(index, response);
@@ -218,7 +217,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
//接收到数据之后时间重新赋值
_dataModel.LeftReceiveDataTime = DateTime.Now;
@@ -271,16 +270,6 @@
//将pcm数据写入缓存
_audioService.Write(pcm);
-
- //波形图数据
- var length = pcm.Length / 4;
- var spectrumData = new double[length];
- for (var i = 0; i < length; i++)
- {
- spectrumData[i] = BitConverter.ToSingle(pcm, i * 4);
- }
-
- // _audioService.AudioVisualizer.PushSampleData(spectrumData);
}
}
@@ -310,7 +299,7 @@
}
_dataModel.DevCode = devCode;
- if (devCode.Equals(DevCode.Dev1))
+ if (devCode.Equals(RuntimeCache.Dev1))
{
_dataModel.LeftDeviceDataArray = doubleArrays.ToOneDimensionalArray();
}
diff --git a/Correlator/Dialog/CheckResponseDialog.xaml.cs b/Correlator/Dialog/CheckResponseDialog.xaml.cs
index 43f84fd..91441a2 100644
--- a/Correlator/Dialog/CheckResponseDialog.xaml.cs
+++ b/Correlator/Dialog/CheckResponseDialog.xaml.cs
@@ -231,7 +231,7 @@
if (RedSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev1);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev1);
_redResponseTimer.Start();
ReCheckButton.IsEnabled = true;
@@ -239,11 +239,11 @@
else if (RedSensorStepBar.StepIndex == 2)
{
//下发数据全部正常指令
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev1}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev1}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.RedSensorOriginalResp orderby pair.Key select pair;
@@ -266,7 +266,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev1, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev1, tags);
#endregion
}
@@ -315,18 +315,18 @@
if (BlueSensorStepBar.StepIndex == 1)
{
RuntimeCache.SeqCaches.Clear();
- CommandSender.StartCheckResponse(_serialPortService.Sp, DevCode.Dev2);
+ CommandSender.StartCheckResponse(_serialPortService.Sp, RuntimeCache.Dev2);
_blueResponseTimer.Start();
ReCheckButton.IsEnabled = true;
}
else if (BlueSensorStepBar.StepIndex == 2)
{
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, new List());
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, new List());
#region 保存原始数据
- var fileName = $"{locateDataDir}\\原始数据.{DevCode.Dev2}.txt";
+ var fileName = $"{locateDataDir}\\原始数据.{RuntimeCache.Dev2}.txt";
//将Dictionary按照index排序
var sortResult = from pair in RuntimeCache.BlueSensorOriginalResp orderby pair.Key select pair;
@@ -349,7 +349,7 @@
tags.Add(noiseTag);
}
- _serialPortService.HandleHydrophoneData(DevCode.Dev2, tags);
+ _serialPortService.HandleHydrophoneData(RuntimeCache.Dev2, tags);
#endregion
}
@@ -396,7 +396,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev1, redIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev1, redIndexArray);
}
else
{
@@ -417,7 +417,7 @@
}
}
- CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, DevCode.Dev2, blueIndexArray);
+ CommandSender.SendDataCheckResultCmd(_serialPortService.Sp, RuntimeCache.Dev2, blueIndexArray);
}
};
}
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml b/Correlator/Dialog/SimplyAuditionDialog.xaml
index 5fd8124..cd03b74 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml
@@ -9,7 +9,7 @@
xmlns:prism="http://prismlibrary.com/"
xmlns:vm="clr-namespace:Correlator.ViewModels"
Width="600"
- Height="400"
+ Height="480"
d:DataContext="{d:DesignInstance Type=vm:SimplyAuditionDialogViewModel}"
Loaded="SimplyAuditionDialog_OnLoaded"
Unloaded="SimplyAuditionDialog_OnUnloaded"
@@ -187,10 +187,15 @@
-
+ Background="{StaticResource MainThemeColor}">
+
+
+
+
+
diff --git a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
index 3747ce0..41cb280 100644
--- a/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
+++ b/Correlator/Dialog/SimplyAuditionDialog.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
@@ -6,6 +7,8 @@
using System.Windows.Threading;
using Correlator.DataService;
using Correlator.Util;
+using NAudio.CoreAudioApi;
+using NAudio.Wave;
namespace Correlator.Dialog
{
@@ -16,6 +19,7 @@
{
private readonly AudioVisualizer _visualizer; // 可视化
private double[] _spectrumData; // 频谱数据
+ private readonly WasapiCapture _capture; // 音频捕获
private int _colorIndex;
private readonly Color[] _allColors;
@@ -29,29 +33,44 @@
Interval = new TimeSpan(0, 0, 0, 0, 30)
};
- public SimplyAuditionDialog(IApplicationDataService dataService, IAudioService audioService)
+ public SimplyAuditionDialog(IApplicationDataService dataService)
{
InitializeComponent();
- // _visualizer = dataService.GetAudioVisualizer(256);
- // _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
- //
- // audioService.AudioVisualizer = _visualizer;
- //
- // _dataTimer.Tick += DataTimer_Tick;
- // _drawingTimer.Tick += DrawingTimer_Tick;
+ _capture = new WasapiLoopbackCapture(); // 捕获电脑发出的声音
+ _visualizer = dataService.GetAudioVisualizer(512);
+ _allColors = dataService.GetAllHsvColors(); // 获取所有的渐变颜色 (HSV 颜色)
+
+ _capture.WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(7500, 1);
+ _capture.DataAvailable += delegate(object o, WaveInEventArgs args)
+ {
+ var length = args.BytesRecorded / 4; // 采样的数量 (每一个采样是 4 字节)
+ var result = new double[length];
+
+ for (var i = 0; i < length; i++)
+ {
+ result[i] = BitConverter.ToSingle(args.Buffer, i * 4); // 取出采样值
+ }
+
+ _visualizer.PushSampleData(result); // 将新的采样存储到 可视化器 中
+ };
+
+ _dataTimer.Tick += DataTimer_Tick;
+ _drawingTimer.Tick += DrawingTimer_Tick;
}
private void SimplyAuditionDialog_OnLoaded(object sender, RoutedEventArgs e)
{
- // _dataTimer.Start();
- // _drawingTimer.Start();
+ _capture.StartRecording();
+ _dataTimer.Start();
+ _drawingTimer.Start();
}
private void SimplyAuditionDialog_OnUnloaded(object sender, RoutedEventArgs e)
{
- // _drawingTimer.Stop();
- // _dataTimer.Stop();
+ _drawingTimer.Stop();
+ _dataTimer.Stop();
+ _capture.StopRecording();
}
///
@@ -62,7 +81,7 @@
private void DataTimer_Tick(object sender, EventArgs e)
{
var newSpectrumData = _visualizer.GetSpectrumData(); // 从可视化器中获取频谱数据
- newSpectrumData = AudioVisualizer.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
+ newSpectrumData = AudioDataHub.Get.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
if (_spectrumData == null) // 如果已经存储的频谱数据为空, 则把新的频谱数据直接赋值上去
{
@@ -92,80 +111,90 @@
var color1 = _allColors[_colorIndex % _allColors.Length];
var color2 = _allColors[(_colorIndex + 200) % _allColors.Length];
- DrawGradientStrips(
- StripsPath, color1, color2,
- _spectrumData, _spectrumData.Length,
- StripsPath.ActualWidth, 0, StripsPath.ActualHeight,
- 2, -StripsPath.ActualHeight * 200
+ var bassArea = AudioDataHub.Get.TakeSpectrumOfFrequency(
+ _spectrumData, RuntimeCache.AudioSampleRate, 250
+ );
+ var bassScale = bassArea.Average() * 100; //低音区
+
+ //波形曲线
+ var curveBrush = new SolidColorBrush(color1);
+ DrawCurve(
+ SampleWavePath, curveBrush,
+ _visualizer.SampleData, _visualizer.SampleData.Length,
+ SampleWavePanel.ActualWidth, 0, SampleWavePanel.ActualHeight / 2,
+ Math.Min(SampleWavePanel.ActualHeight / 2, 50)
+ );
+
+ //四周边框
+ DrawGradientBorder(
+ TopBorder, BottomBorder, LeftBorder, RightBorder,
+ Color.FromArgb(0, color1.R, color1.G, color1.B), color2,
+ SampleWavePanel.ActualWidth / 3, bassScale
);
}
///
- /// 绘制渐变的条形
+ /// 画曲线
///
- /// 绘图目标
- /// 下方颜色
- /// 上方颜色
- /// 频谱数据
- /// 条形的数量
- /// 绘图的宽度
- /// 绘图的起始 X 坐标
- /// 绘图的起始 Y 坐标
- /// 条形与条形之间的间隔(像素)
- /// 控制波形图波峰高度
- private void DrawGradientStrips(
- Path stripsPath, Color bottomColor, Color topColor, double[] spectrumData,
- int stripCount, double drawingWidth, double xOffset, double yOffset, double spacing, double scale
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 控制波形图波峰高度和波谷深度
+ private void DrawCurve(
+ Path wavePath, Brush brush, double[] spectrumData, int pointCount, double drawingWidth,
+ double xOffset, double yOffset, double scale
)
{
- //竖条宽度
- var stripWidth = (drawingWidth - spacing * stripCount) / stripCount;
- var pointArray = new Point[stripCount];
-
- for (var i = 0; i < stripCount; i++)
+ var pointArray = new Point[pointCount];
+ for (var i = 0; i < pointCount; i++)
{
- var x = stripWidth * i + spacing * i + xOffset;
- var y = spectrumData[i * spectrumData.Length / stripCount] * scale; // height
- //给所有频谱位置赋值
+ var x = i * drawingWidth / pointCount + xOffset;
+ var y = spectrumData[i * spectrumData.Length / pointCount] * scale + yOffset;
pointArray[i] = new Point(x, y);
}
- //生成一系列频谱竖条
- var geometry = new GeometryGroup();
- foreach (var point in pointArray)
+ var figure = new PathFigure
{
- var height = point.Y;
+ StartPoint = pointArray[0]
+ };
+ figure.Segments.Add(new PolyLineSegment(pointArray, true));
- if (height < 0)
- {
- height = -height;
- }
+ wavePath.Data = new PathGeometry { Figures = { figure } };
+ wavePath.Stroke = brush;
+ }
- //每根竖条的四个角坐标
- var endPoints = new[]
- {
- new Point(point.X, point.Y + yOffset), //左下角
- new Point(point.X, point.Y + height + yOffset), //左上角
- new Point(point.X + stripWidth, point.Y + height + yOffset), //右上角
- new Point(point.X + stripWidth, point.Y + yOffset) //右下角
- };
+ ///
+ /// 画四周渐变边框
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 画图宽度
+ /// 高低音转化比例
+ private void DrawGradientBorder(
+ Rectangle topBorder, Rectangle bottomBorder, Rectangle leftBorder,
+ Rectangle rightBorder, Color inner, Color outer, double width, double bassScale
+ )
+ {
+ //边框粗细根据音频高低音变化
+ var thickness = (int)(width * bassScale);
- var figure = new PathFigure
- {
- StartPoint = endPoints[0]
- };
+ topBorder.Height = thickness;
+ bottomBorder.Height = thickness;
+ leftBorder.Width = thickness;
+ rightBorder.Width = thickness;
- figure.Segments.Add(new PolyLineSegment(endPoints, false));
- geometry.Children.Add(new PathGeometry { Figures = { figure } });
- }
-
- stripsPath.Data = geometry;
-
- //设置频谱竖条的渐变色
- var linearGradientBrush = new LinearGradientBrush(
- bottomColor, topColor, new Point(0, 0), new Point(0, 1)
- );
- stripsPath.Fill = linearGradientBrush;
+ topBorder.Fill = new LinearGradientBrush(outer, inner, 90);
+ bottomBorder.Fill = new LinearGradientBrush(inner, outer, 90);
+ leftBorder.Fill = new LinearGradientBrush(outer, inner, 0);
+ rightBorder.Fill = new LinearGradientBrush(inner, outer, 0);
}
}
}
\ No newline at end of file
diff --git a/Correlator/SensorHubTag/DevCode.cs b/Correlator/SensorHubTag/DevCode.cs
deleted file mode 100644
index afd5e8f..0000000
--- a/Correlator/SensorHubTag/DevCode.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Correlator.SensorHubTag
-{
- public static class DevCode
- {
- public static string Dev1 => "211700082201";
-
- public static string Dev2 => "211700082202";
- }
-}
\ No newline at end of file
diff --git a/Correlator/Util/AudioDataHub.cs b/Correlator/Util/AudioDataHub.cs
new file mode 100644
index 0000000..72d62ea
--- /dev/null
+++ b/Correlator/Util/AudioDataHub.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+
+namespace Correlator.Util
+{
+ ///
+ /// 音频可视化数据处理
+ ///
+ public class AudioDataHub
+ {
+ #region 懒汉单例模式
+
+ private static readonly Lazy Lazy = new Lazy(() => new AudioDataHub());
+
+ public static AudioDataHub Get => Lazy.Value;
+
+
+ private AudioDataHub()
+ {
+ }
+
+ #endregion
+
+ private double[] _smoothResult;
+
+ public double[] TakeSpectrumOfFrequency(double[] spectrum, double sampleRate, double frequency)
+ {
+ var frequencyPerSample = sampleRate / spectrum.Length;
+
+ var lengthInNeed = (int)Math.Min(frequency / frequencyPerSample, spectrum.Length);
+ var result = new double[lengthInNeed];
+ Array.Copy(spectrum, 0, result, 0, lengthInNeed);
+ return result;
+ }
+
+ ///
+ /// 简单的数据模糊
+ ///
+ /// 数据
+ /// 模糊半径
+ /// 结果
+ public double[] MakeSmooth(double[] data, int radius)
+ {
+ var weights = GetWeights(radius);
+ var buffer = new double[1 + radius * 2];
+
+ _smoothResult = new double[data.Length];
+ if (data.Length < radius)
+ {
+ data.Average();
+ _smoothResult.SetValue(data, 0);
+ return _smoothResult;
+ }
+
+ for (var i = 0; i < radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = radius; i < data.Length - radius; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[j] = data[i - j];
+ }
+
+ buffer[radius] = data[i];
+
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + j + 1] = data[i + j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ for (var i = data.Length - radius; i < data.Length; i++)
+ {
+ for (var j = 0; j < radius; j++) //
+ {
+ buffer[radius + 1 + j] = data[i - j];
+ }
+
+ ApplyWeights(buffer, weights);
+ _smoothResult[i] = buffer.Sum();
+ }
+
+ return _smoothResult;
+ }
+
+ private double[] GetWeights(int radius)
+ {
+ double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
+
+ var len = 1 + radius * 2; // 长度
+ var end = len - 1; // 最后的索引
+ var radiusF = (double)radius; // 半径浮点数
+ var weights = new double[len]; // 权重
+
+ for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
+ {
+ weights[radius + i] = Gaussian(i / radiusF);
+ }
+
+ for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
+ {
+ weights[i] = weights[end - i];
+ }
+
+ var total = weights.Sum();
+ for (var i = 0; i < len; i++) // 使权重合为 0
+ {
+ weights[i] /= total;
+ }
+
+ return weights;
+ }
+
+ private void ApplyWeights(double[] buffer, double[] weights)
+ {
+ var len = buffer.Length;
+ for (var i = 0; i < len; i++)
+ {
+ buffer[i] *= weights[i];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Correlator/Util/AudioVisualizer.cs b/Correlator/Util/AudioVisualizer.cs
index 9a888f5..393f7df 100644
--- a/Correlator/Util/AudioVisualizer.cs
+++ b/Correlator/Util/AudioVisualizer.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using FftSharp;
using FftSharp.Windows;
using Complex = System.Numerics.Complex;
@@ -13,6 +12,8 @@
///
public double[] SampleData { get; }
+ private Complex[] _data;
+
///
///
///
@@ -63,126 +64,27 @@
public double[] GetSpectrumData()
{
var len = SampleData.Length;
- var data = new Complex[len];
-
+ _data = new Complex[len];
+
for (var i = 0; i < len; i++)
{
- data[i] = new Complex(SampleData[i], 0);
+ _data[i] = new Complex(SampleData[i], 0);
}
-
- FFT.Forward(data);
-
+
+ FFT.Forward(_data);
+
var halfLen = len / 2;
var result = new double[halfLen]; // 傅里叶变换结果左右对称, 只需要取一半
for (var i = 0; i < halfLen; i++)
{
- result[i] = data[i].Magnitude / len;
+ result[i] = _data[i].Magnitude / len;
}
-
+
var window = new Bartlett();
window.Create(halfLen);
window.ApplyInPlace(result);
-
+
return result;
}
-
- ///
- /// 简单的数据模糊
- ///
- /// 数据
- /// 模糊半径
- /// 结果
- public static double[] MakeSmooth(double[] data, int radius)
- {
- var weights = GetWeights(radius);
- var buffer = new double[1 + radius * 2];
-
- var result = new double[data.Length];
- if (data.Length < radius)
- {
- data.Average();
- result.SetValue(data, 0);
- return result;
- }
-
- for (var i = 0; i < radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = radius; i < data.Length - radius; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[j] = data[i - j];
- }
-
- buffer[radius] = data[i];
-
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + j + 1] = data[i + j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- for (var i = data.Length - radius; i < data.Length; i++)
- {
- for (var j = 0; j < radius; j++) //
- {
- buffer[radius + 1 + j] = data[i - j];
- }
-
- ApplyWeights(buffer, weights);
- result[i] = buffer.Sum();
- }
-
- return result;
- }
-
- private static double[] GetWeights(int radius)
- {
- double Gaussian(double x) => Math.Pow(Math.E, -4 * x * x); // 高斯函数
-
- var len = 1 + radius * 2; // 长度
- var end = len - 1; // 最后的索引
- var radiusF = (double)radius; // 半径浮点数
- var weights = new double[len]; // 权重
-
- for (var i = 0; i <= radius; i++) // 先把右边的权重算出来
- {
- weights[radius + i] = Gaussian(i / radiusF);
- }
-
- for (var i = 0; i < radius; i++) // 把右边的权重拷贝到左边
- {
- weights[i] = weights[end - i];
- }
-
- var total = weights.Sum();
- for (var i = 0; i < len; i++) // 使权重合为 0
- {
- weights[i] /= total;
- }
-
- return weights;
- }
-
- private static void ApplyWeights(double[] buffer, double[] weights)
- {
- var len = buffer.Length;
- for (var i = 0; i < len; i++)
- {
- buffer[i] *= weights[i];
- }
- }
}
}
\ No newline at end of file
diff --git a/Correlator/Util/RuntimeCache.cs b/Correlator/Util/RuntimeCache.cs
index 468ca7f..4a1e94e 100644
--- a/Correlator/Util/RuntimeCache.cs
+++ b/Correlator/Util/RuntimeCache.cs
@@ -86,5 +86,15 @@
/// 采样率
///
public const int AudioSampleRate = 7500;
+
+ ///
+ /// 设备1(红色的)
+ ///
+ public static string Dev1 => "211700082201";
+
+ ///
+ /// 设备2(蓝色的)
+ ///
+ public static string Dev2 => "211700082202";
}
}
\ No newline at end of file
diff --git a/Correlator/ViewModels/ImportResponseDialogViewModel.cs b/Correlator/ViewModels/ImportResponseDialogViewModel.cs
index 5b6c1f3..af9c398 100644
--- a/Correlator/ViewModels/ImportResponseDialogViewModel.cs
+++ b/Correlator/ViewModels/ImportResponseDialogViewModel.cs
@@ -286,7 +286,7 @@
Thread.Sleep(10);
}
- _dataModel.DevCode = DevCode.Dev1;
+ _dataModel.DevCode = RuntimeCache.Dev1;
_dataModel.LeftReceiveDataTime = DateTime.Now;
_dataModel.LeftDeviceDataArray = totalData.ToArray();
}
@@ -312,7 +312,7 @@
Thread.Sleep(10);
}
- _dataModel.DevCode = DevCode.Dev2;
+ _dataModel.DevCode = RuntimeCache.Dev2;
_dataModel.RightReceiveDataTime = DateTime.Now;
_dataModel.RightDeviceDataArray = totalData.ToArray();
}
diff --git a/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs b/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs
index d1f6f4c..9322765 100644
--- a/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs
+++ b/Correlator/ViewModels/SimplyAuditionDialogViewModel.cs
@@ -129,8 +129,8 @@
}
else
{
- CommandSender.SendSoundCollectCmd(serialPortService.Sp, DevCode.Dev1);
- audioService.Start(DevCode.Dev1);
+ CommandSender.SendSoundCollectCmd(serialPortService.Sp, RuntimeCache.Dev1);
+ audioService.Start(RuntimeCache.Dev1);
IsRedRecording = true;
}
});
@@ -178,8 +178,8 @@
}
else
{
- CommandSender.SendSoundCollectCmd(serialPortService.Sp, DevCode.Dev2);
- audioService.Start(DevCode.Dev2);
+ CommandSender.SendSoundCollectCmd(serialPortService.Sp, RuntimeCache.Dev2);
+ audioService.Start(RuntimeCache.Dev2);
IsBlueRecording = true;
}
});
@@ -192,7 +192,7 @@
///
private void StopRedSensor(ISerialPortService serialPortService, IAudioService audioService)
{
- CommandSender.SendSoundStopCmd(serialPortService.Sp, DevCode.Dev1);
+ CommandSender.SendSoundStopCmd(serialPortService.Sp, RuntimeCache.Dev1);
audioService.Stop();
IsRedRecording = false;
RuntimeCache.SoundCaches.SaveSoundData();
@@ -205,7 +205,7 @@
///
private void StopBlueSensor(ISerialPortService serialPortService, IAudioService audioService)
{
- CommandSender.SendSoundStopCmd(serialPortService.Sp, DevCode.Dev2);
+ CommandSender.SendSoundStopCmd(serialPortService.Sp, RuntimeCache.Dev2);
audioService.Stop();
IsBlueRecording = false;
RuntimeCache.SoundCaches.SaveSoundData();
diff --git a/Correlator/Views/AudioFileView.xaml.cs b/Correlator/Views/AudioFileView.xaml.cs
index 76e7f1b..b59a84f 100644
--- a/Correlator/Views/AudioFileView.xaml.cs
+++ b/Correlator/Views/AudioFileView.xaml.cs
@@ -77,7 +77,7 @@
private void DataTimer_Tick(object sender, EventArgs e)
{
var newSpectrumData = _visualizer.GetSpectrumData(); // 从可视化器中获取频谱数据
- newSpectrumData = AudioVisualizer.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
+ newSpectrumData = AudioDataHub.Get.MakeSmooth(newSpectrumData, 2); // 平滑频谱数据
if (_spectrumData == null) // 如果已经存储的频谱数据为空, 则把新的频谱数据直接赋值上去
{
diff --git a/Correlator/Views/MainWindow.xaml b/Correlator/Views/MainWindow.xaml
index 683db0a..8aa9c1e 100644
--- a/Correlator/Views/MainWindow.xaml
+++ b/Correlator/Views/MainWindow.xaml
@@ -863,7 +863,6 @@
Text="管道材料" />
-