前提・実現したいこと
C#で音声を取得してグラフ表示し、音の高さ・低さ(Hz)を値として取得するアプリを作成しているのですが、
作成できずにいます。
参考URLを見ながらある程度進めることはできたのですが、途中で躓いてしまいました。
この度実現したいことは3つです。
・一番大きい・小さい値の周波数を表示する
・二種グラフ表示する
・音量(デシベル)等の情報も値として表示させたい
発生している問題
参考URLの下のグラフの表示方法が不明(ProcessSample2)
処理の作り方に誤りがあるのか、下のグラフが表示されない。(ProcessSample2)
一番大きい値の周波数を求める方法が不明(ProcessSample2)
2020年10月7日16時00分 エラー箇所について更新します。
エラー発生個所
おそらくこの辺の個所の誤りなのかとは思うのですが、参考URLの内容ががいまいち理解できず苦戦しています。
C#
1 private void ProcessSample2(float sample) 2 { 3 var windowsize = _recorded2.Count; 4 5 _recorded2.Add(sample); 6 7 if (_recorded2.Count == 1024) 8 { 9 10 var window = Window.Hamming(windowsize); 11 _recorded2 = _recorded2.Select((v, i) => v * (float)window[i]).ToList(); 12 13 Complex[] complexData = _recorded2.Select(v => new Complex(v, 0.0)).ToArray(); 14 15 Fourier.Forward(complexData, FourierOptions.Matlab); // 16 17 var s = windowsize * (1.0 / 8000.0); 18 19 var point = complexData.Take(complexData.Count() / 2).Select((v, index) => 20 new DataPoint((double)index / s, 21 Math.Sqrt(v.Real * v.Real + v.Imaginary * v.Imaginary))).ToList(); 22 23 _lineSeries2.Points.Clear(); 24 _lineSeries2.Points.AddRange(point); 25 this.plotView2.InvalidatePlot(true); 26 27 } 28 29 } 30
該当のソースコード
C#
1 2using System; 3using System.Collections.Generic; 4using System.ComponentModel; 5using System.Data; 6using System.Drawing; 7using System.Linq; 8using System.Text; 9using System.Threading.Tasks; 10using System.Windows.Forms; 11using NAudio.Wave; 12using OxyPlot; 13using OxyPlot.Axes; 14using OxyPlot.Series; 15using MathNet.Numerics; 16using System.Numerics; 17using MathNet.Numerics.IntegralTransforms; 18 19namespace soundtest 20{ 21 public partial class Form1 : Form 22 { 23 public Form1() 24 { 25 InitializeComponent(); 26 } 27 28 private void Form1_Load(object sender, EventArgs e) 29 { 30 31 this.FormBorderStyle = FormBorderStyle.FixedSingle; 32 33 for (int i = 0; i < WaveIn.DeviceCount; i++) 34 { 35 var deviceInfo = WaveIn.GetCapabilities(i); 36 this.micname.Text = String.Format("Device {0}: {1}, {2} channels", 37 i, deviceInfo.ProductName, deviceInfo.Channels); 38 } 39 40 // グラフ初期化 41 InitPlot(); 42 43 } 44 45 private void recording_Click(object sender, EventArgs e) 46 { 47 WaveIn waveIn = new WaveIn() 48 { 49 DeviceNumber = 0, // Default 50 }; 51 waveIn.DataAvailable += WaveIn_DataAvailable; 52 waveIn.WaveFormat = new WaveFormat(sampleRate: 8000, channels: 1); 53 waveIn.StartRecording(); 54 } 55 56 private void finish_Click(object sender, EventArgs e) 57 { 58 // アプリケーションを終了する 59 Application.Exit(); 60 } 61 62 private void WaveIn_DataAvailable(object sender, WaveInEventArgs e) 63 { 64 // 32bitで最大値1.0fにする 65 for (int index = 0; index < e.BytesRecorded; index += 2) 66 { 67 short sample = (short)((e.Buffer[index + 1] << 8) | e.Buffer[index + 0]); 68 69 float sample32 = sample / 32768f; 70 ProcessSample(sample32); 71 ProcessSample2(sample32); 72 } 73 } 74# region "波形表示" 75 76 // グラフ1の設定 77 private PlotModel _plotmodel1 = new PlotModel(); 78 private LinearAxis _linearaxis1_1 = new LinearAxis 79 { 80 Position = AxisPosition.Bottom 81 }; 82 private LinearAxis _linearaxis1_2 = new LinearAxis 83 { 84 Minimum = -1.0, 85 Maximum = 1.0, 86 Position = AxisPosition.Left 87 }; 88 89 private LineSeries _lineSeries1 = new LineSeries(); 90 List<float> _recorded1 = new List<float>(); // 音声データ 91 92 // グラフ2の設定 93 private PlotModel _plotmodel2 = new PlotModel(); 94 private LinearAxis _linearaxis2_1 = new LinearAxis 95 { 96 Position = AxisPosition.Bottom 97 }; 98 private LinearAxis _linearaxis2_2 = new LinearAxis 99 { 100 Minimum = -1.0, 101 Maximum = 1.0, 102 Position = AxisPosition.Left 103 }; 104 105 private LineSeries _lineSeries2 = new LineSeries(); 106 List<float> _recorded2 = new List<float>(); // 音声データ 107 108 /// <summary> 109 /// グラフの表示 110 /// </summary> 111 private void InitPlot() 112 { 113 _plotmodel1.Axes.Add(_linearaxis1_1); 114 _plotmodel1.Axes.Add(_linearaxis1_2); 115 _plotmodel1.Series.Add(_lineSeries1); 116 this.plotView1.Model = _plotmodel1; 117 118 _plotmodel2.Axes.Add(_linearaxis2_1); 119 _plotmodel2.Axes.Add(_linearaxis2_2); 120 _plotmodel2.Series.Add(_lineSeries2); 121 this.plotView2.Model = _plotmodel2; 122 } 123 124 /// <summary> 125 /// 波形の表示 126 /// </summary> 127 /// <param name="sample"></param> 128 private void ProcessSample(float sample) 129 { 130 _recorded1.Add(sample); 131 132 if (_recorded1.Count == 1024) 133 { 134 var points = _recorded1.Select((v, index) => 135 new DataPoint((double)index, v) 136 ).ToList(); 137 _lineSeries1.Points.Clear(); 138 _lineSeries1.Points.AddRange(points); 139 140 this.plotView1.InvalidatePlot(true); 141 142 _recorded1.Clear(); 143 } 144 145 } 146 147 /// <summary> 148 /// 波形の表示2 149 /// </summary> 150 /// <param name="sample"></param> 151 private void ProcessSample2(float sample) 152 { 153 var windowsize = _recorded2.Count; 154 155 _recorded2.Add(sample); 156 157 if (_recorded2.Count == 1024) 158 { 159 160 var window = Window.Hamming(windowsize); 161 _recorded2 = _recorded2.Select((v, i) => v * (float)window[i]).ToList(); 162 163 Complex[] complexData = _recorded2.Select(v => new Complex(v, 0.0)).ToArray(); 164 165 Fourier.Forward(complexData, FourierOptions.Matlab); // 166 167 var s = windowsize * (1.0 / 8000.0); 168 169 var point = complexData.Take(complexData.Count() / 2).Select((v, index) => 170 new DataPoint((double)index / s, 171 Math.Sqrt(v.Real * v.Real + v.Imaginary * v.Imaginary))).ToList(); 172 173 _lineSeries2.Points.Clear(); 174 _lineSeries2.Points.AddRange(point); 175 this.plotView2.InvalidatePlot(true); 176 177 } 178 179 } 180 181 182 #endregion 183 184 185 } 186} 187 188
補足情報
参考にしたURL
http://wildpie.hatenablog.com/entry/2014/09/24/000900
https://teratail.com/questions/42564
回答1件
あなたの回答
tips
プレビュー