增加计时器内的计数器(System.Windows.Forms.Timer)C#

时间:2016-03-29 10:45:20

标签: c# winforms timer operators increment

我正在使用C#编写一个Windows窗体应用程序,它将用户输入的频率输入到设备的麦克风中,我想获得以一定间隔计算的频率,

我希望通过将最后计算的频率分配给全局变量来实现这一点,并且当提出timer.tick事件时,将值赋给数组的索引(userFrequencies),

以下是代码:

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

我遇到的问题是cIndex有时增加1,有时增加2,因此没有正确地为数组赋值,

我知道计时器可以关闭大约15毫秒并且表格背景中有很多事情发生 - 这可能是一个因素,在编译过程中事件会不同吗?

非常感谢任何帮助!

编辑:要求的附加代码:

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的间隔:750毫秒

应用程序在自动调用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 

1 个答案:

答案 0 :(得分:1)

我输入了一个类似的应用。问题是以下两行:

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

事件被提升两次。因此删除这两行,只保留通过属性检查器添加的行(仅在.Designer.cs文件中检查它)