package kompose;

import com.cycling74.max.*;
import java.io.*;
import javax.sound.midi.*;
import java.lang.*;
import java.util.*;

public class jbm_MidiParse extends MaxObject
	{
	private static Sequence _current_seq;
	private static DumpReceiver _my_receiver;
	private static TreeMap<Integer,ArrayList> MIDI_noteons;						// all noteons by track
	private static TreeMap<Integer,ArrayList> MIDI_noteoffs;					// all noteoffs by track
	private String inst = "";
	
	private static TreeMap<Integer,ArrayList> MIDI_completeSequenceMap;			// all complete event info by track
	/*
		Each track of the sequence is stored in an ArrayList. The track 
		number is an Integer, which acts as a key into the MIDI_completeEventList.

		Nov. 29, 2006 --- NOTE: There is currently a significant problem in this data, involving the interval values. Since these are not
		derived using Voice information, they will not be correct in any situation where the instrument/track contains chords. In such
		cases, the melodic intervals will be lumped-in with harmonic intervals. This will have implications for SPEAC detection at later
		stages in the analysis and should be fixed. The simplest way to do this (if not the most efficient) is to separate the track into
		temporary data structures, by voice, thus grouping all like voices together individual ArrayLists, then iterating through these
		voice data structures when assigning interval values.

	*/	

	public jbm_MidiParse() 
		{
		_current_seq = null;
		_my_receiver = null;
		MIDI_noteons = new TreeMap<Integer,ArrayList>();
		MIDI_noteoffs = new TreeMap<Integer,ArrayList>();	
		MIDI_completeSequenceMap = new TreeMap<Integer,ArrayList>();
		}
	
	
	public TreeMap parseMidiFile(String midifile)
		{
		int eventCount = 0;
		double tempo = 0.0;
	//	String Instrument = "";
	//	String MIDI_port = "";
		Integer ts_num = new Integer(0);
		Integer ts_denom = new Integer(0);
		int status = 0;
		int data1 = 0;
		int data2 = 0;
		Double temp = new Double(0.0);
		Double tempI = new Double(0.0);	
		
	//=== rawSeq info =============================================================//
	//																			   //
	// resolution, tempo, status, data1, data2, tickStamp, ts_num, ts_denom, voice //
	//																			   //
	//=============================================================================//
	
	//	clearFile(); 	// enable this later to clear before analyzing new file

		String abs_path = MaxSystem.locateFile(midifile);

		if (_my_receiver == null)
			_my_receiver = new DumpReceiver();
		if (abs_path == null)
			post("unable to locate " + midifile + "in Max search path");
		else {
			try {
				_current_seq = MidiSystem.getSequence(new File(abs_path));
			} catch (InvalidMidiDataException e) {
				post("File " + abs_path + "is not a valid MIDI file");
			} catch (IOException e2) {
				e2.printStackTrace();
			}
			int resolution = _current_seq.getResolution();
			Track[] tracks = _current_seq.getTracks();
			
			// Special list for track end messages
			ArrayList<Atom[]> messages = new ArrayList<Atom[]>();
			
			for (int nTrack = 0; nTrack < tracks.length; nTrack++) 
				{
				pitchArray = new int[128];
				for(int i=0;i < 16;i++)
					{
					voiceStatusArray[i] = 1;																// initialize voiceStatusArray
					}
				noteState = new int[128];
			//	double endMarker = 0.0;
				Track track = tracks[nTrack];
				Integer trackKey = new Integer(nTrack);
				Integer messageTrackKey = new Integer(999);
				
				post("track: " +trackKey);
				ArrayList<Atom[]> thisTrack_noteons = new ArrayList<Atom[]>(40);
				ArrayList<Atom[]> thisTrack_noteoffs = new ArrayList<Atom[]>(40);
				for (int nEvent = 0; nEvent < track.size(); nEvent++) 
					{
					Atom[] rawSeq = new Atom[10];
					MidiEvent event = track.get(nEvent);
					double tickStamp = event.getTick();
				//	post("tickStamp: " +tickStamp);
					
					// Special info for track end
					Atom[] end = new Atom[4];
					
					rawSeq[5] = Atom.newAtom((int)tickStamp);
					rawSeq[0] = Atom.newAtom((int)resolution);
					
					MidiMessage eventInfo = event.getMessage();

					if (eventInfo instanceof MetaMessage)
						{
						String tempRet = _my_receiver.decodeMessage((MetaMessage) eventInfo);
					//	post(tempRet);
						StringTokenizer st = new StringTokenizer(tempRet);
						String label = st.nextToken();
						if(label.equals("Tempo"))
							{
							temp = temp.valueOf(st.nextToken());
							tempo = temp.doubleValue();
							post("Tempo: " +tempo);
							}
							
						if(label.equals("Name"))
							{
							inst = st.nextToken();
							post("Instrument: " +inst);
							}						
							
						if(label.equals("Time_Signature"))
							{
							String timesig = st.nextToken();
							StringTokenizer stts = new StringTokenizer(timesig,"/");
							ts_num = ts_num.valueOf(stts.nextToken());
							ts_denom = ts_denom.valueOf(stts.nextToken());
							post("Time signature: " +ts_num +"/" +ts_denom);
							}
						if(label.equals("End"))
							{
						//	post("End tick: " +tickStamp);
							end[0] = Atom.newAtom((long)tickStamp);
							end[1] = Atom.newAtom((int)resolution);
							end[2] = Atom.newAtom((int)ts_num);
							end[3] = Atom.newAtom((int)ts_denom);
						//	post("Adding end of track: " +Atom.toDebugString(end));
							messages.add(end);
							post("End of Track: " +tickStamp);
							}
       	        	 	}

					else if (eventInfo instanceof ShortMessage)
						{
						eventCount++;
						Integer eventKey = new Integer(eventCount);
						String tempRet2 = _my_receiver.decodeMessage((ShortMessage) eventInfo);
						StringTokenizer st = new StringTokenizer(tempRet2);
						if(st.nextToken().equals("event"))
							{
							ArrayList<Double> rawSeqStrings = new ArrayList<Double>(3);
							while(st.hasMoreTokens())
								{
								rawSeqStrings.add(Double.valueOf(st.nextToken()));
								}
							if(rawSeqStrings.size() == 3)
								{
								
								tempI = rawSeqStrings.get(0);
								status = tempI.intValue();
								rawSeq[2] = Atom.newAtom((int)status);
							//	post("status: " +status);


								tempI = rawSeqStrings.get(1);
								data1 = tempI.intValue();
								rawSeq[3] = Atom.newAtom((int)data1);
							//	post("data1: " +data1);

								tempI = rawSeqStrings.get(2);
								data2 = tempI.intValue();
								rawSeq[4] = Atom.newAtom((int)data2);
							//	post("data2: " +data2);
								} else {
								
								tempI = rawSeqStrings.get(0);
								status = tempI.intValue();
								rawSeq[2] = Atom.newAtom((int)status);
							//	post("status: " +status);


								tempI = rawSeqStrings.get(1);
								data1 = tempI.intValue();
								rawSeq[3] = Atom.newAtom((int)data1);
							//	post("data1: " +data1);

								rawSeq[4] = Atom.newAtom((int)0);
							//	post("data2: " +data2);		
								}						
													
							}
														
						rawSeq[1] = Atom.newAtom((int)tempo);
						rawSeq[6] = Atom.newAtom((Integer)ts_num);
						rawSeq[7] = Atom.newAtom((Integer)ts_denom);
						rawSeq[8] = Atom.newAtom((int)0);

						if((rawSeq[2].getInt() >= 128) && (rawSeq[2].getInt() < 160))
							{
							if(rawSeq[2].getInt() < 144)
								{
								rawSeq[4] = Atom.newAtom((int)0);
								}
							int tempPitch = rawSeq[3].getInt();
							int tempVel = rawSeq[4].getInt();
							rawSeq[8] = Atom.newAtom((int)getVoiceNumber(tempPitch,tempVel));
							if(rawSeq[4].getInt() > 0) // if noteon
								{
								thisTrack_noteons.add(rawSeq);									// store all noteons (note events)
								} else {
								thisTrack_noteoffs.add(rawSeq);									// store all noteoffs (note events)
								}
							}
						if((rawSeq[2].getInt() >= 176) && (rawSeq[2].getInt() < 192))
							{
							rawSeq[4] = Atom.newAtom((int)0);
							thisTrack_noteons.add(rawSeq);										// to make sure noteon and noteoff lists contain identical event counts
							thisTrack_noteoffs.add(rawSeq);										// store CCs in BOTH noteon and noteoff lists
							}
						// July 30, 2007 - pitchbend data added as CC (will map to CC 999)
						if((rawSeq[2].getInt() >= 224) && (rawSeq[2].getInt() < 240))
							{
							rawSeq[4] = Atom.newAtom((int)0);
							thisTrack_noteons.add(rawSeq);										// do the same for pitchbend info
							thisTrack_noteoffs.add(rawSeq);										
							}
						// ----------------------------------------------------------------
						rawSeq[9] = Atom.newAtom((String)inst);
				//		post("rawSeq: " +rawSeq[0] +" " +rawSeq[1] +" " +rawSeq[2] +" " +rawSeq[3] +" " +rawSeq[4] +" " +rawSeq[5] +" " +rawSeq[6] +" " +rawSeq[7] +" " +rawSeq[8]);

						}
					}
		//		post("noteons: " +thisTrack_noteons.size() +", noteoffs: " +thisTrack_noteoffs.size());	
				MIDI_noteons.put(trackKey,thisTrack_noteons);									// store noteons ArrayList in MIDI_noteons map by Track number
				MIDI_noteoffs.put(trackKey,thisTrack_noteoffs);									// store noteoffs ArrayList in MIDI_noteoffs map by Track number
				}	
			addTrackEndInfo(messages);
			build_MIDI_completeSequenceMap();
			}
		return MIDI_completeSequenceMap;	
		}					
							
	private void addTrackEndInfo(ArrayList<Atom[]> endMessages)
		{
		Integer messageTrackKey = new Integer(999);
		MIDI_completeSequenceMap.put(messageTrackKey, endMessages);
		}
	
	private void build_MIDI_completeSequenceMap()
		{	
		int thisPitch, lastPitch;
		Set tracksList = MIDI_noteons.keySet();
		Iterator track_itr = tracksList.iterator();
		
		while(track_itr.hasNext())																		// outer loop gets noteon and noteoff ArrayLists for each track
			{
			count = 0;
			thisPitch = 0;
			lastPitch = 0;
			Integer trackCount = (Integer)track_itr.next();
			ArrayList<Atom[]> thisTrack_noteons = (ArrayList<Atom[]>)MIDI_noteons.get(trackCount);
			ArrayList<Atom[]> thisTrack_noteoffs = (ArrayList<Atom[]>)MIDI_noteoffs.get(trackCount);
			ArrayList<Atom[]> completeTrackEventList = new ArrayList<Atom[]>(40);						// new data structure for this track's completed events
			for(int nEvent = 0;nEvent < thisTrack_noteons.size();nEvent++)								// inner loop runs through events in track
				{
				Atom[] MIDI_completeEventEntry = new Atom[15]; 											// data structure for each event's complete event data
				MIDI_completeEventEntry = MIDI_completeEventEntryInit(MIDI_completeEventEntry);
	
	//===== MIDI_completeEventEntry info ===================================================================================================================//
	//																																	      		 		//
	// event_index, tickStamp, beatResolution, ts_num, ts_denom, pitch, interval, velocity, duration, ED_offset, CCNum, CCVal, channel, voice, instrument 	//	
	//																											 (999 = bend)																															      		 		//
	//======================================================================================================================================================//

				/*
				 * July 14: Some midi files are malformed, and have fewer noteoffs than noteons. The following
				 * lines have been given conditions to skip events in these situations.
				 */
				Atom[] thisNoteonEvent = new Atom[15];
				Atom[] thisNoteoffEvent = new Atom[15];
				if(thisTrack_noteons.size() > nEvent)
					thisNoteonEvent = thisTrack_noteons.get(nEvent);									// get raw lists for noteons
				else 
					continue;
				if(thisTrack_noteoffs.size() > nEvent)
					thisNoteoffEvent = thisTrack_noteoffs.get(nEvent);								// get raw lists for noteoffs
				else 
					continue;
				int resolution = thisNoteonEvent[0].getInt();
				/*
				 * July 30, 2007. Moving CC and bend data detection before note data. This data will
				 * be assigned to temporary variables so that, when note events follow CC or bend events,
				 * this data will still be held in the correct variables. This should allow note events
				 * to indicate the CC or bend settings at the time of the note event, which could be useful
				 * for detecting patch/matrix changes and quarter-tone playback. The one major drawback,
				 * of course, in the case of CC data, is that only the LAST CC change to be sent before the
				 * note event can be recorded with the note events... lame.
				 * 
				 * The other possible option, which could be pursued later on, if necessary, would be to
				 * turn MIDI_completeEventEntry[10] and [11] into Strings, the contents of which indicate
				 * the CC and bend data at the time of the note event. All CC data collected since the last
				 * note event would be packed into a String, so that if multiple CCs had been used to select
				 * a given articulation, all of the data would be recorded.
				 */
				Atom CC_num_temp = Atom.newAtom((int)0);
				Atom CC_val_temp = Atom.newAtom((int)0);
				if((thisNoteonEvent[2].getInt() >= 176) && (thisNoteonEvent[2].getInt() < 192))
					{
					MIDI_completeEventEntry[10] = thisNoteonEvent[3];									// CCVal -- Atom(int)
					CC_num_temp = thisNoteonEvent[3];
					MIDI_completeEventEntry[11] = thisNoteonEvent[4];									// CcNum -- Atom(int)
					CC_val_temp = thisNoteonEvent[4];
					MIDI_completeEventEntry[0] = Atom.newAtom((int)getEventCount
							(thisNoteonEvent[4].getInt()));												// EVENT_COUNT -- Atom(int)
					}
				// July 30, 2007 - trying to add pitchbend data
				if((thisNoteonEvent[2].getInt() >= 224) && (thisNoteonEvent[2].getInt() < 240))
					{
					MIDI_completeEventEntry[10] = Atom.newAtom((int)999);	// *hack* CC 999 will be detected as pitchbend -- Atom(int)
					CC_num_temp = thisNoteonEvent[3];
					MIDI_completeEventEntry[11] = thisNoteonEvent[4];									// Bend value -- Atom(int)
					CC_val_temp = thisNoteonEvent[4];
					MIDI_completeEventEntry[0] = Atom.newAtom((int)getEventCount
							(thisNoteonEvent[4].getInt()));												// EVENT_COUNT -- Atom(int)
					}
				// ---------------------------------------------
				if((thisNoteonEvent[2].getInt() >= 144) && (thisNoteonEvent[2].getInt() < 160))			// if it's a note event
					{
					MIDI_completeEventEntry[14] = thisNoteonEvent[9];									// INSTRUMENT -- Atom(String)
					MIDI_completeEventEntry[13] = thisNoteonEvent[8];									// VOICE -- Atom(int)
					int voice = thisNoteonEvent[8].getInt();
					MIDI_completeEventEntry[1] = thisNoteonEvent[5];									// TICKSTAMP -- Atom(double)
					MIDI_completeEventEntry[2] = Atom.newAtom((int)getBeatResolution
							(resolution,(int)thisNoteonEvent[6].getInt(),(int)thisNoteonEvent[7].getInt())); 	// BEAT RESOLUTION -- (int)
					// post("beat res: " +MIDI_completeEventEntry[2]);
					MIDI_completeEventEntry[3] = thisNoteonEvent[6];									// TS_NUM -- Atom(Integer)
					MIDI_completeEventEntry[4] = thisNoteonEvent[7];									// TS_DENOM -- Atom(Integer)
					MIDI_completeEventEntry[5] = thisNoteonEvent[3];			 						// PITCH -- Atom(int)
					thisPitch = thisNoteonEvent[3].getInt();
					MIDI_completeEventEntry[6] = Atom.newAtom((int)getInterval(thisPitch, lastPitch, voice));	// INTERVAL -- Atom(int)
					//	post("interval: " +beatEventEntry[7]);
					MIDI_completeEventEntry[7] = thisNoteonEvent[4];									// VELOCITY -- Atom(int)
					//	post("velocity: " +MIDI_completeEventEntry[7]);
					MIDI_completeEventEntry[8] = Atom.newAtom((long)getDuration
							(thisNoteonEvent[5].getInt(),thisNoteoffEvent[5].getInt()));				// DURATION -- Atom(long)
					MIDI_completeEventEntry[9] = Atom.newAtom((long)getED_offset
							(MIDI_completeEventEntry[2].getInt(),thisNoteonEvent[5].getInt()));			// ED_OFFSET -- Atom(long)
					MIDI_completeEventEntry[12] = Atom.newAtom((int)getChannel(thisNoteonEvent[2]));	// CHANNEL -- Atom(int)
					MIDI_completeEventEntry[0] = Atom.newAtom((int)getEventCount
							(thisNoteonEvent[4].getInt()));												// EVENT_COUNT -- Atom(int)
					MIDI_completeEventEntry[10] = CC_num_temp;	// ADD CC number and value stored above
					MIDI_completeEventEntry[11] = CC_val_temp;	// Remember that CC 999 is used for bend info!
					}
				lastPitch = thisPitch;	
				completeTrackEventList.add(MIDI_completeEventEntry);
				}
			MIDI_completeSequenceMap.put(trackCount,completeTrackEventList);	
			}			
		}



// +++++++++++++++++++ Private methods for determining Sequence data +++++++++++++++++++++++++++++++++++++ //



	// ----------- get running event count --------------------- //
	int count = 0;

	private int getEventCount(int vel)
		{
		if(vel > 0)
			{
			count++;
			}	
	//	post("note count: " +count);
		return count;
		}	


	// ---- get proper beat resolution (simple/compound time ----- //

	/*
		This kind of sucks, but it may be the only widely-adaptable solution. Problems with actually finding the correct
		downbeats for the entire track, given the possibility of time signature changes, makes the idea of cutting Groups
		to 1/8th-note in duration very attractive. This way, the vast majority of time signatures can be mapped out reasonably
		well. There's still the problem of beat position within measures (beat stress) to consider, though...
	
		It may, however, make sense to ignore the time signatures, as they may not always follow the most transparent structural
		logic anyway, even though they are specified in the score. 

		The other possibility is to have beats change length based on context. The idea would simply be to group identical 1/8th-note
		Group Labels into single, longer duration Groups. That is, if [58, 67, 75] occurs 3 times in a row, then the Group would be
		defines as a dotted-quarter length Group with the label [58, 67, 75]. 
	*/
	private int getBeatResolution(int resolution, int ts_num, int ts_denom)
		{
	//	boolean is_Odd_eighth = false;
	//	switch(ts_num)
	//		{
	//		case 5: is_Odd_eighth = true; break;
	//		case 7: is_Odd_eighth = true; break;
	//		case 10: is_Odd_eighth = true; break;
	//		case 11: is_Odd_eighth = true; break;
	//		case 13: is_Odd_eighth = true; break;
	//		}
		int beatResolution = 0;
	//	if((ts_denom > 4) && ((ts_num % 3) == 0))
	//		{
	//		beatResolution = resolution + (resolution/2);
	//		} else {
	//		beatResolution = resolution;
	//		}
	//	if((ts_denom == 8) && is_Odd_eighth)
	//		{
	//		beatResolution = resolution/2;
	//		}	
		beatResolution = resolution/2;		// half the PPQ becomes the beat length >>>> April 25, trying quarter-note res  (not resolution/2)
		return beatResolution;
		}

	// --------- get durations ----------------------------- //	
	int[] noteBuffer = new int[128];

	private long getDuration(int onTick, int offTick)
		{
		long duration = offTick - onTick;
		return duration;
		}


	// ---------- get ED_offsets (offset in ticks from downbeat) -------------- //
	private long getED_offset(int resolution, int tickStamp)
		{
		long ED_offset =  tickStamp % resolution;
		return ED_offset;
		}

	// -------------- get channel ---------------- //
	private int getChannel(Atom status)
		{
		int statusVal = status.getInt();
		int channel = 0;
		if((statusVal >= 144) && (statusVal < 160))
			{
			channel = statusVal - 143;
			}
		return channel;
		}

	// ------------ get voice number ----------------- //
	// ------ this is being done with rawSeq! -------- //
	int[] pitchArray = new int[128];
	int[] voiceStatusArray = new int[16];

	private int getVoiceNumber(int pitch, int vel)
		{
		int voiceNumber = 1;
		if(vel > 0)
			{
			for(int i=0;i < 16;i++)
				{
				if(voiceStatusArray[i] == 1) 							// if the voice is free - loop actually find first "free" (1) voice
					{
					voiceNumber = i + 1; 								// assign voice as index + 1
				//	post("voiceStatusArray: " +voiceNumber);
					voiceStatusArray[i] = 0;							// set voiceStatusArray index to "0" (voice is NOT available)
					break;
					}
				}
			if(voiceNumber < 1)
				{ 
				voiceNumber = 1;										// fudge for double-noteoff problems (2 consecutive noteoffs with same pitch)
				}
			pitchArray[pitch] = voiceNumber;
			} else {
			voiceNumber = pitchArray[pitch];							// get the voiceNumber for the noteoff
			if(voiceNumber < 1)
				{ 
				voiceNumber = 1;										// fudge for double-noteoff problems (2 consecutive noteoffs with same pitch)
				}
			pitchArray[pitch] = 0;										// clear the pitch for the noteoff
			voiceStatusArray[voiceNumber - 1] = 1;						// reset the voice to "available"
			}
		return voiceNumber;
		}

	// ------------- get interval ----------------------- //
	
	/*
		As noted above, this must be made a little more intelligent with regard to voice number. This new version will use
		a temporary register to store voice numbers and will only calculate intervals between thisNote and lastNote, for
		each distinct voice.

		The version below seems to be okay, but should be tested with a midi file containing only chords.
	*/

	int v1_lastPitch = 0;
	int v2_lastPitch = 0;
	int v3_lastPitch = 0;
	int v4_lastPitch = 0;
	int v5_lastPitch = 0;
	int v6_lastPitch = 0;
	int v7_lastPitch = 0;
	int v8_lastPitch = 0;
	int v9_lastPitch = 0;
	int v10_lastPitch = 0;
	int v11_lastPitch = 0;
	int v12_lastPitch = 0;

	private int getInterval(int thisPitch, int lastPitch, int voice)
		{
		int interval = 0;
		switch(voice)
			{
			case 1:		v1_lastPitch = lastPitch; 
						interval = thisPitch - v1_lastPitch; break;
			case 2:		v2_lastPitch = lastPitch; 
						interval = thisPitch - v2_lastPitch; break;
			case 3:		v3_lastPitch = lastPitch; 
						interval = thisPitch - v3_lastPitch; break;
			case 4:		v4_lastPitch = lastPitch; 
						interval = thisPitch - v4_lastPitch; break;
			case 5:		v5_lastPitch = lastPitch; 
						interval = thisPitch - v5_lastPitch; break;
			case 6:		v6_lastPitch = lastPitch; 
						interval = thisPitch - v6_lastPitch; break;
			case 7:		v7_lastPitch = lastPitch; 
						interval = thisPitch - v7_lastPitch; break;
			case 8:		v8_lastPitch = lastPitch; 
						interval = thisPitch - v8_lastPitch; break;
			case 9:		v9_lastPitch = lastPitch; 
						interval = thisPitch - v9_lastPitch; break;
			case 10:	v10_lastPitch = lastPitch; 
						interval = thisPitch - v10_lastPitch; break;
			case 11:	v11_lastPitch = lastPitch; 
						interval = thisPitch - v11_lastPitch; break;
			case 12:	v12_lastPitch = lastPitch; 
						interval = thisPitch - v12_lastPitch; break;
			}
	//	post("interval: " +interval +", voice: " +voice);
		return interval;
		}
	
	int[] noteState = new int[128];

	// initialize the boraxOut array to avoid nullPointerExceptions
	// types: 0=int, 1=double, 2=int, 3=Integer, 4=Integer, 5=int, 6=int, 7=int, 8=long, 9=long, 10=int, 11=int, 12=int, 13=int
	private Atom[] MIDI_completeEventEntryInit(Atom[] event)
		{
		int initAsInt = 0;
		long initAsLong = (long)0;
		double initAsDouble = (double)0.0;
		Integer initAsInteger = new Integer(0);
		for(int i = 0;i < event.length;i++)
			{
			switch(i)
				{
				case 0: event[i] = Atom.newAtom((int)initAsInt); break;
				case 1: event[i] = Atom.newAtom((double)initAsDouble); break;
				case 2: event[i] = Atom.newAtom((int)initAsInt); break;
				case 3: event[i] = Atom.newAtom((Integer)initAsInteger); break;
				case 4:	event[i] = Atom.newAtom((Integer)initAsInteger); break;
				case 5:	event[i] = Atom.newAtom((int)initAsInt); break;
				case 6: event[i] = Atom.newAtom((int)initAsInt); break;
				case 7: event[i] = Atom.newAtom((int)initAsInt); break;
				case 8: event[i] = Atom.newAtom((long)initAsLong); break;
				case 9:	event[i] = Atom.newAtom((int)initAsInt); break;
				case 10: event[i] = Atom.newAtom((int)initAsInt); break;
				case 11: event[i] = Atom.newAtom((int)initAsInt); break;
				case 12: event[i] = Atom.newAtom((int)initAsInt); break;
				case 13: event[i] = Atom.newAtom((int)initAsInt); break;
				}
			}
		return event;
		}

	}	