diff --git a/Builds/VisualStudio2013/open-ephys.sln b/Builds/VisualStudio2013/open-ephys.sln
index 59a9d10ba28a4b47817570df74b1433044daefbb..04e5ad8e940f5a2fd76f23d26080ccf301f4f1c9 100644
--- a/Builds/VisualStudio2013/open-ephys.sln
+++ b/Builds/VisualStudio2013/open-ephys.sln
@@ -1,6 +1,9 @@
-Microsoft Visual Studio Solution File, Format Version 11.00
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Express 2013 for Windows Desktop
+VisualStudioVersion = 12.0.21005.1
 # Visual Studio 2013
-Project("{5A05F353-1D63-394C-DFB0-981BB2309002}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}"
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/Source/Processors/Channel/Channel.cpp b/Source/Processors/Channel/Channel.cpp
index e3a20afb7daffa9ce07d6e6c95a3353114d5f32b..dee6db3795fc79dd44c7fd20268591618f4d0e16 100644
--- a/Source/Processors/Channel/Channel.cpp
+++ b/Source/Processors/Channel/Channel.cpp
@@ -70,6 +70,7 @@ Channel::Channel(const Channel& ch)
     y = ch.y;
     z = ch.z;
     impedance = ch.impedance;
+	extraData = ch.extraData;
 
     setRecordState(false);
 }
@@ -138,14 +139,8 @@ void Channel::createDefaultName()
         case EVENT_CHANNEL:
             name = String("EVENT");
             break;
-        case SINGLE_ELECTRODE:
-            name = String("SE");
-            break;
-        case STEREOTRODE:
-            name = String("ST");
-            break;
-        case TETRODE:
-            name = String("TT");
+        case ELECTRODE_CHANNEL:
+            name = String("ELEC");
             break;
         case MESSAGE_CHANNEL:
             name = String("MSG");
@@ -153,3 +148,17 @@ void Channel::createDefaultName()
 
     name += index;
 }
+
+bool Channel::getRecordState()
+{
+	return isRecording;
+}
+
+ChannelExtraData::ChannelExtraData(void* ptr, int size)
+	: dataPtr(ptr), dataSize(size)
+{
+}
+
+ChannelExtraData::~ChannelExtraData()
+{
+}
\ No newline at end of file
diff --git a/Source/Processors/Channel/Channel.h b/Source/Processors/Channel/Channel.h
index af53777607ddace822aa8a1ca8780e7e851a35ec..f7dceb166c84c2ba93e85ebf36cba11e7ca1a201 100644
--- a/Source/Processors/Channel/Channel.h
+++ b/Source/Processors/Channel/Channel.h
@@ -32,6 +32,7 @@
 #include <stdio.h>
 
 class GenericProcessor;
+class ChannelExtraData;
 
 /**
 
@@ -87,10 +88,7 @@ public:
     void setRecordState(bool t); // {isRecording = t;}
 
     /** Sets whether or not the channel will record. */
-    bool getRecordState()
-    {
-        return isRecording;
-    }
+	bool getRecordState();
 
     /** Sets the bitVolts value for this channel. */
     void setBitVolts(float bitVolts);
@@ -154,6 +152,8 @@ public:
     /** Impedance of this channel. */
     float impedance;
 
+	/** For use with special event channels. */
+	ReferenceCountedObjectPtr<ChannelExtraData> extraData;
 
 private:
 
@@ -167,4 +167,13 @@ private:
 
 };
 
+class ChannelExtraData : public ReferenceCountedObject
+{
+public:
+	ChannelExtraData(void* data, int size);
+	virtual ~ChannelExtraData();
+	void* const dataPtr;
+	const int dataSize;
+};
+
 #endif  // __CHANNEL_H_DABDFE3F__
diff --git a/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.cpp b/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.cpp
index 95d1ec5e052765802a066bd7063500fc471379af..db90e2bb8761cece31a49db9ed1898debb5c39f7 100644
--- a/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.cpp
+++ b/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.cpp
@@ -278,12 +278,12 @@ void PeriStimulusTimeHistogramEditor::buttonEvent(Button* button)
 			PopupMenu m;
 			
 			
-			m.addItem(1,"TTL",true, processor->saveTTLs);
+		/*	m.addItem(1,"TTL",true, processor->saveTTLs);
 			m.addItem(2,"Network Events",true, processor->saveNetworkEvents);
 			m.addItem(7,"Network Events [when recording is off]",true, processor->saveNetworkEventsWhenNotRecording);
-			m.addItem(3,"Eye Tracking",true, processor->saveEyeTracking);
+			m.addItem(3,"Eye Tracking",true, processor->saveEyeTracking);*/
 			
-			m.addItem(4,"Sorted Spikes: TS only ",true, processor->spikeSavingMode == 1);
+			//m.addItem(4,"Sorted Spikes: TS only ",true, processor->spikeSavingMode == 1);
 			m.addItem(5,"Sorted Spikes: TS+waveform",true, processor->spikeSavingMode == 2);
 			m.addItem(6,"All Spikes: TS+waveform",true, processor->spikeSavingMode == 3);
 			
diff --git a/Source/Processors/GenericProcessor/GenericProcessor.h b/Source/Processors/GenericProcessor/GenericProcessor.h
index 32059caf80c5ea182793fb2c1b704c0e2037e919..1135db44a1b6573be25ff1d671552b23212aa28f 100755
--- a/Source/Processors/GenericProcessor/GenericProcessor.h
+++ b/Source/Processors/GenericProcessor/GenericProcessor.h
@@ -25,7 +25,7 @@
 #define __GENERICPROCESSOR_H_1F469DAF__
 
 enum ChannelType {HEADSTAGE_CHANNEL = 0, AUX_CHANNEL = 1, ADC_CHANNEL = 2, EVENT_CHANNEL = 3,
-                  SINGLE_ELECTRODE = 4, STEREOTRODE = 5, TETRODE = 6, MESSAGE_CHANNEL = 7
+                  ELECTRODE_CHANNEL = 4,  MESSAGE_CHANNEL = 5 
                  };
 
 #include "../../../JuceLibraryCode/JuceHeader.h"
diff --git a/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.cpp b/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.cpp
index 3aa78eb1f00041fb0f5d7c618082e53eca96e898..31dc71c595b7e710466b53517e4f0879903dcb51 100644
--- a/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.cpp
+++ b/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.cpp
@@ -37,7 +37,6 @@ PeriStimulusTimeHistogramNode::PeriStimulusTimeHistogramNode()
     : GenericProcessor("PSTH"), displayBufferSize(5),  redrawRequested(false)
 {
 	trialCircularBuffer  = nullptr;
-	eventFile = nullptr;
 	isRecording = false;
 	saveEyeTracking = saveTTLs = saveNetworkEvents = false;
 	saveNetworkEventsWhenNotRecording = false;
@@ -114,13 +113,19 @@ void PeriStimulusTimeHistogramNode::allocateTrialCircularBuffer()
 
 void PeriStimulusTimeHistogramNode::updateSettings()
 {
-	delete trialCircularBuffer;
 	trialCircularBuffer = nullptr;
 	if (trialCircularBuffer  == nullptr && getSampleRate() > 0 && getNumInputs() > 0)
 	{
 		allocateTrialCircularBuffer();
 		syncInternalDataStructuresWithSpikeSorter();
 	}
+	electrodeChannels.clear();
+	for (int k = 0; k < eventChannels.size(); k++)
+	{
+		if ((eventChannels[k]->type == ELECTRODE_CHANNEL) &&
+			(static_cast<SpikeChannel*>(eventChannels[k]->extraData.get())->dataType == SpikeChannel::Sorted))
+			electrodeChannels.add(eventChannels[k]);
+	}
 
 	recordNode = getProcessorGraph()->getRecordNode();
 //    diskWriteLock = recordNode->getLock();
@@ -137,6 +142,16 @@ bool PeriStimulusTimeHistogramNode::enable()
     std::cout << "PeriStimulusTimeHistogramNode::enable()" << std::endl;
 	PeriStimulusTimeHistogramEditor* editor = (PeriStimulusTimeHistogramEditor*) getEditor();
     editor->enable();
+
+	recordNode->registerSpikeSource(this);
+	for (int i = 0; i < electrodeChannels.size(); i++)
+	{
+		SpikeRecordInfo *recElec = new SpikeRecordInfo();
+		recElec->name = electrodeChannels[i]->name;
+		recElec->numChannels = static_cast<SpikeChannel*>(electrodeChannels[i]->extraData.get())->numChannels;
+		recElec->sampleRate = settings.sampleRate;
+		electrodeChannels[i]->recordIndex = recordNode->addSpikeElectrode(recElec);
+	}
 		
     return true;
 
@@ -186,186 +201,22 @@ void PeriStimulusTimeHistogramNode::process(AudioSampleBuffer& buffer, MidiBuffe
 
 
 
-void PeriStimulusTimeHistogramNode::dumpStartStopRecordEventToDisk(int64 ts, bool startRecord)
-{
-	const ScopedLock myScopedLock(diskWriteLock);
-	#define SESSION 10
-	uint8 eventType = SESSION;
-
-	// write event type
-	fwrite(&eventType, 1,1, eventFile); 
-	// write event size
-	int16 eventSize = 1 +2+ 8; // start/stop(1) + recordnumber (2) + timestamp (8)
-    fwrite(&eventSize, 2,1, eventFile);
-	// write event data
-	// 1. Start/stop
-	fwrite(&startRecord, 1,1, eventFile);
-	// 2. record number
-	fwrite(&recordingNumber, 2,1, eventFile);
-	// 3. the software timestamp
-	fwrite(&ts, 8,1, eventFile);
-
-
-}
-
-void PeriStimulusTimeHistogramNode::dumpNetworkEventToDisk(String S, int64 ts)
-{
-	const ScopedLock myScopedLock(diskWriteLock);
-	
-	uint8 eventType = NETWORK;
-
-	// write event type
-	fwrite(&eventType, 1,1, eventFile); 
-	// write event size
-	int16 eventSize = S.getNumBytesAsUTF8() + 8; // string length + timestamp
-    fwrite(&eventSize, 2,1, eventFile);
-	// write event data
-	// 1. the network event string
-	fwrite(S.toUTF8(), S.getNumBytesAsUTF8(), 1, eventFile);
-	// 2. the software timestamp
-	fwrite(&ts, 8,1, eventFile);
-
-	
-}
-
-void PeriStimulusTimeHistogramNode::dumpSpikeEventToDisk(SpikeObject *s, bool dumpWave)
-{
-	const ScopedLock myScopedLock(diskWriteLock);
-
-
-
-	uint8 eventType = SPIKE;
-
-	// write event type
-	fwrite(&eventType, 1,1, eventFile); 
-	int16 eventSize = 8+8+2+2+2+2+2  + s->nChannels*4; // ts, ts, sorted id, electrode ID, num channels, num data per channel + 4x gains 
-
-	if (dumpWave)
-		eventSize += 2*(s->nSamples*s->nChannels); // uint16 per samples 
-
-	// write event size
-    fwrite(&eventSize, 2,1, eventFile);
-
-	// write event data
-	// 1. software ts
-	fwrite(&s->timestamp_software, 8,1, eventFile);
-	// 2. hardware ts
-	fwrite(&s->timestamp, 8,1, eventFile);
-	// 3. sorted ID
-	fwrite(&s->sortedId, 2,1, eventFile);
-	// 4. electrod ID
-	fwrite(&s->electrodeID, 2,1, eventFile);
-
-	// 5. Channel in which threshold was detected
-	fwrite(&s->channel, 2,1, eventFile);
-
-	// 6. num channels
-	fwrite(&s->nChannels, 2,1, eventFile);
-
-	// 7. gains
-	fwrite(&s->gain, 4,s->nChannels, eventFile);
-
-	// 8. num data points per channel
-	fwrite(&s->nSamples, 2,1, eventFile);
-	if (dumpWave)
-		fwrite(&s->data, 2,s->nSamples*s->nChannels, eventFile);
-
-	
-}
-void PeriStimulusTimeHistogramNode::dumpTTLeventToDisk(int channel, bool risingEdge, int64 ttl_timestamp_software, int64 ttl_timestamp_hardware, int samplePosition )
-{
-	const ScopedLock myScopedLock(diskWriteLock);
-	uint8 eventType = TTL;
-
-	// write event type
-	fwrite(&eventType, 1,1, eventFile); 
-	// write event size
-	int16 eventSize = 1 + 2 + 8 + 8; // rising/falling(1) + software ts (8) + hardware ts (8)
-    fwrite(&eventSize, 2,1, eventFile);
-	// write event data
-	// 1. rising/falling edge
-	fwrite(&risingEdge, 1, 1, eventFile);
-	// 2. channel
-	fwrite(&channel, 2,1,eventFile);
-	// 2. software ts
-	fwrite(&ttl_timestamp_software, 8,1, eventFile);
-	// 3. hardware ts
-	fwrite(&ttl_timestamp_hardware, 8,1, eventFile);
-
-	
-}
-/*
-void PeriStimulusTimeHistogramNode::dumpEyeTrackingEventToDisk(EyePosition pos)
-{
-	diskWriteLock->enter();
-
-	uint8 eventType = EYE_POSITION;
-
-	// write event type
-	fwrite(&eventType, 1,1, eventFile); 
-	// write event size
-	int16 eventSize = 8 + 8 + 8 + 8 + 8 +8 +8; //  x,y,xc,yc,pupil,timestamp
-    fwrite(&eventSize, 2,1, eventFile);
-	// write event data
-	// 1. eye x position
-	fwrite(&pos.x, 8,1, eventFile);
-	// 2. eye y position
-	fwrite(&pos.y, 8,1, eventFile);
-
-
-	// 3. calibrated eye x position
-	fwrite(&pos.xc, 8,1, eventFile);
-	// 4. calibrated eye y position
-	fwrite(&pos.yc, 8,1, eventFile);
-
-	// 5. eye pupil
-	fwrite(&pos.pupil, 8,1, eventFile);
-	// 6. software timestamp
-	fwrite(&pos.software_timestamp, 8,1, eventFile);
-	// 7. hardware timestamp
-	fwrite(&pos.hardware_timestamp, 8,1, eventFile);
-
-	diskWriteLock->exit();
-}
-*/
-void PeriStimulusTimeHistogramNode::dumpTimestampEventToDisk(int64 softwareTS,int64 hardwareTS)
-{
-	const ScopedLock myScopedLock(diskWriteLock);
-
-	uint8 eventType = TIMESTAMP;
-
-	// write event type
-	fwrite(&eventType, 1,1, eventFile); 
-	// write event size
-	int16 eventSize = 8 + 8; //  software ts (8) + hardware ts (8)
-    fwrite(&eventSize, 2,1, eventFile);
-	// write event data
-	// 1. software ts
-	fwrite(&softwareTS, 8,1, eventFile);
-	// 2. hardware ts
-	fwrite(&hardwareTS, 8,1, eventFile);
-
-	
-
-}
-
 void PeriStimulusTimeHistogramNode::syncInternalDataStructuresWithSpikeSorter()
 {
-	ProcessorGraph *g = getProcessorGraph();
-	Array<GenericProcessor*> p = g->getListOfProcessors();
-	for (int k=0;k<p.size();k++)
+	Array<Electrode*> electrodes;
+	
+	for (int k=0;k<eventChannels.size();k++)
 	{
-		if (p[k]->getName() == "Spike Sorter")
+		if ((eventChannels[k]->type == ELECTRODE_CHANNEL) && 
+			( static_cast<SpikeChannel*>(eventChannels[k]->extraData.get())->dataType == SpikeChannel::Sorted ))
 		{
-			SpikeSorter *node = (SpikeSorter*)p[k];
-			Array<Electrode*> electrodes = node->getElectrodes();
-
-			// for each electrode, verify that 
-			// 1. We have it in our internal structure 
-			// 2. All channels match
-			// 3. We have all sorted unit information
-			trialCircularBuffer->syncInternalDataStructuresWithSpikeSorter(electrodes);
+			electrodes.add(static_cast<Electrode*>(eventChannels[k]->extraData->dataPtr));
 		}
+		// for each electrode, verify that 
+		// 1. We have it in our internal structure 
+		// 2. All channels match
+		// 3. We have all sorted unit information
+		trialCircularBuffer->syncInternalDataStructuresWithSpikeSorter(electrodes);
 	}
 }
 
@@ -388,7 +239,6 @@ void PeriStimulusTimeHistogramNode::modifyTimeRange(double preSec_, double postS
 			TrialCircularBufferParams params = trialCircularBuffer->getParams();
 			params.preSec = preSec_;
 			params.postSec = postSec_;
-			delete trialCircularBuffer;
 			trialCircularBuffer = new TrialCircularBuffer(params);
 			trialCircularBuffer->syncInternalDataStructuresWithSpikeSorter(electrodes);
 
@@ -404,13 +254,13 @@ void PeriStimulusTimeHistogramNode::handleNetworkMessage(StringTS s)
 			ed->updateCanvas();
 		}
 			
-		if (isRecording && saveNetworkEvents)
+	/*	if (isRecording && saveNetworkEvents)
 		{
 			dumpNetworkEventToDisk(s.getString(),s.timestamp);
 		} else if (!isRecording && saveNetworkEvents && saveNetworkEventsWhenNotRecording)
 		{
 			networkEventsHistory.push(s);
-		}
+		}*/
 
 }
 void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& event, int samplePosition)
@@ -449,7 +299,7 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even
 	      memcpy(&hardware_timestamp, dataptr + 4, 8); // remember to skip first four bytes
 		  memcpy(&software_timestamp, dataptr + 12, 8); // remember to skip first four bytes
 		  
-		  if (isRecording)
+		 /* if (isRecording)
 		  {
 			  if (syncCounter == 0)
 			  {
@@ -462,7 +312,7 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even
 			  syncCounter++;
 			  if (syncCounter > 10)
 				  syncCounter = 0;
-		  }
+		  }*/
 
     } 
 	if (eventType == TTL)
@@ -479,8 +329,7 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even
 	   //memcpy(&ttl_timestamp_hardware, dataptr+12, 8);
 	   if (ttl_raise)
 			trialCircularBuffer->addTTLevent(channel,ttl_timestamp_software,ttl_timestamp_hardware, ttl_raise, true);
-	   if (isRecording && saveTTLs)
-		   dumpTTLeventToDisk(channel,ttl_raise,ttl_timestamp_software,ttl_timestamp_hardware,samplePosition );
+	  
 	}
 
     if (eventType == SPIKE)
@@ -497,12 +346,15 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even
 			}
 			if (isRecording)
 			{
-				if  (spikeSavingMode == 1 && newSpike.sortedId > 0)
-					dumpSpikeEventToDisk(&newSpike, false);
+				if (spikeSavingMode == 1 && newSpike.sortedId > 0)
+					recordNode->writeSpike(newSpike, electrodeChannels[newSpike.source]->recordIndex);
+					//dumpSpikeEventToDisk(&newSpike, false);
 				else if (spikeSavingMode == 2 && newSpike.sortedId > 0)
-					dumpSpikeEventToDisk(&newSpike, true);
+					recordNode->writeSpike(newSpike, electrodeChannels[newSpike.source]->recordIndex);
+					//dumpSpikeEventToDisk(&newSpike, true);
 				else if (spikeSavingMode == 3)
-					dumpSpikeEventToDisk(&newSpike, true);
+					recordNode->writeSpike(newSpike, electrodeChannels[newSpike.source]->recordIndex);
+					//dumpSpikeEventToDisk(&newSpike, true);
 			}
         }
     }
@@ -510,136 +362,12 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even
 
 }
 
-
-
-String PeriStimulusTimeHistogramNode::generateHeader()
-{
-
-    String header = "header.format = 'Open Ephys Data Format'; \n";
-    header += "header.version = 0.32;";
-    header += "header.header_bytes = ";
-    header += String(HEADER_SIZE);
-    header += ";\n";
-    header += "header.description = 'each record is size-varying. First is the record size (16-bit), followed by record type (uint8), followed by the actual data (which vary, depending on the type) '; \n";
-    header += "header.date_created = '";
-    header += recordNode->generateDateString();
-    header += "';\n";
-    header += "header.channel = '";
-    header += "events";
-    header += "';\n";
-    header += "header.channelType = 'Event';\n";
-    header += "header.sampleRate = ";
-    // all channels need to have the same sample rate under the current scheme
-    header += String(getSampleRate()); 
-    header += ";\n";
-    header += "header.blockLength = ";
-    header += BLOCK_LENGTH;
-    header += ";\n";
-    header += "header.bufferSize = ";
-    header += getAudioComponent()->getBufferSize();
-    header += ";\n";
-    header += "header.bitVolts = ";
-	if (recordNode->channels.size() > 0)
-	{
-		header += String(recordNode->channels[0]->bitVolts);
-	}
-	else
-	{
-		header += String(getDefaultBitVolts());
-	}
-
-    header += ";\n";
-
-	Time t;
-    header += "header.ticksPerSec = ";
-	header += String(t.getHighResolutionTicksPerSecond());
-    header += ";\n";
-
-    header = header.paddedRight(' ', HEADER_SIZE);
-    return header;
-
-}
-
-
-
-void PeriStimulusTimeHistogramNode::openFile(String filename)
-{
-    std::cout << "OPENING FILE: " << filename << std::endl;
-
-    File f = File(filename);
-     
-    bool fileExists = f.exists();
-    
-	const ScopedLock myScopedLock(diskWriteLock);
-
-    eventFile = fopen(filename.toUTF8(), "ab");
-
-    if (!fileExists)
-    {
-        // create and write header
-        std::cout << "Writing header." << std::endl;
-        String header = generateHeader();
-		int headerSize = header.getNumBytesAsUTF8();
-        std::cout << "File ID: " << eventFile << ", number of bytes: " << headerSize << std::endl;
-        fwrite(header.toUTF8(), header.getNumBytesAsUTF8(), 1, eventFile);
-        std::cout << "Wrote header." << std::endl;
-    }
-    else
-    {
-        std::cout << "File already exists, just opening." << std::endl;
-    }
- 
-}
-
-
 void PeriStimulusTimeHistogramNode::startRecording()
 {
-	if (!isRecording)
-	{
-        File dataDirectory = recordNode->getDataDirectory();
-
-        if (dataDirectory.getFullPathName().length() == 0)
-        {
-            // temporary fix in case nothing is returned by the record node.
-            dataDirectory = File::getSpecialLocation(File::userHomeDirectory); 
-        }
-
-        String baseDirectory = dataDirectory.getFullPathName();
-		String eventChannelFilename = baseDirectory + dataDirectory.separatorString + "all_channels.events";
-        openFile(eventChannelFilename);
-
-		// dump network events that arrived when we weren't recording
-		if (saveNetworkEventsWhenNotRecording)
-		{
-			while (networkEventsHistory.size() > 0)
-			{
-				StringTS s = networkEventsHistory.front();
-				dumpNetworkEventToDisk(s.getString(),s.timestamp);
-				networkEventsHistory.pop();
-			}
-		}
-
-//		recordingNumber = recordNode->getRecordingNumber();
-		Time t;
-		dumpStartStopRecordEventToDisk(t.getHighResolutionTicks(), true);
-		isRecording = true;
-
-	}
-
-
+	isRecording = true;
 }
 
 void PeriStimulusTimeHistogramNode::stopRecording()
 {
-	if (isRecording)
-	{
-		// close files, etc.
-		const ScopedLock myScopedLock(diskWriteLock);
-		std::cout << "CLOSING EVENT FILE: " << std::endl;
-		if (eventFile != nullptr)
-			fclose(eventFile);
-
-	
-		isRecording = false;
-	}
-}
+	isRecording = false;
+}
\ No newline at end of file
diff --git a/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.h b/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.h
index f5c3fdc8e46517fd0077bd781e5f57e0b3afdc82..5a54dbe9be89180feb57e5b7145c7b43f7828923 100644
--- a/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.h
+++ b/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.h
@@ -80,7 +80,7 @@ public:
 	void loadCustomParametersFromXml();
 	void modifyTimeRange(double preSec_, double postSec_);
 
-	TrialCircularBuffer *trialCircularBuffer;
+	ScopedPointer<TrialCircularBuffer> trialCircularBuffer;
 	bool saveTTLs, saveNetworkEvents,saveEyeTracking ;
 	int spikeSavingMode;
 	bool saveNetworkEventsWhenNotRecording;
@@ -90,17 +90,6 @@ public:
 	void handleNetworkMessage(StringTS s);
 private:
 
-	FILE* eventFile;
-	String generateHeader();
-	void openFile(String filename);
-
-	void dumpNetworkEventToDisk(String S, int64 ts);
-	void dumpSpikeEventToDisk(SpikeObject *s,  bool dumpWave);
-	void dumpTimestampEventToDisk(int64 softwareTS,int64 hardwareTS);
-	void dumpTTLeventToDisk(int channel,bool risingEdge, int64 ttl_timestamp_software, int64 ttl_timestamp_hardware, int samplePosition );
-	void dumpStartStopRecordEventToDisk(int64 ts, bool startRecord);
-//	void dumpEyeTrackingEventToDisk(EyePosition pos);
-
 	bool isRecording;
     int displayBufferSize;
     bool redrawRequested;
@@ -109,8 +98,9 @@ private:
 
 	std::queue<StringTS> networkEventsHistory;
     RecordNode* recordNode;
-    uint16 recordingNumber;
+//    uint16 recordingNumber;
     CriticalSection diskWriteLock;
+	Array<Channel*> electrodeChannels;
 
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PeriStimulusTimeHistogramNode);
 
diff --git a/Source/Processors/SpikeDetector/SpikeDetector.cpp b/Source/Processors/SpikeDetector/SpikeDetector.cpp
index bc53a8b64a8f9ff558ba1b14de3f3f69e396f1e2..c51bbc4dccc531794c8a84b3fbcf5b93cc8bd8c5 100755
--- a/Source/Processors/SpikeDetector/SpikeDetector.cpp
+++ b/Source/Processors/SpikeDetector/SpikeDetector.cpp
@@ -88,21 +88,10 @@ void SpikeDetector::updateSettings()
     for (int i = 0; i < electrodes.size(); i++)
     {
 
-        Channel* ch;
-
-        switch (electrodes[i]->numChannels)
-        {
-            case 1:
-                ch = new Channel(this, i, SINGLE_ELECTRODE);
-                break;
-            case 2:
-                ch = new Channel(this, i, STEREOTRODE);
-                break;
-            case 4:
-                ch = new Channel(this, i, TETRODE);
-                break;
-        }
-
+        Channel* ch = new Channel(this,i,ELECTRODE_CHANNEL);
+		ch->name = generateSpikeElectrodeName(electrodes[i]->numChannels, ch->index);
+		SpikeChannel* spk = new SpikeChannel(SpikeChannel::Plain, electrodes[i]->numChannels, NULL, 0);
+		ch->extraData = spk;
         eventChannels.add(ch);
     }
 
diff --git a/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.cpp b/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.cpp
index fa1c2f702f5173f36be76fe578f0b6290e78d9c1..7b0253be6e2a5a606e506f0dd098103ef350336b 100755
--- a/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.cpp
+++ b/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.cpp
@@ -60,24 +60,12 @@ void SpikeDisplayNode::updateSettings()
     {
         ChannelType type = eventChannels[i]->getType();
 
-        if (type == SINGLE_ELECTRODE || type == STEREOTRODE || type == TETRODE)
+        if (type == ELECTRODE_CHANNEL)
         {
 
             Electrode elec;
+			elec.numChannels = static_cast<SpikeChannel*>(eventChannels[i]->extraData.get())->numChannels;
 
-            switch (type)
-            {
-                case SINGLE_ELECTRODE:
-                    elec.numChannels = 1;
-                    break;
-                case STEREOTRODE:
-                    elec.numChannels = 2;
-                    break;
-                case TETRODE:
-                    elec.numChannels = 4;
-                    break;
-            }
-            
             elec.name = eventChannels[i]->getName();
             elec.currentSpikeIndex = 0;
             elec.mostRecentSpikes.ensureStorageAllocated(displayBufferSize);
diff --git a/Source/Processors/SpikeSorter/SpikeSorter.cpp b/Source/Processors/SpikeSorter/SpikeSorter.cpp
index 0eab93df0bbb9bc089fd0b6bcb3a8f36c6150a85..58b284e79e56e66dbba1947538095cd498a0a19b 100644
--- a/Source/Processors/SpikeSorter/SpikeSorter.cpp
+++ b/Source/Processors/SpikeSorter/SpikeSorter.cpp
@@ -192,20 +192,10 @@ void SpikeSorter::updateSettings()
     for (int i = 0; i < electrodes.size(); i++)
     {
 
-        Channel* ch;
-
-        switch (electrodes[i]->numChannels)
-        {
-            case 1:
-                ch = new Channel(this, i, SINGLE_ELECTRODE);
-                break;
-            case 2:
-                ch = new Channel(this, i, STEREOTRODE);
-                break;
-            case 4:
-                ch = new Channel(this, i, TETRODE);
-                break;
-        }
+        Channel* ch = new Channel(this,i,ELECTRODE_CHANNEL);
+		ch->name = generateSpikeElectrodeName(electrodes[i]->numChannels, ch->index);
+		SpikeChannel* spk = new SpikeChannel(SpikeChannel::Sorted, electrodes[i]->numChannels, electrodes[i], sizeof(Electrode));
+		ch->extraData = spk;
 
         eventChannels.add(ch);
     }
diff --git a/Source/Processors/Visualization/SpikeObject.cpp b/Source/Processors/Visualization/SpikeObject.cpp
index 702b9cc53a4b1754aa331bfe3420261ed66e93b8..ce61eb9ba80c350afa20e0a361843fdb26d9fd09 100755
--- a/Source/Processors/Visualization/SpikeObject.cpp
+++ b/Source/Processors/Visualization/SpikeObject.cpp
@@ -400,3 +400,28 @@ int microSecondsToSpikeTimeBin(SpikeObject *s, float t, int ch)
 }
 
 
+SpikeChannel::SpikeChannel(SpikeDataType type, int nChans, void* ptr, int size)
+	: dataType(type), numChannels(nChans), ChannelExtraData(ptr, size)
+{
+}
+
+String generateSpikeElectrodeName(int numChannels, int index)
+{
+	String name;
+	switch (numChannels)
+	{
+	case 1:
+		name = String("SE");
+		break;
+	case 2:
+		name = String("ST");
+		break;
+	case 4:
+		name = String("TT");
+		break;
+	default:
+		name = String("ELEC");
+		break;
+	}
+	return name + String(index);
+}
\ No newline at end of file
diff --git a/Source/Processors/Visualization/SpikeObject.h b/Source/Processors/Visualization/SpikeObject.h
index a386ee0ef097f0c557f559a68b3a2eb64dac16a6..c3a06c0736c2e3e50c2f8808dadd4dc81a72ef38 100755
--- a/Source/Processors/Visualization/SpikeObject.h
+++ b/Source/Processors/Visualization/SpikeObject.h
@@ -29,6 +29,8 @@
 #include <stdint.h>
 #include <math.h>
 
+#include "../Channel/Channel.h"
+
 #define SPIKE_METADATA_SIZE 42
 #define MAX_NUMBER_OF_SPIKE_CHANNELS 4
 #define MAX_NUMBER_OF_SPIKE_CHANNEL_SAMPLES 80
@@ -37,6 +39,21 @@
 #define MAX_SPIKE_BUFFER_LEN 512 // max length of spike buffer in bytes
                                  // the true max calculated from the spike values below is actually 507
 
+/** Class to store spike data in event channels */
+class SpikeChannel : public ChannelExtraData
+{
+public:
+	enum SpikeDataType { Plain = 0, Sorted = 1};
+
+	SpikeChannel(SpikeDataType type, int nChans, void* ptr, int size);
+
+	const SpikeDataType dataType;
+	const int numChannels;
+};
+
+/** Simple generic function to name spike electrode channels */
+String generateSpikeElectrodeName(int numChannels, int index);
+
 #define SPIKE_BASE_CODE 100
 
 /**