質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

1回答

6477閲覧

C#で音声を取得して波形を表示

kagiya

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2020/10/07 06:31

編集2020/10/07 07:02

前提・実現したいこと

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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2020/10/07 06:45

どこまで出来てるんでしょう。 波形のグラフ表示はできてますか?
kagiya

2020/10/07 06:49

質問ありがとうございます。 参考URLの一つ目の波形グラフ表示まではできています。
guest

回答1

0

ベストアンサー

注意)はっきり言って私は計算について何一つわかっていません^^;

windowsizeを取った後で_recorded2.Add(sample);としてしまっては、数が合わなくなるので当然IndexOutOfRangeExceptionが出るでしょう。

おそらくProcessSample2の部分は、ProcessSampleの中でやる処理だったんだと思います(何度も言いますが計算について何一つわかりません。参考ページのコード片から推測しただけです)
参考ページで全文を出してくれていればいいのですが^^;

こうしたところ何かしら表示されましたが、本当にこれでいいのかはわかりませんし質問されても答えられません^^;

cs

1using System; 2using System.Collections.Generic; 3using System.Data; 4using System.Linq; 5using System.Numerics; 6using System.Windows.Forms; 7using MathNet.Numerics; 8using MathNet.Numerics.IntegralTransforms; 9using NAudio.Wave; 10using OxyPlot; 11using OxyPlot.Axes; 12using OxyPlot.Series; 13 14namespace Questions296462 15{ 16 public partial class Form1 : Form 17 { 18 private readonly LineSeries _lineSeries1 = new LineSeries(); 19 private readonly LineSeries _lineSeries2 = new LineSeries(); 20 private readonly List<float> _recorded = new List<float>(); 21 private const int deviceNumber = 0; 22 23 public Form1() => InitializeComponent(); 24 25 private void Form1_Load(object sender, EventArgs e) 26 { 27 FormBorderStyle = FormBorderStyle.FixedSingle; 28 29 var info = WaveIn.GetCapabilities(deviceNumber); 30 micname.Text = $"Device {deviceNumber}: {info.ProductName}, {info.Channels} channels"; 31 32 InitPlot(); 33 } 34 35 private void InitPlot() 36 { 37 var model = new PlotModel(); 38 model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, }); 39 model.Axes.Add(new LinearAxis { Minimum = -1.0, Maximum = 1.0, Position = AxisPosition.Left, }); 40 model.Series.Add(_lineSeries1); 41 plotView1.Model = model; 42 43 model = new PlotModel(); 44 model.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, }); 45 model.Axes.Add(new LinearAxis { Minimum = 0, Maximum = 5.0, Position = AxisPosition.Left, }); 46 model.Series.Add(_lineSeries2); 47 plotView2.Model = model; 48 } 49 50 private void recording_Click(object sender, EventArgs e) 51 { 52 var waveIn = new WaveIn 53 { 54 DeviceNumber = deviceNumber, 55 WaveFormat = new WaveFormat(sampleRate: 8000, channels: 1), 56 }; 57 waveIn.DataAvailable += WaveIn_DataAvailable; 58 waveIn.StartRecording(); 59 } 60 61 private void finish_Click(object sender, EventArgs e) => Application.Exit(); 62 63 private void WaveIn_DataAvailable(object sender, WaveInEventArgs e) 64 { 65 for(var index = 0; index < e.BytesRecorded; index += 2) 66 { 67 var sample = (short)((e.Buffer[index + 1] << 8) | e.Buffer[index + 0]); 68 var sample32 = sample / 32768f; 69 ProcessSample(sample32); 70 } 71 } 72 73 private void ProcessSample(float sample) 74 { 75 _recorded.Add(sample); 76 77 if(_recorded.Count == 1024) 78 { 79 // plotView1 80 var points = _recorded.Select((v, i) => new DataPoint(i, v)); 81 _lineSeries1.Points.Clear(); 82 _lineSeries1.Points.AddRange(points); 83 plotView1.InvalidatePlot(true); 84 85 // plotView2 86 var windowsize = _recorded.Count; 87 var window = Window.Hamming(windowsize); 88 var complexData = _recorded.Select((v, i) => v * (float)window[i]) 89 .Select(v => new Complex(v, 0.0)).ToArray(); 90 Fourier.Forward(complexData, FourierOptions.Matlab); 91 92 var s = windowsize * (1.0 / 8000.0); 93 var point = complexData.Take(complexData.Count() / 2) 94 .Select((v, i) => new DataPoint(i / s, Math.Sqrt(v.Real * v.Real + v.Imaginary * v.Imaginary))) 95 .ToList(); 96 97 _lineSeries2.Points.Clear(); 98 _lineSeries2.Points.AddRange(point); 99 plotView2.InvalidatePlot(true); 100 101 // Hz 102 var max = point.Aggregate((r, n) => r.Y > n.Y ? r : n); 103 label1.Text = $"{point.IndexOf(max) / s:f0} Hz"; 104 105 _recorded.Clear(); 106 } 107 } 108 } 109}

アプリ画像

投稿2020/10/07 21:36

編集2023/07/23 07:46
TN8001

総合スコア9862

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

okuda____

2021/11/10 07:44

私もこのプログラムを実行したいと思いWindowsフォームアプリ実行したところエラーが出ました。 「CS5001 プログラムは、エントリ ポイントに適切な静的 'Main' メソッドを含んでいません」 「CS0103 現在のコンテキストに’InitializeComponent’という名前は存在しません」というエラーメッセージが出ます。InitializeComponentのほかにも'micname'、'plotView1','plotView2'、'label1'にも同様のエラーメッセージが出るのですがどのように改善したらいいでしょうか
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問