nAudio の WaveIn 関数から波形をグラフ化することを検討しています。私がやろうとしていることを正確に達成する例をオンラインで見つけましたが、外部のグラフ作成ライブラリ (Scottplot) を使用し、C# でプログラムされています (VB が必要です)。私は正常に標準チャートにグラフを表示し、基本的にすべてのコードを翻訳しました。コンパイルはできますが、私のストリームは空です。私はこれを何週間も解決しようとしましたが、うまくいきませんでした。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NAudio.Wave; // installed with nuget
using NAudio.CoreAudioApi;
using System.Numerics;
namespace microphone
{
public partial class Form1 : Form
{
public WaveIn wi;
public BufferedWaveProvider bwp;
//public Int32 envelopeMax;
private int RATE = 44100; // sample rate of the sound card
private int BUFFERSIZE = (int) Math.Pow(2,13); // must be a multiple of 2
//private int BUFFERSIZE = 2048; // must be a multiple of 2
public Form1()
{
InitializeComponent();
// see what audio devices are available
int devcount = WaveIn.DeviceCount;
Console.Out.WriteLine("Device Count: {0}.", devcount);
// get the WaveIn class started
WaveIn wi = new WaveIn();
wi.DeviceNumber = 0;
wi.WaveFormat = new NAudio.Wave.WaveFormat(RATE, 1);
// create a wave buffer and start the recording
wi.DataAvailable += new EventHandler<WaveInEventArgs>(wi_DataAvailable);
bwp = new BufferedWaveProvider(wi.WaveFormat);
bwp.BufferLength = BUFFERSIZE * 2;
bwp.DiscardOnBufferOverflow = true;
wi.StartRecording();
}
// adds data to the audio recording buffer
void wi_DataAvailable(object sender, WaveInEventArgs e)
{
bwp.AddSamples(e.Buffer, 0, e.BytesRecorded);
}
public void timer1_Tick(object sender, EventArgs e)
{
// read the bytes from the stream
int frameSize = BUFFERSIZE;
var frames = new byte[frameSize];
bwp.Read(frames, 0, frameSize);
if (frames.Length == 0) return;
if (frames[frameSize - 2] == 0)
{
label1.Text = "removed";
return;
}
else {
label1.Text = "graphing";
}
// convert it to int32 manually (and a double for scottplot)
int SAMPLE_RESOLUTION = 16;
int BYTES_PER_POINT = SAMPLE_RESOLUTION / 8;
Int32[] vals = new Int32[frames.Length/BYTES_PER_POINT];
double[] Ys = new double[frames.Length / BYTES_PER_POINT];
double[] Xs = new double[frames.Length / BYTES_PER_POINT];
// double[] Ys2 = new double[frames.Length / BYTES_PER_POINT];
// double[] Xs2 = new double[frames.Length / BYTES_PER_POINT];
for (int i=0; i<vals.Length; i++)
{
// bit shift the byte buffer into the right variable format
byte hByte = frames[i * 2 + 1];
byte lByte = frames[i * 2 + 0];
vals[i] = (int)(short)((hByte << 8) | lByte);
Xs[i] = i;
Ys[i] = vals[i];
// Xs2[i] = (double)i/Ys.Length*RATE/1000.0; // units are in kHz
}
chart1.ChartAreas[0].AxisX.Maximum = 400;
chart1.ChartAreas[0].AxisX.Minimum= 0;
chart1.Series[0].Points.DataBindXY(Xs, Ys);
//update scottplot (FFT, frequency domain)
/* Ys2 = FFT(Ys);
chart2.ChartAreas[0].AxisX.Maximum = 10;
chart2.ChartAreas[0].AxisX.Minimum = 0; chart2.Series[0].Points.DataBindXY(Xs2.Take(Xs2.Length / 2).ToArray(), Ys2.Take(Ys2.Length / 2).ToArray());
// update the displays
Application.DoEvents();
*/
}
//public double[] FFT(double[] data)
//{
// double[] fft = new double[data.Length]; // this is where we will store the output (fft)
// Complex[] fftComplex = new Complex[data.Length]; // the FFT function requires complex format
// for (int i = 0; i < data.Length; i++)
// {
// fftComplex[i] = new Complex(data[i], 0.0); // make it complex format (imaginary = 0)
// }
// Accord.Math.FourierTransform.FFT(fftComplex, Accord.Math.FourierTransform.Direction.Forward);
// for (int i = 0; i < data.Length; i++)
// {
// fft[i] = fftComplex[i].Magnitude; // back to double
// //fft[i] = Math.Log10(fft[i]); // convert to dB
// }
// return fft;
// //todo: this could be much faster by reusing variables
//}
public void chart1_Click(object sender, EventArgs e) { }
}
}
これは私が修正した元のコードであり、余分なビット (コメント アウト) なしで正常に動作するようになりました。
Imports NAudio
Imports NAudio.CoreAudioApi
Public Class Form1
Public WithEvents wi As New NAudio.Wave.WaveIn() 'Wave 'in Stream Generates 'by Naudio
Public WaveFormat As New NAudio.Wave.WaveFormat(44100, 1) 'Wave In format
'AddHandler wi.DataAvailable, AddressOf StreamWavein_DataAvailable
Public bwp As New NAudio.Wave.BufferedWaveProvider(wi.WaveFormat)
'Public wi As NAudio.Wave.WaveIn()
'Public bwp
Public Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Dim wi As New NAudio.Wave.WaveIn()
'wi.DeviceNumber = 0
'Dim waveforamt As New NAudio.Wave.WaveFormat(44100, 1)
''wi.DataAvailable += New EventHandler < WaveInEventArgs > (wi_DataAvailable)\
'AddHandler wi.DataAvailable, AddressOf StreamWavein_DataAvailable
'Dim bwp As New NAudio.Wave.BufferedWaveProvider(wi.WaveFormat)
bwp.BufferLength = ((Math.Pow(2, 13)) * 2)
bwp.DiscardOnBufferOverflow = True
wi.StartRecording()
Chart1.ChartAreas(0).AxisX.Maximum = 400
Chart1.ChartAreas(0).AxisX.Minimum = 0
End Sub
Public Sub StreamWavein_DataAvailable(ByVal sender As Object, ByVal e As NAudio.Wave.WaveInEventArgs) Handles wi.DataAvailable
bwp.AddSamples(e.Buffer, 0, e.BytesRecorded)
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim frameSize As Integer
frameSize = Math.Pow(2, 13)
Dim frames(frameSize) As Byte
bwp.Read(frames, 0, frameSize)
If frames.Length = 0 Then
Return
End If
If frames(frameSize - 2) = 0 Then
Label1.Text = "removed"
Return
Else
Label1.Text = "graphing"
End If
Dim SAMPLE_RESOLUTION As Integer
SAMPLE_RESOLUTION = 16
Dim BYTES_PER_POINT As Integer
BYTES_PER_POINT = SAMPLE_RESOLUTION / 8
Dim vals(frames.Length / BYTES_PER_POINT) As Int32
Dim Ys(frames.Length / BYTES_PER_POINT) As Double
Dim Xs(frames.Length / BYTES_PER_POINT) As Double
Dim i As Integer
For i = 0 To vals.Length Step 1
Dim hbyte As Byte
Dim lbyte As Byte
hbyte = frames(i * 2 + 1)
lbyte = frames(i * 2 + 0)
vals(i) = CInt(CShort((hbyte << 8) Or lbyte))
Xs(i) = i
Ys(i) = vals(i)
Next
Chart1.Series("Series1").Points.DataBindXY(Xs, Ys)
End Sub
End Class
どこが間違っていたのかわかりませんが、どんな助けでも大歓迎です。