
public class MusicPattern {
	/* Pattern definition :
	 *  0 : low  time
	 *  1 : rise time
	 *  2 : high time
	 *  3 : fall time
	 *  4 : low time
	 */
	private int[] pattern; // in ms
	private int totalLength;
	private int[] patternTiming = new int[5]; // in ms
	private long begin; // in ms
	private long stop; // in ms
	private int repeat;

	public MusicPattern(int[] pattern, int repeat, long begin) {
		if(pattern.length != 5)
			throw new InvalidPatternException();
		this.pattern = pattern;
		this.totalLength = pattern[0] + pattern[1] + pattern[2] + pattern[3] + pattern[4];
		this.patternTiming[0] = pattern[0];
		for(int i=1; i<5; i++)
			this.patternTiming[i] = this.patternTiming[i-1] + pattern[i];
		this.begin = begin;
		this.stop = repeat * totalLength + begin;
		this.repeat = repeat;
	}

	public int[] getPattern() { return pattern; }
	public int[] getPatternTiming() { return patternTiming; }
	public long getStop() { return stop; }
	public long getBegin() { return begin; }
	public int getRepeat() { return repeat; }
	public int getTotalLength () { return totalLength; }
	
	public double render(long tick) { // tick in ms
		if(tick <= begin)
			return 0;
		if(tick >= stop)
			return 0;
		int tickMod = (int) (tick % totalLength);
		if(tickMod < patternTiming[0])
			return 0;
		if(tickMod < patternTiming[1])
			return (double) (tickMod - patternTiming[0]) / (double) (pattern[1]);
		if(tickMod < patternTiming[2])
			return 1;
		if(tickMod < patternTiming[3])
			return 1 - ((double) (tickMod - patternTiming[2]) / (double) (pattern[3]));
		return 0;
	}
}
