在数组中循环并播放音符



我有一个由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。

试试这样的东西:

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的使用,不要让字段公开。顺便说一句,我两年前完成了这项任务:)

最新更新