diff --git a/Source/Plugins/KWIKFormat/RecordEngine/HDF5FileFormat.cpp b/Source/Plugins/KWIKFormat/RecordEngine/HDF5FileFormat.cpp
index a5de05f574b2d3a36077d9addca0ba5054630956..e2c449ba0dcce59f245854c6d5333fa82b8989cc 100644
--- a/Source/Plugins/KWIKFormat/RecordEngine/HDF5FileFormat.cpp
+++ b/Source/Plugins/KWIKFormat/RecordEngine/HDF5FileFormat.cpp
@@ -40,6 +40,10 @@
 #define SPIKE_CHUNK_YSIZE 40
 #endif
 
+#ifndef TIMESTAMP_CHUNK_SIZE
+#define TIMESTAMP_CHUNK_SIZE 4
+#endif
+
 #define MAX_TRANSFORM_SIZE 512
 
 #define MAX_STR_SIZE 256
@@ -675,13 +679,21 @@ void KWDFile::startNewRecording(int recordingNumber, int nChannels, HDF5Recordin
     CHECK_ERROR(createGroup(recordPath+"/application_data"));
    // CHECK_ERROR(setAttributeArray(F32,info->bitVolts.getRawDataPointer(),info->bitVolts.size(),recordPath+"/application_data",String("channel_bit_volts")));
 	bitVoltsSet = createDataSet(F32, info->bitVolts.size(), 0, recordPath + "/application_data/channel_bit_volts");
-	bitVoltsSet->writeDataBlock(info->bitVolts.size(), F32, info->bitVolts.getRawDataPointer());
+	if (bitVoltsSet.get())
+		bitVoltsSet->writeDataBlock(info->bitVolts.size(), F32, info->bitVolts.getRawDataPointer());
+	else
+		std::cerr << "Error creating bitvolts data set" << std::endl;
 	
     CHECK_ERROR(setAttribute(U8,&mSample,recordPath+"/application_data",String("is_multiSampleRate_data")));
     CHECK_ERROR(setAttributeArray(F32,info->channelSampleRates.getRawDataPointer(),info->channelSampleRates.size(),recordPath+"/application_data",String("channel_sample_rates")));
     recdata = createDataSet(I16,0,nChannels,CHUNK_XSIZE,recordPath+"/data");
     if (!recdata.get())
         std::cerr << "Error creating data set" << std::endl;
+
+	tsData = createDataSet(I64, 0, nChannels, TIMESTAMP_CHUNK_SIZE, recordPath + "/application_data/timestamps");
+	if (!tsData.get())
+		std::cerr << "Error creating timestamps data set" << std::endl;
+
     curChan = nChannels;
 }
 
@@ -694,6 +706,7 @@ void KWDFile::stopRecording()
     CHECK_ERROR(setAttributeArray(U32,samples.getRawDataPointer(),samples.size(),path,"valid_samples"));
     //ScopedPointer does the deletion and destructors the closings
     recdata = nullptr;
+	tsData = nullptr;
 }
 
 int KWDFile::createFileStructure()
@@ -728,6 +741,14 @@ void KWDFile::writeRowData(int16* data, int nSamples, int channel)
 	}
 }
 
+void KWDFile::writeTimestamps(int64* ts, int nTs, int channel)
+{
+	if (channel >= 0 && channel < nChannels)
+	{
+		CHECK_ERROR(tsData->writeDataRow(channel, nTs, I64, ts));
+	}
+}
+
 //KWE File
 
 KWEFile::KWEFile(String basename) : HDF5FileBase()
diff --git a/Source/Plugins/KWIKFormat/RecordEngine/HDF5FileFormat.h b/Source/Plugins/KWIKFormat/RecordEngine/HDF5FileFormat.h
index ca0f190f349f0ebfd422f8d91bf002220bd35095..f98748373b7f5be85f8e8e5604c0396a72c9c41f 100644
--- a/Source/Plugins/KWIKFormat/RecordEngine/HDF5FileFormat.h
+++ b/Source/Plugins/KWIKFormat/RecordEngine/HDF5FileFormat.h
@@ -128,6 +128,7 @@ public:
     void writeBlockData(int16* data, int nSamples);
     void writeRowData(int16* data, int nSamples);
 	void writeRowData(int16* data, int nSamples, int channel);
+	void writeTimestamps(int64* ts, int nTs, int channel);
     String getFileName();
 
 protected:
@@ -140,6 +141,7 @@ private:
     String filename;
     bool multiSample;
     ScopedPointer<HDF5RecordingData> recdata;
+	ScopedPointer<HDF5RecordingData> tsData;
 
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(KWDFile);
 };
diff --git a/Source/Plugins/KWIKFormat/RecordEngine/HDF5Recording.cpp b/Source/Plugins/KWIKFormat/RecordEngine/HDF5Recording.cpp
index 3806adcccf3df29f69ba1aaad7813d1c92ca7319..c5d545c4e01c68e461b69cf7c2e7485ef169bc4d 100644
--- a/Source/Plugins/KWIKFormat/RecordEngine/HDF5Recording.cpp
+++ b/Source/Plugins/KWIKFormat/RecordEngine/HDF5Recording.cpp
@@ -23,6 +23,8 @@
 
 #include "HDF5Recording.h"
 #define MAX_BUFFER_SIZE 10000
+#define CHANNEL_TIMESTAMP_PREALLOC_SIZE 16
+#define TIMESTAMP_EACH_NSAMPLES 1024
 
 HDF5Recording::HDF5Recording() : processorIndex(-1), hasAcquired(false)
 {
@@ -37,7 +39,7 @@ HDF5Recording::~HDF5Recording()
     delete intBuffer;
 }
 
-String HDF5Recording::getEngineID()
+String HDF5Recording::getEngineID() const
 {
     return "KWIK";
 }
@@ -73,6 +75,8 @@ void HDF5Recording::resetChannels()
     processorMap.clear();
     infoArray.clear();
 	recordedChanToKWDChan.clear();
+	channelLeftOverSamples.clear();
+	channelTimestampArray.clear();
     if (spikesFile)
         spikesFile->resetChannels();
 }
@@ -129,31 +133,11 @@ void HDF5Recording::openFiles(File rootFolder, int experimentNumber, int recordi
 		int procPos = processorRecPos[index];
 		recordedChanToKWDChan.add(procPos);
 		processorRecPos.set(index, procPos+1);
+		channelTimestampArray.add(new Array<int64>);
+		channelTimestampArray.getLast()->ensureStorageAllocated(CHANNEL_TIMESTAMP_PREALLOC_SIZE);
+		channelLeftOverSamples.add(0);
 	} 
-#if 0
-    for (int i = 0; i < processorMap.size(); i++)
-    {
-        int index = processorMap[i];
-        if (getChannel(i)->getRecordState())
-        {
-			if (!fileArray[index]->isOpen())
-            {
-                fileArray[index]->initFile(getChannel(i)->nodeId,basepath);
-                if (hasAcquired)
-                    infoArray[index]->start_time = (*timestamps)[getChannel(i)->sourceNodeId]; //the timestamps of the first channel
-                else
-                    infoArray[index]->start_time = 0;
-            }
-			channelsPerProcessor.set(index, channelsPerProcessor[index] + 1);
-            bitVoltsArray[index]->add(getChannel(i)->bitVolts);
-            sampleRatesArray[index]->add(getChannel(i)->sampleRate);
-            if (getChannel(i)->sampleRate != infoArray[index]->sample_rate)
-            {
-                infoArray[index]->multiSample = true;
-            }
-        }
-    }
-#endif
+
     for (int i = 0; i < fileArray.size(); i++)
     {
 		if ((!fileArray[i]->isOpen()) && (fileArray[i]->isReadyToOpen()))
@@ -196,6 +180,18 @@ void HDF5Recording::closeFiles()
         }
 		channelsPerProcessor.set(i, 0);
     }
+	recordedChanToKWDChan.clear();
+	channelTimestampArray.clear();
+	channelLeftOverSamples.clear();
+}
+
+void HDF5Recording::startChannelBlock()
+{
+	int nCh = channelTimestampArray.size();
+	for (int i = 0; i < nCh; ++i)
+	{
+		channelTimestampArray[i]->clearQuick();
+	}
 }
 
 void HDF5Recording::writeData(int writeChannel, int realChannel, const float* buffer, int size)
@@ -208,6 +204,48 @@ void HDF5Recording::writeData(int writeChannel, int realChannel, const float* bu
 	fileArray[index]->writeRowData(intBuffer, size, recordedChanToKWDChan[writeChannel]);
 //	int64 t2 = Time::getHighResolutionTicks();
 //	std::cout << "record time: " << float(t2 - t1) / float(Time::getHighResolutionTicksPerSecond()) << std::endl;
+	int64 sampleOffset = channelLeftOverSamples[writeChannel];
+	if (writeChannel == 0)
+		std::cout << "Write " << size << " off " << sampleOffset << " ts " << getTimestamp(realChannel) << " - ";
+	if (sampleOffset + size >= TIMESTAMP_EACH_NSAMPLES)
+	{
+		int64 currentTimestamp = getTimestamp(realChannel);
+		if (sampleOffset > 0)
+		{
+			currentTimestamp = getTimestamp(realChannel) + TIMESTAMP_EACH_NSAMPLES - sampleOffset;
+		}
+
+		for (int samp = 0; samp < size; samp += TIMESTAMP_EACH_NSAMPLES)
+		{
+			if (writeChannel == 0)
+				std::cout << "w: " << currentTimestamp << " ";
+			channelTimestampArray[writeChannel]->add(currentTimestamp);
+			currentTimestamp += TIMESTAMP_EACH_NSAMPLES;
+		}
+
+		channelLeftOverSamples.set(writeChannel, (size + sampleOffset) % TIMESTAMP_EACH_NSAMPLES);
+	}
+	else
+	{
+		channelLeftOverSamples.set(writeChannel, sampleOffset + size);
+	}
+	if (writeChannel == 0)
+		std::cout << std::endl;
+}
+
+void HDF5Recording::endChannelBlock()
+{
+	int nCh = channelTimestampArray.size();
+	for (int ch = 0; ch < nCh; ++ch)
+	{
+		int tsSize = channelTimestampArray[ch]->size();
+		if (tsSize > 0)
+		{
+			int realChan = getRealChannel(ch);
+			int index = processorMap[getChannel(realChan)->recordIndex];
+			fileArray[index]->writeTimestamps(channelTimestampArray[ch]->getRawDataPointer(), tsSize, ch);
+		}
+	}
 }
 
 void HDF5Recording::writeEvent(int eventType, const MidiMessage& event, int64 timestamp)
diff --git a/Source/Plugins/KWIKFormat/RecordEngine/HDF5Recording.h b/Source/Plugins/KWIKFormat/RecordEngine/HDF5Recording.h
index a40f5f1e903885975d74fe3d9cf878951e473562..cc0ac27b954afd80499fe7addf72c54e8bc30dbc 100644
--- a/Source/Plugins/KWIKFormat/RecordEngine/HDF5Recording.h
+++ b/Source/Plugins/KWIKFormat/RecordEngine/HDF5Recording.h
@@ -32,7 +32,7 @@ class HDF5Recording : public RecordEngine
 public:
     HDF5Recording();
     ~HDF5Recording();
-    String getEngineID();
+    String getEngineID() const override;
     void openFiles(File rootFolder, int experimentNumber, int recordingNumber) override;
 	void closeFiles() override;
 	void writeData(int writeChannel, int realChannel, const float* buffer, int size) override;
@@ -43,6 +43,8 @@ public:
 	void registerProcessor(const GenericProcessor* processor) override;
 	void resetChannels() override;
 	void startAcquisition() override;
+	void startChannelBlock() override;
+	void endChannelBlock() override;
 
     static RecordEngineManager* getEngineManager();
 private:
@@ -54,6 +56,8 @@ private:
 	Array<int> recordedChanToKWDChan;
     OwnedArray<Array<float>> bitVoltsArray;
     OwnedArray<Array<float>> sampleRatesArray;
+	OwnedArray<Array<int64>> channelTimestampArray;
+	Array<int> channelLeftOverSamples;
     OwnedArray<KWDFile> fileArray;
     OwnedArray<HDF5RecordingInfo> infoArray;
     ScopedPointer<KWEFile> eventFile;
diff --git a/Source/Processors/RecordNode/OriginalRecording.cpp b/Source/Processors/RecordNode/OriginalRecording.cpp
index 5205d144e8cf5b6a8f374f4e007352fd6149b036..7e5aab4d8ce661367b50162f9df89e057cfce445 100644
--- a/Source/Processors/RecordNode/OriginalRecording.cpp
+++ b/Source/Processors/RecordNode/OriginalRecording.cpp
@@ -62,7 +62,7 @@ OriginalRecording::~OriginalRecording()
     delete recordMarker;*/
 }
 
-String OriginalRecording::getEngineID()
+String OriginalRecording::getEngineID() const
 {
     return "OPENEPHYS";
 }
diff --git a/Source/Processors/RecordNode/OriginalRecording.h b/Source/Processors/RecordNode/OriginalRecording.h
index 8a7e7dd3f887630eae1c3bdac922dbe465ac6bf7..0aa252e12963ee5f870a8fbe939682fa0f5e1dfd 100644
--- a/Source/Processors/RecordNode/OriginalRecording.h
+++ b/Source/Processors/RecordNode/OriginalRecording.h
@@ -45,7 +45,7 @@ public:
     ~OriginalRecording();
 
     void setParameter(EngineParameter& parameter);
-    String getEngineID();
+    String getEngineID() const override;
     void openFiles(File rootFolder, int experimentNumber, int recordingNumber) override;
 	void closeFiles() override;
 	void writeData(int writeChannel, int realChannel, const float* buffer, int size) override;
diff --git a/Source/Processors/RecordNode/RecordEngine.h b/Source/Processors/RecordNode/RecordEngine.h
index 1be3109c18fafb9cde4531d57704f87fc0bae889..a222713512283a833ee9684af7cf616207ad3da7 100644
--- a/Source/Processors/RecordNode/RecordEngine.h
+++ b/Source/Processors/RecordNode/RecordEngine.h
@@ -59,7 +59,7 @@ class PLUGIN_API RecordEngine
 public:
     RecordEngine();
     virtual ~RecordEngine();
-    virtual String getEngineID() =0;
+    virtual String getEngineID() const =0;
 
     /** All the public methods (except registerManager) are called by RecordNode or RecordingThread:
     When acquisition starts (in the specified order):