






import javax.sound.sampled.*;
import java.util.*;
public class HNW {
	//The following are general instance variables
	// used to create a SourceDataLine object.
	AudioFormat audioFormat;
	AudioInputStream audioInputStream;
	SourceDataLine sourceDataLine;
	//The following are audio format parameters.
	float sampleRate = 16000.0F;
	//Allowable 8000,11025,16000,22050,44100
	int sampleSizeInBits = 16;
	//Allowable 8,16
	int channels = 1;
	// MONO!
	//Allowable 1,2
	boolean signed = true;
	//Allowable true,false
	boolean bigEndian = true;
	//Allowable true,false
	//
	// size of number of samples to smooth
	// lager = more coarse sounds
	static int harshness = 60;
	static int noiselen = 0;  // length of piece
	//-------------------------------------------//
	public static void main(String args[]){
		if (args.length > 0) {
			harshness = Integer.parseInt(args[0]);
		}// end of if 
		if (args.length > 1) {
			noiselen = Integer.parseInt(args[1]);
		}// end of if 

		new HNW();
	}//end main
	//-------------------------------------------//
	public HNW(){//constructor
		playData();
	}//end constructor

	private void playData() {
		try{
			//Get the required audio format
			audioFormat = new AudioFormat(
					sampleRate,
					sampleSizeInBits,
					channels,
					signed,
					bigEndian);
			//Get info on the required data line
			DataLine.Info dataLineInfo =
				new DataLine.Info(
						SourceDataLine.class,
						audioFormat);
			//Get a SourceDataLine object
			sourceDataLine = (SourceDataLine)AudioSystem.getLine(dataLineInfo);
			new ListenThread().start();
		}catch (Exception e) {
			e.printStackTrace();
			System.exit(0);
		}//end catch
	}//end playData
	//=============================================//
	class ListenThread extends Thread{
		byte playBuffer[] = new byte[200];
		// the size of this buffer = length of sound

		public void run(){
			// need to generate random numbers
			Random generator = new Random();
			// harshness the higher this value the more rough / harsh
			double ss[] = new double[harshness];
			double sa;
			short s; // signed two byte integer  for PCM data

			try{
				sourceDataLine.open(audioFormat);
				sourceDataLine.start();



				for(int z = -1; z < noiselen; z++){ // make this big for long pieces or
					// if noiselen was 0 from commandline run forever!
					// note only play half buffer to stop gaps???
					if (noiselen < 1) z = -2;
					//----------------------- loop ------------------------

					for(int cnt = 0; cnt < 100; cnt = cnt + 2 ){
						// for testing so i can see the data	 
						//  for(int cnt = 0; cnt < 100; cnt = cnt + 2 ){
						int r = generator.nextInt();


						s = (short) r;
						// store new sample - roll out others	   
						for(int x = 0; x < harshness-1; x++){
							ss[x] = ss[x+1];
						} // end of x for
						ss[harshness-1] = (short)s;
						// average  the last harshness number of samples
						// remove the higher pitches
						sa = 0;
						for(int x = 0; x < harshness; x++){
							sa = sa + ss[x];
						}
						sa = sa / harshness;
						s = (short) sa;
						//============ Process  for new sounds ========		   

						//	   loudness====  !!!!
						// basically no wimpy numbers - only fat ones
						if (s > 0 & s < 30000) {s = (short) (s + 30000);}
						if (s < 0 & s > -30000) {s = (short) (s - 30000);}

						//   System.out.println(s);
						//=============== End of Process ============
						// as the output stream is a byte array load the low/high integer	   
						byte hexBase ; // A byte of all ones
						hexBase = (byte) 255;
						byte b1 = (byte) (hexBase & s);
						byte b2 = (byte) ((hexBase <<(8)& s) >> 8);
						//System.out.println(b1);
						playBuffer[cnt] = b2 ;
						playBuffer[cnt+1] = b1 ;
					}
					sourceDataLine.write(playBuffer, 0, 100);
				} // end of loop
				// -------------------------- loop ---------------------
				//Block and wait for internal buffer of the
				// SourceDataLine to become empty.
				sourceDataLine.drain();
				//Finish with the SourceDataLine
				sourceDataLine.stop();
				sourceDataLine.close();

			}catch (Exception e) {
				e.printStackTrace();
				System.exit(0);
			}//end catch
		}//end run
	}//end inner class ListenThread
}//end outer class 

