2012-12-14 25 views
1

我創建了一個節拍器程序,並且for循環正在執行比它應該的+1倍。java - for循環執行的次數比它應該多 - 節拍器程序

public class Tempo { 

String file; 
int bpm; 

public Tempo(int bpm, String file){ 
    this.bpm=bpm; 
    this.file=file; 
} 

public void tempoPlay() throws InterruptedException{ 
    new Play(file).start(); 
    Thread.sleep(60000/bpm); 

} 

public static void main(String[] args) throws InterruptedException { 
    Tempo t = new Tempo(120, "C:\\Users\\Korisnik\\Desktop\\dome3.wav"); 

    for(int i=0;i<20;i++){ 
     t.tempoPlay(); 
    } 
} 
} 

第一個節拍後面緊接着第二個節拍,但後來它變得聽起來很合規。我數了21個節拍,但它應該發揮20 這裏的遊戲類:

import java.io.File; 
import java.io.IOException; 
import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.DataLine; 
import javax.sound.sampled.FloatControl; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.SourceDataLine; 
import javax.sound.sampled.UnsupportedAudioFileException; 

class Play extends Thread { 

private String filename; 
private Position curPosition; 
private final int EXTERNAL_BUFFER_SIZE = 524288; // 128Kb 

enum Position { 

    LEFT, RIGHT, NORMAL 
}; 

public Play(String wavfile) { 
    filename = wavfile; 
    curPosition = Position.NORMAL; 
} 

public Play(String wavfile, Position p) { 
    filename = wavfile; 
    curPosition = p; 
} 

@Override 
public void run() { 

    File soundFile = new File(filename); 
    if (!soundFile.exists()) { 
     System.err.println("Wave file not found: " + filename); 
     return; 
    } 

    AudioInputStream audioInputStream = null; 
    try { 
     audioInputStream = AudioSystem.getAudioInputStream(soundFile); 
    } catch (UnsupportedAudioFileException e1) { 
     e1.printStackTrace(); 
     return; 
    } catch (IOException e1) { 
     e1.printStackTrace(); 
     return; 
    } 

    AudioFormat format = audioInputStream.getFormat(); 
    SourceDataLine auline = null; 
    DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); 

    try { 
     auline = (SourceDataLine) AudioSystem.getLine(info); 
     auline.open(format); 
    } catch (LineUnavailableException e) { 
     e.printStackTrace(); 
     return; 
    } catch (Exception e) { 
     e.printStackTrace(); 
     return; 
    } 

    if (auline.isControlSupported(FloatControl.Type.PAN)) { 
     FloatControl pan = (FloatControl) auline 
       .getControl(FloatControl.Type.PAN); 
     if (curPosition == Position.RIGHT) { 
      pan.setValue(1.0f); 
     } else if (curPosition == Position.LEFT) { 
      pan.setValue(-1.0f); 
     } 
    } 

    auline.start(); 
    int nBytesRead = 0; 
    byte[] abData = new byte[EXTERNAL_BUFFER_SIZE]; 

    try { 
     while (nBytesRead != -1) { 
      nBytesRead = audioInputStream.read(abData, 0, abData.length); 
      if (nBytesRead >= 0) { 
       auline.write(abData, 0, nBytesRead); 
      } 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return; 
    } finally { 
     auline.drain(); 
     auline.close(); 
    } 

} 

} 
+1

1)我建議爲此使用'Clip'。它具有方便的方法,如['loop(int)'](http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/Clip.html#loop%28int%29) 2)如果一個方法需要一個'File',在簽名中指定一個'File'並且用它來完成,傳遞圍繞代表文件路徑的字符串導致混淆不清。 3)但是,除非你從用戶那裏獲得聲音(不太可能),否則該剪輯需要在運行時由'URL'引用。 –

+1

我運行了你的程序,在run(init/end)中添加了幾個'System.out.prints',並且在對輸出進行排序並計算了行號之後,我得到了20個對'run()'的調用,除此之外,使用不同的wav文件(具有不同的睡眠時間,可以使播放足夠快)我可以清楚地聽到正在播放的文件20次。你完全確定有21場比賽嗎? – higuaro

回答

1

瞎猜:這可能是值得完全讀取文件到內存中用於測試目的。猜測可能發生的情況是讀取文件時的I/O會干擾播放的時間。

你或許可以逃避這個測試。

Tempo t = new Tempo(120, "C:\\Users\\Korisnik\\Desktop\\dome3.wav"); 

t.tempoPlay() // ignore this 
Thread.sleep(10); 

for(int i=0;i<20;i++){ 
    t.tempoPlay(); 
} 

或者更好的,有節奏緩存播放聲音之前讀入。

+0

這是工作得很好,爲現在工作就像它應該,但前兩個節拍是關閉的。按照你所建議的方式,它大多使它們發出聲音,但在1/8的情況下它們不是。這可能是因爲netbeans?程序運行時是否需要一些時間來「適應」? –

+0

它可能與您的機器有關 - 內存或磁盤I/O。您也可以嘗試編譯器選項-XX:CompileThreshold = 1 – dfb