2016-03-29 14 views
0

私はC#を使用してWindowsフォームアプリケーションを作成していますが、ユーザーの入力からデバイスのマイクへの周波数を取得し、一定の間隔で計算された周波数を取得したい、タイマー内のカウンタを増やす(System.Windows.Forms.Timer)C#

Iは、グローバル変数に最後に計算された周波数を割り当てることによって、これを達成するために期待していたとtimer.tickイベントがアレイ(userFrequencies)のインデックスに割り当てる値上昇させると、以下

コードであります:

private void getFreqTimer_Tick(object sender, EventArgs e) 
    { 
     if (cIndex < userFrequencies.Length) 
     { 
      userFrequencies[cIndex] = currentFreq; 
      cIndex++; // Also tried ++cIndex; 
     } 
    } 

T私が抱えている問題は、cIndexが時々1ずつ増えていくことがあり、時には2倍になるため、配列に適切に値を割り当てないのです。

私はタイマーが約15msずれていて、フォームのバックグラウンドで - これは要因になる可能性があります、コンパイル中にイベントを違うものにしますか?

ご協力いただければ幸いです!

EDIT:要求されたとして、追加コード:

using NAudio.Dsp; 
using NAudio.Wave; 
using System; 
using System.Data.SqlClient; 
using System.Diagnostics; 
using System.Drawing; 
using System.Drawing.Imaging; 
using System.Runtime.InteropServices; 
using System.Threading; 
using System.Windows.Forms; 
using System.Windows.Forms.DataVisualization.Charting; 

namespace VocalWarmUpFYP 
{ 
    public partial class Form1 : Form 
    { 
     private WaveIn waveIn; 
     public WaveFileWriter waveFile = null; 

    string timeHour = (DateTime.Now.Hour).ToString(); 
    string timeSecond = (DateTime.Now.Second).ToString(); 
    string timeMinute = (DateTime.Now.Minute).ToString(); 
    string timeDay = (DateTime.Now.Day).ToString(); 
    string chartImagePath; 
    int callStopBtnClick; 
    int timeForExercise; 
    int timerSecs; 

    private static int fftLength = 2048; 
    private static int sampleRate = 44100; 
    private SampleAggregator sampleAggregator = new SampleAggregator(fftLength); 

    bool CompFFT = false; 
    int userId = HelpData.UserID; 

    double[] userFrequencies = new double[20]; 
    double[] desiredFrequencies; 
    double currentFreq = 0; 
    public int cIndex = 0; 

    public Form1() 
    { 

     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     StartBtn.BackColor = HelpData.formBackColour; 
     StopBtn.BackColor = HelpData.formBackColour; 
     BackBtn.BackColor = HelpData.formBackColour; 
     BackColor = HelpData.formBackColour; 
     timer1.Tick += timer1_Tick; 
     getFreqTimer.Tick += getFreqTimer_Tick; 
     raiseStopTimer.Tick += raiseStopTimer_Tick; 
     chart1.Series.Clear(); 
     chart1.BackColor = HelpData.formBackColour; 

     switch (HelpData.selectedWarmUp) 
     { 
      case 1: 
       warmupImg.Image = Image.FromFile(Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\Visual Studio 2015\Projects\VocalWarmUpFYP\Images\BumbleBee.png"); 
       getFreqTimer.Interval = 750; 
       timeForExercise = 13; 
       break; 
      case 2: 
       warmupImg.Image = Image.FromFile(Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\Visual Studio 2015\Projects\VocalWarmUpFYP\Images\Lips.png"); 
       getFreqTimer.Interval = 450; 
       timeForExercise = 7; 
       break; 
      case 3: 
       warmupImg.Image = Image.FromFile(Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\Visual Studio 2015\Projects\VocalWarmUpFYP\Images\Siren.png"); 
       getFreqTimer.Interval = 700; 
       timeForExercise = 12; 
       break; 
      case 4: 
       warmupImg.Image = Image.FromFile(Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\Visual Studio 2015\Projects\VocalWarmUpFYP\Images\Mum.png"); 
       getFreqTimer.Interval = 800; 
       timeForExercise = 14; 
       break; 
      case 5: 
       warmupImg.Image = Image.FromFile(Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\Visual Studio 2015\Projects\VocalWarmUpFYP\Images\HummingBird.png"); 
       getFreqTimer.Interval = 450; 
       timeForExercise = 7; 
       break; 
     } 


     if (chart1.Series.Count == 0) // Check to make sure Series 0 exists 
     { 
      var series = chart1.Series.Add("Frequency"); // If it doesn't exist then create it. 
      series.ChartType = SeriesChartType.FastLine; 
      series.ChartArea = "ChartArea1"; 
      series.IsVisibleInLegend = false; 
      series.LabelBackColor = HelpData.formBackColour; 
      series.Color = Color.White; 
      series.BorderWidth = 5; 
     } 

     chart1.ChartAreas["ChartArea1"].BackColor = HelpData.formBackColour; 
     chart1.ChartAreas["ChartArea1"].AxisX.MinorGrid.Enabled = false; 
     chart1.ChartAreas["ChartArea1"].AxisX.MajorGrid.Enabled = false; 
     chart1.ChartAreas["ChartArea1"].AxisY.MajorGrid.Enabled = false; 
     chart1.ChartAreas["ChartArea1"].AxisX.MajorTickMark.Enabled = false; 
     chart1.ChartAreas["ChartArea1"].AxisX.MinorTickMark.Enabled = false; 
     chart1.ChartAreas["ChartArea1"].AxisX.Interval = 0; 
     chart1.ChartAreas["ChartArea1"].AxisY.LabelStyle.Enabled = false; 
     chart1.ChartAreas["ChartArea1"].AxisY.MajorTickMark.Enabled = false; 
     chart1.ChartAreas["ChartArea1"].AxisY.MinorTickMark.Enabled = false; 
     chart1.ChartAreas["ChartArea1"].AxisX.LineWidth = 0; 
     chart1.ChartAreas["ChartArea1"].AxisY.LineWidth = 0; 

     chart1.Visible = false; 
    } 

    private void StopBtn_Click(object sender, EventArgs e) 
    { 
     timer1.Stop(); 
     getFreqTimer.Stop(); 
     raiseStopTimer.Stop(); 
     string currentTimeStamp = timeDay + timeHour + timeMinute + timeSecond; 
     waveIn.StopRecording(); 
     waveFile.Dispose(); 
     waveIn.Dispose(); 

     StartBtn.Visible = true; 
     StopBtn.Visible = false; 

     chart1.SaveImage(@"C:\Temp\TestChart" + currentTimeStamp, ChartImageFormat.Png); 
     chartImagePath = @"C:\Temp\TestChart" + currentTimeStamp + ".Png"; 

     NameRecording NameRecording = new NameRecording(); 
     NameRecording.Tag = this; 
     NameRecording.Show(this); 

     for (int i = 0; i < userFrequencies.Length; i++) 
     { 
      Debug.WriteLine("User frequency at index " + i + ": " + userFrequencies[i]); 
     } 

    /*  
     var con = new SqlConnection("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=C:\\USERS\\OWNER\\DOCUMENTS\\VISUAL STUDIO 2015\\PROJECTS\\VOCALWARMUPFYP\\VOCALWARMUPFYP\\NEWDATABASE.MDF;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"); 

     using (con) 
     { 

      string oString = "SELECT COUNT (*) FROM VocalDetails"; 
      string oString2 = "INSERT INTO VocalDetails (VocalID, FreqImg, Name, Accuracy, Id, TimeStamp, RecordingRef) VALUES (@vocalid, @freqimg, @name, @accuracy, @userid, @timestamp, @filereference)"; 
      con.Open(); 

      SqlCommand oCmd = new SqlCommand(oString, con); 

      int newVocalID = (Convert.ToInt32(oCmd.ExecuteScalar()) + 1); 
      string recordingName = HelpData.userRecordingName; 
      string timeStamp = DateTime.Now.ToShortDateString(); 
      string freqImg = chartImagePath; 
      SqlCommand oCmd2 = new SqlCommand(oString2, con); 

      oCmd2.Parameters.AddWithValue("@vocalid", newVocalID); 
      oCmd2.Parameters.AddWithValue("@freqimg", freqImg); 
      oCmd2.Parameters.AddWithValue("@name", recordingName); 
      oCmd2.Parameters.AddWithValue("@accuracy", Accuracy); 
      oCmd2.Parameters.AddWithValue("@userid", userId); 
      oCmd2.Parameters.AddWithValue("@timestamp", timeStamp); 
      oCmd2.Parameters.AddWithValue("@filereference", fileReference); 

     } 
     con.Close(); 
     con.Dispose(); 
*/ 
     } 


    private void StartBtn_Click(object sender, EventArgs e) 
    { 
     StartBtn.Visible = false; 
     StopBtn.Visible = true; 
     warmupImg.Visible = false; 
     chart1.Visible = true; 
     string currentTimeStamp = timeDay + timeHour + timeMinute + timeSecond; 
     string fileToProcess = @"C:\Temp\Test" + currentTimeStamp + ".wav"; 

     sampleAggregator.PerformFFT = true; 
     sampleAggregator.FftCalculated += new EventHandler<FftEventArgs>(FftCalculated); 
     BufferedWaveProvider wavprov = new BufferedWaveProvider(new WaveFormat(sampleRate, 2)); 

     waveIn = new WaveIn(); 
     waveIn.WaveFormat = new WaveFormat(44100, WaveIn.GetCapabilities(0).Channels); 
     waveIn.DeviceNumber = 0; 
     waveFile = new WaveFileWriter(fileToProcess, waveIn.WaveFormat); 
     timerSecs = DateTime.Now.AddSeconds(timeForExercise).Second; 

     waveIn.DataAvailable += OnDataAvailable; 
     waveIn.StartRecording(); 

     timer1.Start(); 
     getFreqTimer.Start(); 
     raiseStopTimer.Start(); 
    } 

    void OnDataAvailable(object sender, WaveInEventArgs e) 
    { 
     if (InvokeRequired) 
     { 
      BeginInvoke(new EventHandler<WaveInEventArgs>(OnDataAvailable), sender, e); 
     } 
     else 
     { 
      byte[] buffer = e.Buffer; 
      int bytesRecorded = e.BytesRecorded; 
      int bufferIncrement = waveIn.WaveFormat.BlockAlign; 

      for (int index = 0; index < bytesRecorded; index += bufferIncrement) 
      { 
       float sample32 = BitConverter.ToInt16(buffer, index); 
       sampleAggregator.Add(sample32); 
      } 

      if (waveFile != null) 
      { 
       waveFile.Write(e.Buffer, 0, e.BytesRecorded); 
       waveFile.Flush(); 
      } 
     } 
    } 

    class SampleAggregator 
    { 
     // FFT 
     public event EventHandler<FftEventArgs> FftCalculated; 
     public bool PerformFFT { get; set; } 

     private Complex[] fftBuffer; 
     private FftEventArgs fftArgs; 
     private int fftPos; 
     private int fftLength; 
     private int m; 

     public SampleAggregator(int fftLength) 
     { 
      if (!IsPowerOfTwo(fftLength)) 
      { 
       throw new ArgumentException("FFT Length must be a power of two"); 
      } 
      m = (int)Math.Log(fftLength, 2.0); 
      this.fftLength = fftLength; 
      fftBuffer = new Complex[fftLength]; 
      fftArgs = new FftEventArgs(fftBuffer); 
     } 

     bool IsPowerOfTwo(int x) 
     { 
      return (x & (x - 1)) == 0; 
     } 

     public void Add(float value) 
     { 
      if (PerformFFT && FftCalculated != null) 
      { 
       fftBuffer[fftPos].X = (float)(value * FastFourierTransform.HannWindow(fftPos, fftLength)); 
       fftBuffer[fftPos].Y = 0; // This is always zero with audio. 
       fftPos++; 
       if (fftPos >= fftLength) 
       { 
        fftPos = 0; 
        FastFourierTransform.FFT(true, m, fftBuffer); 
        FftCalculated(this, fftArgs); 
       } 
      } 
     } 
    } 

    public class FftEventArgs : EventArgs 
    { 
     [DebuggerStepThrough] 
     public FftEventArgs(Complex[] result) 
     { 
      this.Result = result; 
     } 
     public Complex[] Result { get; private set; } 
    } 

    private void FftCalculated(object sender, FftEventArgs e) 
    { 
     double[] Magnitude = new double[(e.Result.Length/2) - 1]; 
     double Freq; 
     double Power; 
     int Index = 0; 

     if (CompFFT == true) 
     { 
      for (int i = 1; i < (e.Result.Length/2) - 1; i++) 
      { 
       if (chart1.Series.Count <= fftLength) //<<======Now it wont give exception** 
       { 
        if (InvokeRequired == false) //<<====== Invoke method used to allow access to the chart control from custom event** 
        { 

         this.Invoke(new MethodInvoker(delegate 
         { 

          var series = 0; 
          double Max_Magnitude = 0; 
          double Max_Index = -1; 

          for (int j = 0; j < (e.Result.Length/2) - 1; j++) 
          { 

           e.Result[j].Y = 0; 
           Power = (e.Result[j].X * e.Result[j].X) + (e.Result[j].Y * e.Result[j].Y); 
           Magnitude[j] = Math.Sqrt(Power); 
          } 

          for (int j = 0; j < Magnitude.Length; j++) 
          { 

           if (Magnitude[j] > Max_Magnitude && j != 0 && Magnitude[j] > 1) 
           { 
            Index = j; 
            Max_Magnitude = Magnitude[Index]; 
            Max_Index = Index; 
           } 
          } 

          Freq = ((Max_Index * sampleRate)/fftLength); 

          if (Freq > 0) 
          { 
           currentFreq = Freq; 
          } 

          chart1.DataSource = Freq; 
          chart1.Series[series].Points.Add(Freq); 

          CompFFT = false; 
         })); 
         return; 
        } 
       } 

       chart1.Update(); 
      } 
     } 
    } 

    private void timer1_Tick(object sender, EventArgs e) 
    { 
     CompFFT = true; 
    } 

    private void BackBtn_Click(object sender, EventArgs e) 
    { 
     SelectWarmUp SelectWarmUp = new SelectWarmUp(); 
     SelectWarmUp.Tag = this; 
     SelectWarmUp.Show(this); 
     Hide(); 
    } 

    private void getFreqTimer_Tick(object sender, EventArgs e) 
    { 
     if (cIndex < userFrequencies.Length) 
     { 
      userFrequencies[cIndex] = currentFreq; 
      cIndex++; 
     } 
     Debug.WriteLine("cIndex: " + cIndex); 
    } 

    private void raiseStopTimer_Tick(object sender, EventArgs e) 
    { 
     callStopBtnClick = DateTime.Now.Second; 

     if (callStopBtnClick == timerSecs + 2) 
     { 
      StopBtn.PerformClick(); 
     } 
    } 
} 
} 

Timer1の間隔:25msの getFreqTimer間隔:750ms

StopBtn_Clickイベントが自動的に呼び出される前に、アプリケーションが15秒間に実行されます - これは最大20個の値を与えるはずです

@Eminemからの出力:

cIndex: 1 
x: 1 
cIndex: 2 
x: 2 
cIndex: 3 
x: 3 
cIndex: 4 
x: 4 
cIndex: 5 
x: 5 
cIndex: 6 
x: 6 
cIndex: 7 
x: 7 
cIndex: 8 
x: 8 
cIndex: 9 
x: 9 
cIndex: 10 
x: 10 
cIndex: 11 
x: 11 
cIndex: 12 
x: 12 
cIndex: 13 
x: 13 
cIndex: 14 
x: 14 
cIndex: 15 
x: 15 
cIndex: 16 
x: 16 
cIndex: 17 
x: 17 
cIndex: 18 
x: 18 
cIndex: 19 
x: 19 
cIndex: 20 
x: 20 
cIndex: 20 
x: 21 
cIndex: 20 
x: 22 
cIndex: 20 
x: 23 
cIndex: 20 
x: 24 
cIndex: 20 
x: 25 
cIndex: 20 
x: 26 
cIndex: 20 
x: 27 
cIndex: 20 
x: 28 
cIndex: 20 
x: 29 
cIndex: 20 
x: 30 
cIndex: 20 
x: 31 
cIndex: 20 
x: 32 
cIndex: 20 
x: 33 
cIndex: 20 
x: 34 
cIndex: 20 
x: 35 
cIndex: 20 
x: 36 
cIndex: 20 
x: 37 
cIndex: 20 
x: 38 

User frequency at index 0: 172.265625 
User frequency at index 1: 172.265625 
User frequency at index 2: 279.931640625 
User frequency at index 3: 279.931640625 
User frequency at index 4: 193.798828125 
User frequency at index 5: 193.798828125 
User frequency at index 6: 279.931640625 
User frequency at index 7: 279.931640625 
User frequency at index 8: 387.59765625 
User frequency at index 9: 387.59765625 
User frequency at index 10: 236.865234375 
User frequency at index 11: 236.865234375 
User frequency at index 12: 1098.193359375 
User frequency at index 13: 1098.193359375 
User frequency at index 14: 559.86328125 
User frequency at index 15: 559.86328125 
User frequency at index 16: 258.3984375 
User frequency at index 17: 258.3984375 
User frequency at index 18: 279.931640625 
User frequency at index 19: 279.931640625 
+0

使用している間隔は何ですか? –

+0

@GlenThomasこれはフォームにアクセスするために使用されたボタン(5つのオプションがあります)に依存しますが、私がテストしたものは750 – JBrian30221

+0

なので、特定のインデックスでnull/ –

答えて

1

同様のアプリをタイプしました。問題は次の2行です:

getFreqTimer.Tick += getFreqTimer_Tick; 
raiseStopTimer.Tick += raiseStopTimer_Tick; 

イベントが2回発生しています。したがって、これらの2行を削除し、プロパティインスペクタで追加したものだけを残しておきます(.Designer.csファイルでのみチェックしてください)

+0

リストに値を代入してみましたが、期待値の代わりに36の値が得られます。 – JBrian30221

+0

私は同意します。 getFreqTimer_Tick関数は、インターバルが750msに設定され、15秒間実行するように設定されている場合にのみ、20回呼び出される必要があります。 getFreqTimer_Tick関数が入力された回数を数える別のcount変数を追加してください。調整済みの回答を参照 – Eminem

+0

提案通りにコードを変更し、出力で質問を更新しました – JBrian30221

関連する問題