2013-12-09 4 views
0

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. 이 같은

답변

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#에서 속성을 사용하는 것이 좋습니다. 그런데 2 년 전에이 과제를 수행했습니다 :)

+0

답장을 보내 주셔서 감사합니다.하지만 불행히도 작동하지 않습니다. noteDuration에 값을 할당 할 수 있도록 MusicNote의 타이머가 필요합니다 .... MusicStaff에 다른 타이머를 배치해야합니까? MusicNote에서 이미이 문제를 피하고 싶습니다. – user2307236

+0

UI 스레드에서 'Sleep'을 사용하지 않는 것이 좋습니다. 그것은 당신의 신청을 막을 것입니다. – etaiso

+0

그 때 당신은 무엇을 추천합니까? – user2307236

관련 문제