package jeranvier.io;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

public class SlidingWindowInputStream extends InputStream{
	
	private static final int INFLATION_FACTOR = 5; // if we have a window of 6, we collect the elements 30 by 30 form the underlying stream
	InputStream in; //underlying stream
	private int frameSize; // the size of the window
	private int frameShift; // the amount by which the window is shifted ( allow overlapping windows)
	private int indexStartFrame; //index at which the next window is starting
	private byte[] read; // buffer
	private int offset; // amount of element that are still in the read array before reading new elements
	private int inCounter; //how many elements have been last read from the underlying stream
	
	public SlidingWindowInputStream(InputStream in, int frameSize, int frameShift) {
		this.in = in;
		this.frameSize = frameSize;
		this.frameShift = frameShift;
		indexStartFrame = 0;
		inCounter = 0;
		read = new byte[0];
	}

	@Override
	public int read() throws IOException {
		return 0;
	}

	@Override
	public int read(byte[] b) throws IOException {
		//if not enough data, read next chunk
		if(indexStartFrame + frameSize > offset + inCounter){
			if(read.length != 0){
				read = Arrays.copyOfRange(read, indexStartFrame, indexStartFrame + read.length);
				offset = read.length - indexStartFrame;
			}
			else{
				read = new byte[frameSize*INFLATION_FACTOR];
				offset = 0;
			}
			
			inCounter = in.read(read, offset, read.length - offset);
			indexStartFrame = 0;
		}
		
		//if we cannot write anymore complete frames
		if(inCounter + offset >= indexStartFrame + frameSize && inCounter == -1){
			b = new byte[0];
			return -1;
		}
		
		//if enough data, write frame, otherwise, we will have exit the method in the lines above
		else if(inCounter + offset >= indexStartFrame + frameSize){
			for(int i = indexStartFrame; i < indexStartFrame + frameSize; i++){
				b[i-indexStartFrame] = read[i];
			}
			indexStartFrame += frameShift;
			return frameSize;
		}
		else{ //to make it complete, but should never be used
			b = new byte[0];
			return -1;
		}
	}


}

@@ -16,16 +16,37 @@
 er.io;%0A%0A
+import java.io.File;%0A
 import j
@@ -109,19 +109,218 @@
 ava.
-util.Arrays
+nio.ByteBuffer;%0Aimport java.nio.ByteOrder;%0Aimport java.util.Arrays;%0A%0Aimport javax.sound.sampled.AudioInputStream;%0Aimport javax.sound.sampled.AudioSystem;%0Aimport javax.sound.sampled.UnsupportedAudioFileException
 ;%0A%0Ap
@@ -2372,12 +2372,727 @@
 %0A%09%09%7D%0A%09%7D%0A
+%09%0A%09public static void main(String%5B%5D arg) throws UnsupportedAudioFileException, IOException%7B%0A%09%09int frameSize = 128;%0A%09%09int frameShift = 5;%0A%09%09AudioInputStream audio = AudioSystem.getAudioInputStream(new File(%22/Users/ranvier/Desktop/tone600.wav%22));%0A%09%09SlidingWindowInputStream swis = new SlidingWindowInputStream(audio, frameSize, frameShift);%0A%09%09byte%5B%5D read = new byte%5BframeSize%5D;%0A%09%09ByteBuffer bb = ByteBuffer.allocate(2);%0A//%09%09bb.order(audio.getFormat().isBigEndian()?ByteOrder.BIG_ENDIAN:ByteOrder.LITTLE_ENDIAN);%0A%09%09swis.read(read);%0A%09%09for(int i=0; i%3Cread.length/2; i++)%7B%0A%09%09%09bb.clear();%0A%09%09%09bb.put(read%5B2*i%5D);%0A%09%09%09bb.put(read%5B2*i+1%5D);%0A%09%09%09System.out.println(bb.getShort(0));%0A//%09%09%09System.out.println(read%5B2*i+1%5D);%0A%09%09%7D%0A%09%09%0A%09%7D%0A
 %0A%0A%7D%0A

add main method for testing purposes, might delete that at later time