迭代数组并播放音符

时间:2013-12-09 11:35:54

标签: c# arrays winforms

我有一个由MusicNotes填充的数组。每个MusicNote都是一个具有它属性的对象,例如音高和持续时间。持续时间是使用MusicNote类中的计时器创建的。

问题在于,当我遍历数组并播放所有声音时,每个MusicNote的持续时间都会丢失,并且它将播放整个wav文件(对于每个音符)。

我知道问题与计时器有关,我知道它可能与MusicNote中的Play()方法有关,但我对如何修复它没有任何想法。我已经发布了与此问题相关的代码。

public class MusicNote : PictureBox
    {
        Timer tmr1 = new Timer();
        int tmr1duration;
        public SoundPlayer sp = new SoundPlayer();
        public Timer tmr = new Timer();
        public int pitch;        //The no. of the music key (e.g. the sound freuency).
        public int noteDuration; //Shape of note.
        public string noteShape;
        static int xLoc = 0;
        int yLoc = 100;

        public MusicNote(int iPitch, int iNoteDuration)
            : base()
        {
            pitch = iPitch;
            noteDuration = iNoteDuration;
            Size = new Size(40, 40);
            this.BackColor = Color.Transparent;
            this.MouseClick += new MouseEventHandler(MusicNote_MouseClick);
            this.MouseDown += new MouseEventHandler(MusicNote_MouseDown);
            this.MouseUp += new MouseEventHandler(MusicNote_MouseUp);
            tmr1.Tick += new EventHandler(tmr1_Tick);
            tmr.Tick += new EventHandler(ClockTick);
        }

        public void ShowNote()
        {
            if (this.noteDuration == 1) noteShape = "Quaver.png";
            if (this.noteDuration == 4) noteShape = "Crotchet.png";
            if (this.noteDuration == 7) noteShape = "minim.png";
            if (this.noteDuration == 10) noteShape = "DotMin.png";
            if (this.noteDuration == 12) noteShape = "SemiBreve.png";
            this.BackgroundImage = Image.FromFile(noteShape);
            this.BackColor = Color.Transparent;
            Location = new Point(xLoc, yLoc);
            xLoc = xLoc + 40;
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
        }

        public void Play()
        {
            sp.SoundLocation = this.pitch + ".wav";
            sp.Play();
            //Timer to play the duration
            this.tmr.Interval = 100 * this.noteDuration;
            this.tmr.Start();
        }

        void ClockTick(object sender, EventArgs e)
        {
            sp.Stop();
            tmr.Stop();
        }

        private void MusicNote_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Play();
            }
        }
    }
}

这是我有阵列的课程......

   public class MusicStaff: Panel
    {
        public ArrayList musicNotes = new ArrayList(); //Array to store the Music Notes.
        SoundPlayer sp = new SoundPlayer();

        public void AddNote(MusicNote newNote)         //Method to add the notes.
        {
            musicNotes.Add(newNote);
        }

        public int ListSize()
        {
            return musicNotes.Count;                   //Returns the size of the list.
        }

   public void PlayAll()
    {
        foreach (MusicNote m in musicNotes)
        {
            m.Play();
        }

我已从类中删除了一些未重新插入问题的代码,因此问题不会太长。任何帮助如何解决这个问题将不胜感激。 TKS。

1 个答案:

答案 0 :(得分:0)

尝试这样的事情:

public void PlayAll()
{
    foreach (MusicNote m in musicNotes)
    {
        m.sp.Stop();
        m.sp.PlaySync();
        Thread.Sleep(m.noteDuration); //duration should be in milliseconds
    }
}

如果这项工作正常,您可以完全移除计时器。

我建议你研究在C#中使用Properties来不让字段公开。 顺便说一下,两年前我做了这个任务:)