diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile
index 656eae35e93b946cafe53646a6345519d3cc5d37..b5ecbffed88b8f7aeeca4aff25715102b9398489 100644
--- a/Builds/Linux/Makefile
+++ b/Builds/Linux/Makefile
@@ -18,12 +18,12 @@ ifeq ($(CONFIG),Debug)
     TARGET_ARCH := -march=native
   endif
 
-  CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.3" -D "JUCE_APP_VERSION_HEX=0x303" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules
+  CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.4" -D "JUCE_APP_VERSION_HEX=0x304" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules
   CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O3 -export-dynamic -g -pg -std=c++0x
   CXXFLAGS += $(CFLAGS)
   LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -L/usr/X11R6/lib/ -L/usr/local/include -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt -pg -ldl -lXext -lGLU -lhdf5 -lhdf5_cpp
   LDDEPS :=
-  RESFLAGS :=  -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.3" -D "JUCE_APP_VERSION_HEX=0x303" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules
+  RESFLAGS :=  -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.4" -D "JUCE_APP_VERSION_HEX=0x304" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules
   TARGET := open-ephys
   BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
   CLEANCMD = rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
@@ -39,12 +39,12 @@ ifeq ($(CONFIG),Release)
     TARGET_ARCH := -march=native
   endif
 
-  CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.3" -D "JUCE_APP_VERSION_HEX=0x303" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules
+  CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.4" -D "JUCE_APP_VERSION_HEX=0x304" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules
   CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O3 -export-dynamic -g -pg -std=c++0x
   CXXFLAGS += $(CFLAGS)
   LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -fvisibility=hidden -L/usr/X11R6/lib/ -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt -pg -ldl -lXext -lGLU -lhdf5 -lhdf5_cpp
   LDDEPS :=
-  RESFLAGS :=  -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.3" -D "JUCE_APP_VERSION_HEX=0x303" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules
+  RESFLAGS :=  -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.4" -D "JUCE_APP_VERSION_HEX=0x304" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules
   TARGET := open-ephys-release
   BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
   CLEANCMD = rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR)
@@ -58,7 +58,6 @@ OBJECTS := \
   $(OBJDIR)/ArduinoOutputEditor_e1b7e52b.o \
   $(OBJDIR)/AudioEditor_3931be27.o \
   $(OBJDIR)/AudioNode_3db3557c.o \
-  $(OBJDIR)/AudioResamplingNode_bdba71b0.o \
   $(OBJDIR)/Channel_5cb2d4d2.o \
   $(OBJDIR)/ChannelMappingEditor_9b145f15.o \
   $(OBJDIR)/ChannelMappingNode_ec0559ea.o \
@@ -70,8 +69,6 @@ OBJECTS := \
   $(OBJDIR)/rhd2000evalboard_e0b412d5.o \
   $(OBJDIR)/rhd2000registers_cf6cd63b.o \
   $(OBJDIR)/RHD2000Thread_23e0b041.o \
-  $(OBJDIR)/FileReaderThread_933ea08.o \
-  $(OBJDIR)/FPGAThread_a8dc34ed.o \
   $(OBJDIR)/DataBuffer_6ae4f549.o \
   $(OBJDIR)/DataThread_b2a47a13.o \
   $(OBJDIR)/Bessel_7e54cb27.o \
@@ -107,15 +104,10 @@ OBJECTS := \
   $(OBJDIR)/FileReaderEditor_e1193ff7.o \
   $(OBJDIR)/FilterEditor_93e366f5.o \
   $(OBJDIR)/FilterNode_d2b4d9ca.o \
-  $(OBJDIR)/FPGAOutput_9ccd34ea.o \
-  $(OBJDIR)/FPGAOutputEditor_749d7837.o \
   $(OBJDIR)/GenericProcessor_3e79932a.o \
   $(OBJDIR)/LfpDisplayCanvas_9bbf9660.o \
   $(OBJDIR)/LfpDisplayEditor_e7c32ff5.o \
   $(OBJDIR)/LfpDisplayNode_fdf2e2ca.o \
-  $(OBJDIR)/LfpTriggeredAverageCanvas_5ba95b5e.o \
-  $(OBJDIR)/LfpTriggeredAverageEditor_a7acf4f3.o \
-  $(OBJDIR)/LfpTriggeredAverageNode_2ee5cf48.o \
   $(OBJDIR)/Merger_53fb4e4a.o \
   $(OBJDIR)/MergerEditor_e36b0997.o \
   $(OBJDIR)/MessageCenter_bd1ba084.o \
@@ -139,8 +131,6 @@ OBJECTS := \
   $(OBJDIR)/PeriStimulusTimeHistogramNode_9631ca2a.o \
   $(OBJDIR)/tictoc_cdca1ed.o \
   $(OBJDIR)/TrialCircularBuffer_4a4cef0c.o \
-  $(OBJDIR)/ReferenceNode_97454f26.o \
-  $(OBJDIR)/ReferenceNodeEditor_7d0ff573.o \
   $(OBJDIR)/ResamplingNode_9825590a.o \
   $(OBJDIR)/ResamplingNodeEditor_8b120457.o \
   $(OBJDIR)/PulsePal_14932a18.o \
@@ -166,8 +156,6 @@ OBJECTS := \
   $(OBJDIR)/DataWindow_83ce6754.o \
   $(OBJDIR)/SpikeObject_24e8c655.o \
   $(OBJDIR)/MatlabLikePlot_fb09c37f.o \
-  $(OBJDIR)/WiFiOutput_416d244a.o \
-  $(OBJDIR)/WiFiOutputEditor_ada45f97.o \
   $(OBJDIR)/EcubeDialogComponent_2ec3bd57.o \
   $(OBJDIR)/CustomArrowButton_206e4278.o \
   $(OBJDIR)/GraphViewer_e43fd2ce.o \
@@ -250,11 +238,6 @@ $(OBJDIR)/AudioNode_3db3557c.o: ../../Source/Processors/AudioNode/AudioNode.cpp
 	@echo "Compiling AudioNode.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
-$(OBJDIR)/AudioResamplingNode_bdba71b0.o: ../../Source/Processors/AudioResamplingNode/AudioResamplingNode.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling AudioResamplingNode.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
 $(OBJDIR)/Channel_5cb2d4d2.o: ../../Source/Processors/Channel/Channel.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling Channel.cpp"
@@ -310,16 +293,6 @@ $(OBJDIR)/RHD2000Thread_23e0b041.o: ../../Source/Processors/DataThreads/RHD2000T
 	@echo "Compiling RHD2000Thread.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
-$(OBJDIR)/FileReaderThread_933ea08.o: ../../Source/Processors/DataThreads/FileReaderThread.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling FileReaderThread.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
-$(OBJDIR)/FPGAThread_a8dc34ed.o: ../../Source/Processors/DataThreads/FPGAThread.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling FPGAThread.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
 $(OBJDIR)/DataBuffer_6ae4f549.o: ../../Source/Processors/DataThreads/DataBuffer.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling DataBuffer.cpp"
@@ -495,16 +468,6 @@ $(OBJDIR)/FilterNode_d2b4d9ca.o: ../../Source/Processors/FilterNode/FilterNode.c
 	@echo "Compiling FilterNode.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
-$(OBJDIR)/FPGAOutput_9ccd34ea.o: ../../Source/Processors/FPGAOutput/FPGAOutput.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling FPGAOutput.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
-$(OBJDIR)/FPGAOutputEditor_749d7837.o: ../../Source/Processors/FPGAOutput/FPGAOutputEditor.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling FPGAOutputEditor.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
 $(OBJDIR)/GenericProcessor_3e79932a.o: ../../Source/Processors/GenericProcessor/GenericProcessor.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling GenericProcessor.cpp"
@@ -525,21 +488,6 @@ $(OBJDIR)/LfpDisplayNode_fdf2e2ca.o: ../../Source/Processors/LfpDisplayNode/LfpD
 	@echo "Compiling LfpDisplayNode.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
-$(OBJDIR)/LfpTriggeredAverageCanvas_5ba95b5e.o: ../../Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageCanvas.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling LfpTriggeredAverageCanvas.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
-$(OBJDIR)/LfpTriggeredAverageEditor_a7acf4f3.o: ../../Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageEditor.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling LfpTriggeredAverageEditor.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
-$(OBJDIR)/LfpTriggeredAverageNode_2ee5cf48.o: ../../Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling LfpTriggeredAverageNode.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
 $(OBJDIR)/Merger_53fb4e4a.o: ../../Source/Processors/Merger/Merger.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling Merger.cpp"
@@ -655,16 +603,6 @@ $(OBJDIR)/TrialCircularBuffer_4a4cef0c.o: ../../Source/Processors/PSTH/TrialCirc
 	@echo "Compiling TrialCircularBuffer.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
-$(OBJDIR)/ReferenceNode_97454f26.o: ../../Source/Processors/ReferenceNode/ReferenceNode.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling ReferenceNode.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
-$(OBJDIR)/ReferenceNodeEditor_7d0ff573.o: ../../Source/Processors/ReferenceNode/ReferenceNodeEditor.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling ReferenceNodeEditor.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
 $(OBJDIR)/ResamplingNode_9825590a.o: ../../Source/Processors/ResamplingNode/ResamplingNode.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling ResamplingNode.cpp"
@@ -790,16 +728,6 @@ $(OBJDIR)/MatlabLikePlot_fb09c37f.o: ../../Source/Processors/Visualization/Matla
 	@echo "Compiling MatlabLikePlot.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
-$(OBJDIR)/WiFiOutput_416d244a.o: ../../Source/Processors/WiFiOutput/WiFiOutput.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling WiFiOutput.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
-$(OBJDIR)/WiFiOutputEditor_ada45f97.o: ../../Source/Processors/WiFiOutput/WiFiOutputEditor.cpp
-	-@mkdir -p $(OBJDIR)
-	@echo "Compiling WiFiOutputEditor.cpp"
-	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
-
 $(OBJDIR)/EcubeDialogComponent_2ec3bd57.o: ../../Source/UI/EcubeDialogComponent.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling EcubeDialogComponent.cpp"
diff --git a/Builds/MacOSX/Info.plist b/Builds/MacOSX/Info.plist
index 5db847465d67cce80fe1330283aca27cb95a772a..c9fa38de1f2a137aee04e5040b8fd9e1ee9b2980 100644
--- a/Builds/MacOSX/Info.plist
+++ b/Builds/MacOSX/Info.plist
@@ -16,9 +16,9 @@
     <key>CFBundleSignature</key>
     <string>????</string>
     <key>CFBundleShortVersionString</key>
-    <string>0.3.3</string>
+    <string>0.3.4</string>
     <key>CFBundleVersion</key>
-    <string>0.3.3</string>
+    <string>0.3.4</string>
     <key>NSHumanReadableCopyright</key>
     <string>Open Ephys</string>
     <key>NSHighResolutionCapable</key>
diff --git a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
index 14c951fc1ab6172abf13715164f2efb1117c75d5..67ceb869433dc3be1e29c8c791c48fcd5c619ed2 100644
--- a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
+++ b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
@@ -28,7 +28,6 @@
 		527EB48A4A9C2F4FF1BC4FB2 = {isa = PBXBuildFile; fileRef = E850C14F13F9855CE1E14C1A; };
 		8352817FEDC7542D3E65B49A = {isa = PBXBuildFile; fileRef = DA4EAC64A750D0C3DEE83C5D; };
 		44DB81313BDDF1ECB6AD33FE = {isa = PBXBuildFile; fileRef = 1F22CC8D992B8B49D57DDB3F; };
-		64FC0EA0C132341C1C3E98E1 = {isa = PBXBuildFile; fileRef = 41E88094E8D929866A6DCA9A; };
 		C45009DBCD71E9E234BFCE97 = {isa = PBXBuildFile; fileRef = FA8CC6FD54A9F20DA755F2EA; };
 		E6038800731F7C747D181A51 = {isa = PBXBuildFile; fileRef = D0105584D551FED59203CC84; };
 		FFCA1C44C024BCA1878F49FE = {isa = PBXBuildFile; fileRef = 25CEC111DFEC71FA6828257F; };
@@ -40,8 +39,6 @@
 		DA836EC803E4FF4EDEBE6386 = {isa = PBXBuildFile; fileRef = 2D2BAC4320470CF68743F58E; };
 		702C9BFCE865CB6C6B8BFB0D = {isa = PBXBuildFile; fileRef = 5DB3B3197F8C1E5EE159D6FC; };
 		739573501D1D440A72C5C2E5 = {isa = PBXBuildFile; fileRef = A3FB0EA0264580F6B00D993B; };
-		955561F4FF4484648FDB9F73 = {isa = PBXBuildFile; fileRef = 1718EC50691D8421EC00F8B3; };
-		6B67D7B6301182C7621294B6 = {isa = PBXBuildFile; fileRef = FA23A1334E4CFA77BC18A153; };
 		FAE745870674A07A65690433 = {isa = PBXBuildFile; fileRef = 788F8B7719B70465762B634B; };
 		24CC7E9A7E87F762D4AB0467 = {isa = PBXBuildFile; fileRef = 92602D7166325C7232B85EDD; };
 		9252537C12447F047243DEE9 = {isa = PBXBuildFile; fileRef = 041038F6E67FE0409D8ECC74; };
@@ -77,15 +74,10 @@
 		24800AF87AD21CE652552EDE = {isa = PBXBuildFile; fileRef = 56F810EF10E01535A417B671; };
 		0203D029CE7420984F737E51 = {isa = PBXBuildFile; fileRef = 414969AEF838522C9FE1B807; };
 		3BAE3A1FD0834E798B8602BF = {isa = PBXBuildFile; fileRef = 9AA19ECEFE2B49832ECEED2F; };
-		1A415CE073017DDDA7F2E234 = {isa = PBXBuildFile; fileRef = 4448875C40EAB061B2F8A289; };
-		63B3CC385B0988C7ABA3B07B = {isa = PBXBuildFile; fileRef = AB4D72F040FF59BED08826EC; };
 		B49852F77C0C392C159A1914 = {isa = PBXBuildFile; fileRef = C5654EAA7B65445CF1340983; };
 		9F431DA23C92CA0F8E3A2A28 = {isa = PBXBuildFile; fileRef = D9BF6DA66C22FFF5C4D41991; };
 		BFFD23BD72ECEC9E54936061 = {isa = PBXBuildFile; fileRef = 88C69F0563A99BD2F7BF5FBB; };
 		FA882EEE408CBBDC7BD90F14 = {isa = PBXBuildFile; fileRef = 1C64C490BD7FE9E57D6C682D; };
-		0E62780F9978861D5D2BCF71 = {isa = PBXBuildFile; fileRef = CC9134D38EBEC67112CA7502; };
-		E13848868678C0655147C59D = {isa = PBXBuildFile; fileRef = 20DBF92457AF75C0698D1B26; };
-		01646F263C203BB412580CB8 = {isa = PBXBuildFile; fileRef = FA12F07F4F9C872C18A2817B; };
 		6D00BABD3FE1AA0EAA267C1C = {isa = PBXBuildFile; fileRef = 07B84F46CF90D04BB6B673C5; };
 		AD371C6F383F03EF392B6581 = {isa = PBXBuildFile; fileRef = BAA5B3AD1A27F8C4D37A6869; };
 		4EF2825142BBAA76FD55FE26 = {isa = PBXBuildFile; fileRef = BC1543B1F822FEEDCB9AC26D; };
@@ -109,8 +101,6 @@
 		093F0BA37D6C91C7E92AB658 = {isa = PBXBuildFile; fileRef = 25B9B8D5E54B9C547197E414; };
 		620CF6292EFB911F15916EA6 = {isa = PBXBuildFile; fileRef = 547C76794FAC1BC349163509; };
 		7B50AD44D4F9610CE4A43414 = {isa = PBXBuildFile; fileRef = FB827FEEA15A274E5F7577DB; };
-		A5A90525A975EC3B1E40086E = {isa = PBXBuildFile; fileRef = D9B10885C9D93CEF580EF167; };
-		79FC643530710BF2885932C1 = {isa = PBXBuildFile; fileRef = 6D4D435D25CFC019E0FCF4A1; };
 		69B5045877D4C674E8A4967F = {isa = PBXBuildFile; fileRef = E102C308B0722DFFFEFF2415; };
 		97105BCBC5B1BE4E86D48899 = {isa = PBXBuildFile; fileRef = 55DFE30C901793E56A7E3A22; };
 		790911EDF00A4BF77327D99A = {isa = PBXBuildFile; fileRef = 48E12736F471C43C959AD15C; };
@@ -136,8 +126,6 @@
 		1B620FC17AAECA4C5DE741E2 = {isa = PBXBuildFile; fileRef = 66463AB11EA4D6341C32F27E; };
 		19BB86C918F89D1377F8A0E1 = {isa = PBXBuildFile; fileRef = 5894D40A0E8FA6E9B3EBF9D9; };
 		89223664B6CB2A912E36B091 = {isa = PBXBuildFile; fileRef = F115ED75E977A54AAF036B2C; };
-		AEE1F2B70ED51F7AFEF4E93B = {isa = PBXBuildFile; fileRef = B25949076F9BB831C5862415; };
-		74D0CA6935D890153FB58C56 = {isa = PBXBuildFile; fileRef = 3734FF118787377E4C8741D1; };
 		8F39AD3F7938EFE82D06E89F = {isa = PBXBuildFile; fileRef = AF28CAB9C7531EF7422602E1; };
 		BA608CEFC85F7AB9E30E0EB3 = {isa = PBXBuildFile; fileRef = F960CC94B136201BDA148EEA; };
 		D499273B65D901D0A101CAAA = {isa = PBXBuildFile; fileRef = E5C1D021C0FD6FAD082C5D75; };
@@ -194,7 +182,6 @@
 		06072EC6BCD3B7D8C17C2402 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioProcessor.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp"; sourceTree = "SOURCE_ROOT"; };
 		078625CF5C083AD538D23401 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioCDReader.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.cpp"; sourceTree = "SOURCE_ROOT"; };
 		0790CCE2FCFDFA6944DFC402 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PopupMenu.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.cpp"; sourceTree = "SOURCE_ROOT"; };
-		07A8ED74417654C40F9EFEFC = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FPGAOutput.h; path = ../../Source/Processors/FPGAOutput/FPGAOutput.h; sourceTree = "SOURCE_ROOT"; };
 		07B84F46CF90D04BB6B673C5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Merger.cpp; path = ../../Source/Processors/Merger/Merger.cpp; sourceTree = "SOURCE_ROOT"; };
 		07FD5E530E9E6BFB2ACA4B8C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_audio_formats.h"; path = "../../JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.h"; sourceTree = "SOURCE_ROOT"; };
 		081E86FE0B991469CFA8D7EA = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_CPlusPlusCodeTokeniser.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CPlusPlusCodeTokeniser.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -265,7 +252,6 @@
 		167524110873F9888CF1B9E8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ApplicationCommandID.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandID.h"; sourceTree = "SOURCE_ROOT"; };
 		168823A9EBD85BFBFD2CE2EE = {isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons-03.png"; path = "../../Resources/Images/Icons/RadioButtons-03.png"; sourceTree = "SOURCE_ROOT"; };
 		1712916024EC787B6C231732 = {isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected_over-03.png"; path = "../../Resources/Images/Icons/RadioButtons_selected_over-03.png"; sourceTree = "SOURCE_ROOT"; };
-		1718EC50691D8421EC00F8B3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FileReaderThread.cpp; path = ../../Source/Processors/DataThreads/FileReaderThread.cpp; sourceTree = "SOURCE_ROOT"; };
 		1719507D8A73EA71F1C3F306 = {isa = PBXFileReference; lastKnownFileType = file; name = "cpmono-plain-serialized"; path = "../../Resources/Fonts/cpmono-plain-serialized"; sourceTree = "SOURCE_ROOT"; };
 		172FA5C9EC4B16BC0C45F269 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Variant.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_Variant.h"; sourceTree = "SOURCE_ROOT"; };
 		174842EA681FA29BE38A6272 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ButtonPropertyComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -313,7 +299,6 @@
 		205E9A5C31827555F1CAC30D = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OpenGL_osx.h"; path = "../../JuceLibraryCode/modules/juce_opengl/native/juce_OpenGL_osx.h"; sourceTree = "SOURCE_ROOT"; };
 		208DCD7025D0DF2740C01E4A = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextPropertyComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h"; sourceTree = "SOURCE_ROOT"; };
 		20BB146B925C4D4AD43BA479 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = State.cpp; path = ../../Source/Processors/Dsp/State.cpp; sourceTree = "SOURCE_ROOT"; };
-		20DBF92457AF75C0698D1B26 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpTriggeredAverageEditor.cpp; path = ../../Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageEditor.cpp; sourceTree = "SOURCE_ROOT"; };
 		20EB4F22A76954F2986F364A = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_Windowing.mm"; path = "../../JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_Windowing.mm"; sourceTree = "SOURCE_ROOT"; };
 		215B159836CE40810964B773 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Uuid.h"; path = "../../JuceLibraryCode/modules/juce_core/misc/juce_Uuid.h"; sourceTree = "SOURCE_ROOT"; };
 		215E1BD79B5870D5356810F0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Visualizer.h; path = ../../Source/Processors/Visualization/Visualizer.h; sourceTree = "SOURCE_ROOT"; };
@@ -322,7 +307,6 @@
 		21C11A58CAA0F9E86AA204EC = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Slider.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Slider.h"; sourceTree = "SOURCE_ROOT"; };
 		21D3C1095D2B5A834D998B74 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_OpenSL.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_devices/native/juce_android_OpenSL.cpp"; sourceTree = "SOURCE_ROOT"; };
 		222AC2E9BEFE12BE7FF88879 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Thread.cpp"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_Thread.cpp"; sourceTree = "SOURCE_ROOT"; };
-		22FAA3DA9944AA853D66114F = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LfpTriggeredAverageCanvas.h; path = ../../Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageCanvas.h; sourceTree = "SOURCE_ROOT"; };
 		235A8987D99A191D07208D2F = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = okFrontPanelDLL.cpp; path = "../../Source/Processors/DataThreads/rhythm-api/okFrontPanelDLL.cpp"; sourceTree = "SOURCE_ROOT"; };
 		23609D430A25F54723269E91 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_gui_basics.mm"; path = "../../JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.mm"; sourceTree = "SOURCE_ROOT"; };
 		23A6BA852B71DAAF3F709428 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RHD2000Thread.h; path = ../../Source/Processors/DataThreads/RHD2000Thread.h; sourceTree = "SOURCE_ROOT"; };
@@ -401,7 +385,6 @@
 		36332333DBF8363163F454E6 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = HDF5Recording.cpp; path = ../../Source/Processors/RecordNode/HDF5Recording.cpp; sourceTree = "SOURCE_ROOT"; };
 		3663C981D28BF165C1B601A7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OptionalScopedPointer.h"; path = "../../JuceLibraryCode/modules/juce_core/memory/juce_OptionalScopedPointer.h"; sourceTree = "SOURCE_ROOT"; };
 		36A9736F04AAA2F8E9D711BB = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SpinLock.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_SpinLock.h"; sourceTree = "SOURCE_ROOT"; };
-		3734FF118787377E4C8741D1 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WiFiOutputEditor.cpp; path = ../../Source/Processors/WiFiOutput/WiFiOutputEditor.cpp; sourceTree = "SOURCE_ROOT"; };
 		3753B3B311AE0A9F4CC5AD40 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ofArduino.cpp; path = ../../Source/Processors/Serial/ofArduino.cpp; sourceTree = "SOURCE_ROOT"; };
 		3774BBCA6CB133D9A854CF71 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CustomLookAndFeel.cpp; path = ../../Source/UI/CustomLookAndFeel.cpp; sourceTree = "SOURCE_ROOT"; };
 		381F5DC605AE69088004DF80 = {isa = PBXFileReference; lastKnownFileType = image.png; name = "PipelineB-01.png"; path = "../../Resources/Images/Buttons/PipelineB-01.png"; sourceTree = "SOURCE_ROOT"; };
@@ -458,7 +441,6 @@
 		414D8E6E4EE98E66C2583A50 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TextPropertyComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
 		416B99B14B44CB16B725C4B2 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StretchableObjectResizer.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableObjectResizer.h"; sourceTree = "SOURCE_ROOT"; };
 		41AF61914A96159E9EA194B0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_Clipboard.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Clipboard.cpp"; sourceTree = "SOURCE_ROOT"; };
-		41E88094E8D929866A6DCA9A = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioResamplingNode.cpp; path = ../../Source/Processors/AudioResamplingNode/AudioResamplingNode.cpp; sourceTree = "SOURCE_ROOT"; };
 		420843E39C285B620B220C1D = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LeakedObjectDetector.h"; path = "../../JuceLibraryCode/modules/juce_core/memory/juce_LeakedObjectDetector.h"; sourceTree = "SOURCE_ROOT"; };
 		420B0E95F1300ABFDC125DBF = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AccessClass.cpp; path = ../../Source/AccessClass.cpp; sourceTree = "SOURCE_ROOT"; };
 		42BF0530EADF336E58D39CD3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FloatVectorOperations.h"; path = "../../JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h"; sourceTree = "SOURCE_ROOT"; };
@@ -466,7 +448,6 @@
 		434E153E6C8337C1E4A2709A = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ButtonPropertyComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.h"; sourceTree = "SOURCE_ROOT"; };
 		442F01DC974E1EAC57450906 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PoleFilter.h; path = ../../Source/Processors/Dsp/PoleFilter.h; sourceTree = "SOURCE_ROOT"; };
 		4434939E139A45962C8CFB4C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DrawableShape.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableShape.cpp"; sourceTree = "SOURCE_ROOT"; };
-		4448875C40EAB061B2F8A289 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FPGAOutput.cpp; path = ../../Source/Processors/FPGAOutput/FPGAOutput.cpp; sourceTree = "SOURCE_ROOT"; };
 		449B26D1265BB91B331EFF84 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HDF5FileFormat.h; path = ../../Source/Processors/RecordNode/HDF5FileFormat.h; sourceTree = "SOURCE_ROOT"; };
 		44E04E5F584A8BFAD062A09D = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ShapeButton.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ShapeButton.h"; sourceTree = "SOURCE_ROOT"; };
 		45258533F9F65AC96D3080B3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MultiTouchMapper.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/native/juce_MultiTouchMapper.h"; sourceTree = "SOURCE_ROOT"; };
@@ -531,7 +512,6 @@
 		50DD8D693741DD18106C0BA7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentListener.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/components/juce_ComponentListener.h"; sourceTree = "SOURCE_ROOT"; };
 		510ACDAD798813D7FC110197 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TabbedComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedComponent.h"; sourceTree = "SOURCE_ROOT"; };
 		511C443A0A806706A772E981 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Primes.cpp"; path = "../../JuceLibraryCode/modules/juce_cryptography/encryption/juce_Primes.cpp"; sourceTree = "SOURCE_ROOT"; };
-		513D20023796491A24EC58A7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WiFiOutputEditor.h; path = ../../Source/Processors/WiFiOutput/WiFiOutputEditor.h; sourceTree = "SOURCE_ROOT"; };
 		515213CC3271E8DEA8125D33 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DynamicLibrary.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_DynamicLibrary.h"; sourceTree = "SOURCE_ROOT"; };
 		515C4C8AC20EA25F3DEF2336 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LuaCodeTokeniser.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_LuaCodeTokeniser.h"; sourceTree = "SOURCE_ROOT"; };
 		51926BEEA63BF141D93A5B36 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RelativePoint.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePoint.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -545,7 +525,6 @@
 		5343D594AA7D444A7C6AD924 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_GZIPDecompressorInputStream.h"; path = "../../JuceLibraryCode/modules/juce_core/zip/juce_GZIPDecompressorInputStream.h"; sourceTree = "SOURCE_ROOT"; };
 		5379FC603780F30A2F05FE78 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AsyncUpdater.h"; path = "../../JuceLibraryCode/modules/juce_events/broadcasters/juce_AsyncUpdater.h"; sourceTree = "SOURCE_ROOT"; };
 		53C8A2696FE4389E4AB4441C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Slider.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Slider.cpp"; sourceTree = "SOURCE_ROOT"; };
-		540CD9ED0C719DB1DAECA37E = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WiFiOutput.h; path = ../../Source/Processors/WiFiOutput/WiFiOutput.h; sourceTree = "SOURCE_ROOT"; };
 		54339ADDCB6F8E9E7721A986 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Windowing.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/native/juce_android_Windowing.cpp"; sourceTree = "SOURCE_ROOT"; };
 		547C76794FAC1BC349163509 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = tictoc.cpp; path = ../../Source/Processors/PSTH/tictoc.cpp; sourceTree = "SOURCE_ROOT"; };
 		54B7796F6DCF5531789CCF43 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Types.h; path = ../../Source/Processors/Dsp/Types.h; sourceTree = "SOURCE_ROOT"; };
@@ -600,7 +579,6 @@
 		5E0F8A60411A03461FD687CE = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_GroupComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_GroupComponent.h"; sourceTree = "SOURCE_ROOT"; };
 		5E1EFF4EEA5684FA00CAA353 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ResizableBorderComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableBorderComponent.h"; sourceTree = "SOURCE_ROOT"; };
 		5E5098D437FC0612291567AC = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Documentation.cpp; path = ../../Source/Processors/Dsp/Documentation.cpp; sourceTree = "SOURCE_ROOT"; };
-		5E5736CB6D96D5271F1A7597 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioResamplingNode.h; path = ../../Source/Processors/AudioResamplingNode/AudioResamplingNode.h; sourceTree = "SOURCE_ROOT"; };
 		5E663D5A55F191AB92A1383F = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileInputStream.h"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_FileInputStream.h"; sourceTree = "SOURCE_ROOT"; };
 		5E94E897783BEEFE61E61A2C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_WebBrowserComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
 		5EA566ED87CC02EA6DF1993B = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FilterEditor.h; path = ../../Source/Processors/FilterNode/FilterEditor.h; sourceTree = "SOURCE_ROOT"; };
@@ -646,7 +624,6 @@
 		670987D88775D6B240C34820 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_NotificationType.h"; path = "../../JuceLibraryCode/modules/juce_events/messages/juce_NotificationType.h"; sourceTree = "SOURCE_ROOT"; };
 		674FDCCEF6A1379A0F689004 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentBoundsConstrainer.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.h"; sourceTree = "SOURCE_ROOT"; };
 		677CC8DA903C77D8ECBAE26D = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Params.h; path = ../../Source/Processors/Dsp/Params.h; sourceTree = "SOURCE_ROOT"; };
-		679BBE9F6C930A1941BA7944 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ReferenceNode.h; path = ../../Source/Processors/ReferenceNode/ReferenceNode.h; sourceTree = "SOURCE_ROOT"; };
 		67BB47E709B643D4C01AB34C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioDeviceSelectorComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
 		6832130272774CD542793762 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_CoreGraphicsContext.mm"; path = "../../JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm"; sourceTree = "SOURCE_ROOT"; };
 		686FA8DDF2848517CBFB9E4A = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MouseCursor.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -672,7 +649,6 @@
 		6D34DD9AB987A67BADE71C65 = {isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons-05.png"; path = "../../Resources/Images/Icons/RadioButtons-05.png"; sourceTree = "SOURCE_ROOT"; };
 		6D38B76951D31D96F1B71E0F = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SerialInputEditor.cpp; path = ../../Source/Processors/SerialInput/SerialInputEditor.cpp; sourceTree = "SOURCE_ROOT"; };
 		6D4BA4399FDEB6D2195B257D = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SplashScreen.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_SplashScreen.h"; sourceTree = "SOURCE_ROOT"; };
-		6D4D435D25CFC019E0FCF4A1 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ReferenceNodeEditor.cpp; path = ../../Source/Processors/ReferenceNode/ReferenceNodeEditor.cpp; sourceTree = "SOURCE_ROOT"; };
 		6D4DFC260B2966E3EBFC0C79 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SliderPropertyComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
 		6D619C7A3A14981DC4EFF223 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_IIRFilterAudioSource.h"; path = "../../JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.h"; sourceTree = "SOURCE_ROOT"; };
 		6D77949E9C7C9B5A7795C0E0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_PathStrokeType.h"; path = "../../JuceLibraryCode/modules/juce_graphics/geometry/juce_PathStrokeType.h"; sourceTree = "SOURCE_ROOT"; };
@@ -799,14 +775,12 @@
 		8689288B66B16EFB106CB2F4 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextInputTarget.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_TextInputTarget.h"; sourceTree = "SOURCE_ROOT"; };
 		86E8E44A13F17083ED300BD5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ChangeListener.h"; path = "../../JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeListener.h"; sourceTree = "SOURCE_ROOT"; };
 		86F4AAFCE3FEB34E325F3020 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_win32_ComSmartPtr.h"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_win32_ComSmartPtr.h"; sourceTree = "SOURCE_ROOT"; };
-		8751DF970A9E3598683BACAF = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FPGAThread.h; path = ../../Source/Processors/DataThreads/FPGAThread.h; sourceTree = "SOURCE_ROOT"; };
 		879B0383EF2A8B116903A500 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImageCache.h"; path = "../../JuceLibraryCode/modules/juce_graphics/images/juce_ImageCache.h"; sourceTree = "SOURCE_ROOT"; };
 		87B4BA68E49DD11197B7AFDB = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = "SOURCE_ROOT"; };
 		87C0534EAC82E887E1D354C3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Butterworth.h; path = ../../Source/Processors/Dsp/Butterworth.h; sourceTree = "SOURCE_ROOT"; };
 		880CC7C325EFF665AC3006D2 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_KeyListener.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyListener.cpp"; sourceTree = "SOURCE_ROOT"; };
 		881237D5E366342B117C0ED7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_WildcardFileFilter.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_WildcardFileFilter.cpp"; sourceTree = "SOURCE_ROOT"; };
 		8822ADC9DB83FAF39B841E31 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Font.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/fonts/juce_Font.cpp"; sourceTree = "SOURCE_ROOT"; };
-		883E23B392AFB86C3EE1A2AC = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ReferenceNodeEditor.h; path = ../../Source/Processors/ReferenceNode/ReferenceNodeEditor.h; sourceTree = "SOURCE_ROOT"; };
 		8882F8EBE55F52FA8E519249 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Files.cpp"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_android_Files.cpp"; sourceTree = "SOURCE_ROOT"; };
 		88C69F0563A99BD2F7BF5FBB = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpDisplayEditor.cpp; path = ../../Source/Processors/LfpDisplayNode/LfpDisplayEditor.cpp; sourceTree = "SOURCE_ROOT"; };
 		88E5D0906646465409715828 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PreferencesPanel.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_PreferencesPanel.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -875,7 +849,6 @@
 		949422DF0532222450E95926 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = RecordNode.cpp; path = ../../Source/Processors/RecordNode/RecordNode.cpp; sourceTree = "SOURCE_ROOT"; };
 		94BD861806F8EA598EC09370 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ResizableCornerComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableCornerComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
 		95A64508FF3D0140D3001A19 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ArduinoOutput.cpp; path = ../../Source/Processors/ArduinoOutput/ArduinoOutput.cpp; sourceTree = "SOURCE_ROOT"; };
-		95B57108E929DD11F898B7B1 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FileReaderThread.h; path = ../../Source/Processors/DataThreads/FileReaderThread.h; sourceTree = "SOURCE_ROOT"; };
 		95EC6B1536DC65070D0ADCEE = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ListBox.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ListBox.h"; sourceTree = "SOURCE_ROOT"; };
 		967138FE8A086734ADC8CABB = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Value.cpp"; path = "../../JuceLibraryCode/modules/juce_data_structures/values/juce_Value.cpp"; sourceTree = "SOURCE_ROOT"; };
 		96E99CD031BD069997E387FE = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MidiBuffer.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -964,7 +937,6 @@
 		AADBA8C0AD524CE677428AFF = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_GlowEffect.h"; path = "../../JuceLibraryCode/modules/juce_graphics/effects/juce_GlowEffect.h"; sourceTree = "SOURCE_ROOT"; };
 		AAF5C27D2EEDD254A3652717 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Bessel.h; path = ../../Source/Processors/Dsp/Bessel.h; sourceTree = "SOURCE_ROOT"; };
 		AB4C7059669AC385B02179C1 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileLogger.h"; path = "../../JuceLibraryCode/modules/juce_core/logging/juce_FileLogger.h"; sourceTree = "SOURCE_ROOT"; };
-		AB4D72F040FF59BED08826EC = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FPGAOutputEditor.cpp; path = ../../Source/Processors/FPGAOutput/FPGAOutputEditor.cpp; sourceTree = "SOURCE_ROOT"; };
 		ABA3FCD5D762336535D56D94 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ScopedLock.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_ScopedLock.h"; sourceTree = "SOURCE_ROOT"; };
 		AC116E6590D49AB2EF19CB9E = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_OpenGLImage.cpp"; path = "../../JuceLibraryCode/modules/juce_opengl/opengl/juce_OpenGLImage.cpp"; sourceTree = "SOURCE_ROOT"; };
 		AC9E30922A14330704FB2573 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDisplayNode.cpp; path = ../../Source/Processors/SpikeDisplayNode/SpikeDisplayNode.cpp; sourceTree = "SOURCE_ROOT"; };
@@ -976,7 +948,6 @@
 		AD7D35FCD8CF66B6C393A7F7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileBrowserComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.h"; sourceTree = "SOURCE_ROOT"; };
 		AD960F561259904BA68DDA73 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MemoryMappedFile.h"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_MemoryMappedFile.h"; sourceTree = "SOURCE_ROOT"; };
 		ADCB42E4C5641007A4B78025 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeObject.h; path = ../../Source/Processors/Visualization/SpikeObject.h; sourceTree = "SOURCE_ROOT"; };
-		ADCEA06868A5085B60487AC3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LfpTriggeredAverageEditor.h; path = ../../Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageEditor.h; sourceTree = "SOURCE_ROOT"; };
 		AE1EA04666EAD34D0CA0373D = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_opengl.h"; path = "../../JuceLibraryCode/modules/juce_opengl/juce_opengl.h"; sourceTree = "SOURCE_ROOT"; };
 		AE1FC768C646A0EFEC3E3A11 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDisplayNode.h; path = ../../Source/Processors/SpikeDisplayNode/SpikeDisplayNode.h; sourceTree = "SOURCE_ROOT"; };
 		AE3D7946F13CE32AE41DD1B7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MatlabLikePlot.h; path = ../../Source/Processors/Visualization/MatlabLikePlot.h; sourceTree = "SOURCE_ROOT"; };
@@ -1016,7 +987,6 @@
 		B2241E3C5C9F93389586F357 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DirectoryIterator.h"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_DirectoryIterator.h"; sourceTree = "SOURCE_ROOT"; };
 		B23E6EBB5F99CF7FC72FAC4E = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VisualizerEditor.h; path = ../../Source/Processors/Editors/VisualizerEditor.h; sourceTree = "SOURCE_ROOT"; };
 		B24098EC4FD79D5EDC9383EC = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Initialisation.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/application/juce_Initialisation.h"; sourceTree = "SOURCE_ROOT"; };
-		B25949076F9BB831C5862415 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WiFiOutput.cpp; path = ../../Source/Processors/WiFiOutput/WiFiOutput.cpp; sourceTree = "SOURCE_ROOT"; };
 		B2EF409A1F459E964756BA7C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileInputStream.cpp"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_FileInputStream.cpp"; sourceTree = "SOURCE_ROOT"; };
 		B2F72769CF14BD7F882E9542 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LfpDisplayNode.h; path = ../../Source/Processors/LfpDisplayNode/LfpDisplayNode.h; sourceTree = "SOURCE_ROOT"; };
 		B2FA9CC4754E136F22281176 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImageEffectFilter.h"; path = "../../JuceLibraryCode/modules/juce_graphics/effects/juce_ImageEffectFilter.h"; sourceTree = "SOURCE_ROOT"; };
@@ -1138,7 +1108,6 @@
 		CC35C78D5B446ABF57DDDAE0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImageFileFormat.h"; path = "../../JuceLibraryCode/modules/juce_graphics/images/juce_ImageFileFormat.h"; sourceTree = "SOURCE_ROOT"; };
 		CC42C4D4230BE4F1071CB2D3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ResizableEdgeComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.h"; sourceTree = "SOURCE_ROOT"; };
 		CC62E20B1189C697DD238810 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OpenGL_linux.h"; path = "../../JuceLibraryCode/modules/juce_opengl/native/juce_OpenGL_linux.h"; sourceTree = "SOURCE_ROOT"; };
-		CC9134D38EBEC67112CA7502 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpTriggeredAverageCanvas.cpp; path = ../../Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageCanvas.cpp; sourceTree = "SOURCE_ROOT"; };
 		CCE779E203974113A80D6D85 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tictoc.h; path = ../../Source/Processors/PSTH/tictoc.h; sourceTree = "SOURCE_ROOT"; };
 		CD2E26CFD0DC7F6090E15A20 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Line.h"; path = "../../JuceLibraryCode/modules/juce_graphics/geometry/juce_Line.h"; sourceTree = "SOURCE_ROOT"; };
 		CD41C1D09F6D73FA33993F45 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Desktop.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/components/juce_Desktop.h"; sourceTree = "SOURCE_ROOT"; };
@@ -1197,7 +1166,6 @@
 		D8AFDCC674A7514B7019EEA6 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DrawableButton.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/buttons/juce_DrawableButton.h"; sourceTree = "SOURCE_ROOT"; };
 		D952A208CC8164F0B459EC9E = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_WebBrowserComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_extra/native/juce_linux_WebBrowserComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
 		D960588B732D973B82500E2D = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioProcessorListener.h"; path = "../../JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorListener.h"; sourceTree = "SOURCE_ROOT"; };
-		D9B10885C9D93CEF580EF167 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ReferenceNode.cpp; path = ../../Source/Processors/ReferenceNode/ReferenceNode.cpp; sourceTree = "SOURCE_ROOT"; };
 		D9BF6DA66C22FFF5C4D41991 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpDisplayCanvas.cpp; path = ../../Source/Processors/LfpDisplayNode/LfpDisplayCanvas.cpp; sourceTree = "SOURCE_ROOT"; };
 		D9C9FCA6D705B72B80DB1142 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Socket.cpp"; path = "../../JuceLibraryCode/modules/juce_core/network/juce_Socket.cpp"; sourceTree = "SOURCE_ROOT"; };
 		D9CB4CEC2C07346BE69262A0 = {isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected-01.png"; path = "../../Resources/Images/Icons/RadioButtons_selected-01.png"; sourceTree = "SOURCE_ROOT"; };
@@ -1213,7 +1181,6 @@
 		DB4FF7675E5C98CF62DA8A2E = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AccessClass.h; path = ../../Source/AccessClass.h; sourceTree = "SOURCE_ROOT"; };
 		DB550BAB034060FF4578BB64 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_audio_basics.h"; path = "../../JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.h"; sourceTree = "SOURCE_ROOT"; };
 		DB7866AFC8A4894810DBD05E = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_InterProcessLock.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_InterProcessLock.h"; sourceTree = "SOURCE_ROOT"; };
-		DBAB7848C770895CED4E2F95 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LfpTriggeredAverageNode.h; path = ../../Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.h; sourceTree = "SOURCE_ROOT"; };
 		DBB769DEBCD6468C13A3CD25 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
 		DBCA7E2FFCFD1354DD19DDD6 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_data_structures.mm"; path = "../../JuceLibraryCode/modules/juce_data_structures/juce_data_structures.mm"; sourceTree = "SOURCE_ROOT"; };
 		DBED17FBB262C4DACEEDA9B0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MidiKeyboardState.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -1275,31 +1242,29 @@
 		E7ACE8C1456403A574236451 = {isa = PBXFileReference; lastKnownFileType = file; name = "cpmono-bold-serialized"; path = "../../Resources/Fonts/cpmono-bold-serialized"; sourceTree = "SOURCE_ROOT"; };
 		E7EE416EF527C7506B499070 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_BigInteger.h"; path = "../../JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.h"; sourceTree = "SOURCE_ROOT"; };
 		E835BEB3C42E4B241804BE13 = {isa = PBXFileReference; lastKnownFileType = file; name = "cpmono-light-serialized"; path = "../../Resources/Fonts/cpmono-light-serialized"; sourceTree = "SOURCE_ROOT"; };
+		E849E3966302E7D4D06712F5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = RecordControl.cpp; path = ../../Source/Processors/RecordControl/RecordControl.cpp; sourceTree = "SOURCE_ROOT"; };
 		E850C14F13F9855CE1E14C1A = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ArduinoOutputEditor.cpp; path = ../../Source/Processors/ArduinoOutput/ArduinoOutputEditor.cpp; sourceTree = "SOURCE_ROOT"; };
-		E91A272EF06892937CB4B9CE = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentDragger.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.cpp"; sourceTree = "SOURCE_ROOT"; };
+		E8964C0BE264A55753BC6B7B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_Midi.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_Midi.cpp"; sourceTree = "SOURCE_ROOT"; };
+		E91923510CB2280C3A3B9E9C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LocalisedStrings.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.h"; sourceTree = "SOURCE_ROOT"; };
 		E946426F95E0240683CB3337 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DrawablePath.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawablePath.h"; sourceTree = "SOURCE_ROOT"; };
-		EA2FC92CECD1EDA1F07DC59C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TooltipWindow.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_TooltipWindow.h"; sourceTree = "SOURCE_ROOT"; };
-		ED86166920362E9D2BE2CB26 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SVGParser.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp"; sourceTree = "SOURCE_ROOT"; };
-		EDAC82BD742A54182E8DF2FE = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RelativeCoordinatePositioner.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.h"; sourceTree = "SOURCE_ROOT"; };
-		EE0336B43A39FD585DF638EE = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ResizableEdgeComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
-		EE4DD055D31F7D9DC718DBD8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentMovementWatcher.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.h"; sourceTree = "SOURCE_ROOT"; };
+		EA354D7D8E48D461415D52D8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_JPEGLoader.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp"; sourceTree = "SOURCE_ROOT"; };
+		EA9518CDEA7049C21D5CE2D5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Process.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_Process.h"; sourceTree = "SOURCE_ROOT"; };
+		EAB6A66678B122C578B16445 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_HighResolutionTimer.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.h"; sourceTree = "SOURCE_ROOT"; };
+		EAC262A83CD2BEA14542AE89 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StringPool.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringPool.h"; sourceTree = "SOURCE_ROOT"; };
+		EAEA49B9394D802B79CA8164 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StringPairArray.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.h"; sourceTree = "SOURCE_ROOT"; };
+		EDA209B0E7D124EA581023AD = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioFormatManager.h"; path = "../../JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatManager.h"; sourceTree = "SOURCE_ROOT"; };
+		EF3F9AA8D70E1D4D55F13182 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioThumbnail.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp"; sourceTree = "SOURCE_ROOT"; };
 		F5A00ACFA3D76168F22F1205 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
 		99E1BC08B886CFDD2CCFD462 = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "open-ephys.app"; sourceTree = "BUILT_PRODUCTS_DIR"; };
-		E849E3966302E7D4D06712F5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = RecordControl.cpp; path = ../../Source/Processors/RecordControl/RecordControl.cpp; sourceTree = "SOURCE_ROOT"; };
-		E8964C0BE264A55753BC6B7B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_Midi.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_Midi.cpp"; sourceTree = "SOURCE_ROOT"; };
 		E8D51D470C9955D7D03D5469 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ChebyshevII.h; path = ../../Source/Processors/Dsp/ChebyshevII.h; sourceTree = "SOURCE_ROOT"; };
-		E91923510CB2280C3A3B9E9C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LocalisedStrings.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.h"; sourceTree = "SOURCE_ROOT"; };
+		E91A272EF06892937CB4B9CE = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentDragger.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.cpp"; sourceTree = "SOURCE_ROOT"; };
 		E93BE115650B1CB80EACB841 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EditorViewportButtons.h; path = ../../Source/UI/EditorViewportButtons.h; sourceTree = "SOURCE_ROOT"; };
 		E97684DCE824DEDA6683C6CD = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Synthesiser.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp"; sourceTree = "SOURCE_ROOT"; };
-		EA354D7D8E48D461415D52D8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_JPEGLoader.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp"; sourceTree = "SOURCE_ROOT"; };
+		EA2FC92CECD1EDA1F07DC59C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TooltipWindow.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_TooltipWindow.h"; sourceTree = "SOURCE_ROOT"; };
 		EA73332E3D5AEC04ADDFBB2A = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioDataConverters.h"; path = "../../JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h"; sourceTree = "SOURCE_ROOT"; };
-		EA9518CDEA7049C21D5CE2D5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Process.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_Process.h"; sourceTree = "SOURCE_ROOT"; };
 		EAB2319C7AA57E06A2247CDF = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_BorderSize.h"; path = "../../JuceLibraryCode/modules/juce_graphics/geometry/juce_BorderSize.h"; sourceTree = "SOURCE_ROOT"; };
 		EAB637B566FEBBDADA654262 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_VSTMidiEventList.h"; path = "../../JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h"; sourceTree = "SOURCE_ROOT"; };
-		EAB6A66678B122C578B16445 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_HighResolutionTimer.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.h"; sourceTree = "SOURCE_ROOT"; };
-		EAC262A83CD2BEA14542AE89 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StringPool.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringPool.h"; sourceTree = "SOURCE_ROOT"; };
 		EAC7A64301F0BF2C5E33A1F9 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_InterprocessConnectionServer.cpp"; path = "../../JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnectionServer.cpp"; sourceTree = "SOURCE_ROOT"; };
-		EAEA49B9394D802B79CA8164 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StringPairArray.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.h"; sourceTree = "SOURCE_ROOT"; };
 		EB5F9A50EB53A57D6AE303C2 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_QuickTimeMovieComponent.mm"; path = "../../JuceLibraryCode/modules/juce_video/native/juce_mac_QuickTimeMovieComponent.mm"; sourceTree = "SOURCE_ROOT"; };
 		EBD8622EAEF10558809888B7 = {isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected_over-01.png"; path = "../../Resources/Images/Icons/RadioButtons_selected_over-01.png"; sourceTree = "SOURCE_ROOT"; };
 		EC95A2CF4B33EA37DA5FC1AC = {isa = PBXFileReference; lastKnownFileType = file.ttf; name = nordic.ttf; path = ../../Resources/Fonts/nordic.ttf; sourceTree = "SOURCE_ROOT"; };
@@ -1307,14 +1272,15 @@
 		ECBEF88BBC974D96ED781C75 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_posix_SharedCode.h"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h"; sourceTree = "SOURCE_ROOT"; };
 		ECCE033FF2ACE42188FA4A7F = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TemporaryFile.h"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.h"; sourceTree = "SOURCE_ROOT"; };
 		ECE3BE71EB6B9CF1CE869BBE = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_BubbleComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/misc/juce_BubbleComponent.h"; sourceTree = "SOURCE_ROOT"; };
-		ED0955C4DE64766A7F5F96F2 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FPGAOutputEditor.h; path = ../../Source/Processors/FPGAOutput/FPGAOutputEditor.h; sourceTree = "SOURCE_ROOT"; };
+		ED86166920362E9D2BE2CB26 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_SVGParser.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp"; sourceTree = "SOURCE_ROOT"; };
 		ED887A521EEB8F3EBA7DDB31 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioIODeviceType.h"; path = "../../JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h"; sourceTree = "SOURCE_ROOT"; };
-		EDA209B0E7D124EA581023AD = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioFormatManager.h"; path = "../../JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatManager.h"; sourceTree = "SOURCE_ROOT"; };
+		EDAC82BD742A54182E8DF2FE = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RelativeCoordinatePositioner.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.h"; sourceTree = "SOURCE_ROOT"; };
+		EE0336B43A39FD585DF638EE = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ResizableEdgeComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.cpp"; sourceTree = "SOURCE_ROOT"; };
 		EE2C669B127D00C86B1B8CA8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_Registry.cpp"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_win32_Registry.cpp"; sourceTree = "SOURCE_ROOT"; };
+		EE4DD055D31F7D9DC718DBD8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentMovementWatcher.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.h"; sourceTree = "SOURCE_ROOT"; };
 		EEA51B7EF1CF19028C6672E0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DocumentWindow.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_DocumentWindow.cpp"; sourceTree = "SOURCE_ROOT"; };
 		EEFC66D2DF5FD66B4D83B22F = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Component.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.h"; sourceTree = "SOURCE_ROOT"; };
 		EF059B26886B32000BCF8CFF = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MouseInputSource.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInputSource.h"; sourceTree = "SOURCE_ROOT"; };
-		EF3F9AA8D70E1D4D55F13182 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioThumbnail.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp"; sourceTree = "SOURCE_ROOT"; };
 		EF4A6E0E1232071252ACCD7B = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RelativeParallelogram.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.h"; sourceTree = "SOURCE_ROOT"; };
 		EF610B2A17D9B1C0D24DCE67 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_android_JNIHelpers.h"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_android_JNIHelpers.h"; sourceTree = "SOURCE_ROOT"; };
 		EF7B66764093D950724EFE70 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OpenGLShaderProgram.h"; path = "../../JuceLibraryCode/modules/juce_opengl/opengl/juce_OpenGLShaderProgram.h"; sourceTree = "SOURCE_ROOT"; };
@@ -1360,9 +1326,7 @@
 		F960CC94B136201BDA148EEA = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CustomArrowButton.cpp; path = ../../Source/UI/CustomArrowButton.cpp; sourceTree = "SOURCE_ROOT"; };
 		F9E2371F1A99B292F2947FF5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DragAndDropTarget.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropTarget.h"; sourceTree = "SOURCE_ROOT"; };
 		F9F37AD1C3E7CA932FF44E69 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_LagrangeInterpolator.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp"; sourceTree = "SOURCE_ROOT"; };
-		FA12F07F4F9C872C18A2817B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpTriggeredAverageNode.cpp; path = ../../Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.cpp; sourceTree = "SOURCE_ROOT"; };
 		FA1F1E9C7DEA48CAE6C247F4 = {isa = PBXFileReference; lastKnownFileType = image.png; name = OpenEphysBoardLogoGray.png; path = ../../Resources/Images/Icons/OpenEphysBoardLogoGray.png; sourceTree = "SOURCE_ROOT"; };
-		FA23A1334E4CFA77BC18A153 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FPGAThread.cpp; path = ../../Source/Processors/DataThreads/FPGAThread.cpp; sourceTree = "SOURCE_ROOT"; };
 		FA2F04BA4E146ABF649BBE89 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = rhd2000evalboard.h; path = "../../Source/Processors/DataThreads/rhythm-api/rhd2000evalboard.h"; sourceTree = "SOURCE_ROOT"; };
 		FA8CC6FD54A9F20DA755F2EA = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Channel.cpp; path = ../../Source/Processors/Channel/Channel.cpp; sourceTree = "SOURCE_ROOT"; };
 		FAC7E62CC15CA977A6FC72D1 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ChangeBroadcaster.cpp"; path = "../../JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeBroadcaster.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -1479,9 +1443,6 @@
 					C15024C101ECE85FDDCD770D,
 					1F22CC8D992B8B49D57DDB3F,
 					19B08AF9187EC45ECDE87602, ); name = AudioNode; sourceTree = "<group>"; };
-		7BE07AA81C59DD7252F709E6 = {isa = PBXGroup; children = (
-					41E88094E8D929866A6DCA9A,
-					5E5736CB6D96D5271F1A7597, ); name = AudioResamplingNode; sourceTree = "<group>"; };
 		B3EC4C17E1555DCD89B1B62C = {isa = PBXGroup; children = (
 					FA8CC6FD54A9F20DA755F2EA,
 					74BAC33D6BC1D961F04DCC72, ); name = Channel; sourceTree = "<group>"; };
@@ -1509,10 +1470,6 @@
 					EBA825AF6FDB51EBA368CB8D,
 					A3FB0EA0264580F6B00D993B,
 					23A6BA852B71DAAF3F709428,
-					1718EC50691D8421EC00F8B3,
-					95B57108E929DD11F898B7B1,
-					FA23A1334E4CFA77BC18A153,
-					8751DF970A9E3598683BACAF,
 					788F8B7719B70465762B634B,
 					F09FD6D9CA4997216ADBF54F,
 					92602D7166325C7232B85EDD,
@@ -1595,11 +1552,6 @@
 					5EA566ED87CC02EA6DF1993B,
 					9AA19ECEFE2B49832ECEED2F,
 					70651FEF347D8DE167B68EB8, ); name = FilterNode; sourceTree = "<group>"; };
-		85403FACC153147273CEB933 = {isa = PBXGroup; children = (
-					4448875C40EAB061B2F8A289,
-					07A8ED74417654C40F9EFEFC,
-					AB4D72F040FF59BED08826EC,
-					ED0955C4DE64766A7F5F96F2, ); name = FPGAOutput; sourceTree = "<group>"; };
 		5FAE90CAD8DAA5CE48855F38 = {isa = PBXGroup; children = (
 					C5654EAA7B65445CF1340983,
 					012F05BBF926C8F39AC7871B, ); name = GenericProcessor; sourceTree = "<group>"; };
@@ -1610,13 +1562,6 @@
 					E04512D01D2F6FE00C336CAD,
 					1C64C490BD7FE9E57D6C682D,
 					B2F72769CF14BD7F882E9542, ); name = LfpDisplayNode; sourceTree = "<group>"; };
-		518310F63C8005A8D097A1D8 = {isa = PBXGroup; children = (
-					CC9134D38EBEC67112CA7502,
-					22FAA3DA9944AA853D66114F,
-					20DBF92457AF75C0698D1B26,
-					ADCEA06868A5085B60487AC3,
-					FA12F07F4F9C872C18A2817B,
-					DBAB7848C770895CED4E2F95, ); name = LfpTriggeredAverageNode; sourceTree = "<group>"; };
 		A1678CA8F8E882F5D7EFDB3E = {isa = PBXGroup; children = (
 					07B84F46CF90D04BB6B673C5,
 					CA50A6F43BD78D01A8BE974B,
@@ -1673,11 +1618,6 @@
 					CCE779E203974113A80D6D85,
 					FB827FEEA15A274E5F7577DB,
 					76D8904379362E11CA4EA11D, ); name = PSTH; sourceTree = "<group>"; };
-		21389ED521B378402213EFC3 = {isa = PBXGroup; children = (
-					D9B10885C9D93CEF580EF167,
-					679BBE9F6C930A1941BA7944,
-					6D4D435D25CFC019E0FCF4A1,
-					883E23B392AFB86C3EE1A2AC, ); name = ReferenceNode; sourceTree = "<group>"; };
 		456FCC98D03DFAE9AFEC271B = {isa = PBXGroup; children = (
 					E102C308B0722DFFFEFF2415,
 					B574136FEE7957F7439CB346,
@@ -1740,15 +1680,9 @@
 					215E1BD79B5870D5356810F0,
 					F115ED75E977A54AAF036B2C,
 					AE3D7946F13CE32AE41DD1B7, ); name = Visualization; sourceTree = "<group>"; };
-		552D8D8CC92277F54C95F760 = {isa = PBXGroup; children = (
-					B25949076F9BB831C5862415,
-					540CD9ED0C719DB1DAECA37E,
-					3734FF118787377E4C8741D1,
-					513D20023796491A24EC58A7, ); name = WiFiOutput; sourceTree = "<group>"; };
 		83A3E005DDFCC55F277EEDA5 = {isa = PBXGroup; children = (
 					9C8E3549A602E74DCFC44244,
 					9C7703C01E449614C1CD884D,
-					7BE07AA81C59DD7252F709E6,
 					B3EC4C17E1555DCD89B1B62C,
 					3EE4DBB6ED04E5B9DA85CDF9,
 					DEA24DC5AC8325310FB40395,
@@ -1758,10 +1692,8 @@
 					AE49B2C17B100D5B4F81F694,
 					10488A99117FC063889F25C7,
 					1C714E881A404D148C6170CD,
-					85403FACC153147273CEB933,
 					5FAE90CAD8DAA5CE48855F38,
 					29B817DBDA971F3DA7039F93,
-					518310F63C8005A8D097A1D8,
 					A1678CA8F8E882F5D7EFDB3E,
 					F12EEDE785E2D38F654AE1B1,
 					2AC55A2E70C6CF50A8C46F6B,
@@ -1772,7 +1704,6 @@
 					0E7092A11A3C96E5ECA71CDA,
 					2206667D18B61DE29C856408,
 					70AFD6EB1539BF938821F7A8,
-					21389ED521B378402213EFC3,
 					456FCC98D03DFAE9AFEC271B,
 					3DE49DED45C5CDD8D184E248,
 					C451C93CE8C359C1A4BD23C7,
@@ -1782,8 +1713,7 @@
 					7B2364D82845C97E7A1B1924,
 					D3F8D770C9E60B5BA2CCBC68,
 					E2624A71F15AE5C96B34505B,
-					C4B85C0286AC2510730355E3,
-					552D8D8CC92277F54C95F760, ); name = Processors; sourceTree = "<group>"; };
+					C4B85C0286AC2510730355E3, ); name = Processors; sourceTree = "<group>"; };
 		1D78FCCF430CD91FD1DBD95B = {isa = PBXGroup; children = (
 					AF28CAB9C7531EF7422602E1,
 					A186E03EC7A6A7E657F38300,
@@ -2931,8 +2861,8 @@
 					"_DEBUG=1",
 					"DEBUG=1",
 					"JUCER_XCODE_MAC_F6D2F4CF=1",
-					"JUCE_APP_VERSION=0.3.3",
-					"JUCE_APP_VERSION_HEX=0x303", );
+					"JUCE_APP_VERSION=0.3.4",
+					"JUCE_APP_VERSION_HEX=0x304", );
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 				HEADER_SEARCH_PATHS = ("../../JuceLibraryCode", "../../JuceLibraryCode/modules", "/opt/local/include", "/usr/local/include", "$(inherited)");
 				INFOPLIST_FILE = Info.plist;
@@ -2953,8 +2883,8 @@
 					"_NDEBUG=1",
 					"NDEBUG=1",
 					"JUCER_XCODE_MAC_F6D2F4CF=1",
-					"JUCE_APP_VERSION=0.3.3",
-					"JUCE_APP_VERSION_HEX=0x303", );
+					"JUCE_APP_VERSION=0.3.4",
+					"JUCE_APP_VERSION_HEX=0x304", );
 				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 				HEADER_SEARCH_PATHS = ("../../JuceLibraryCode", "../../JuceLibraryCode/modules", "/opt/local/include", "/usr/local/include", "$(inherited)");
@@ -3012,7 +2942,6 @@
 					527EB48A4A9C2F4FF1BC4FB2,
 					8352817FEDC7542D3E65B49A,
 					44DB81313BDDF1ECB6AD33FE,
-					64FC0EA0C132341C1C3E98E1,
 					C45009DBCD71E9E234BFCE97,
 					E6038800731F7C747D181A51,
 					FFCA1C44C024BCA1878F49FE,
@@ -3024,8 +2953,6 @@
 					DA836EC803E4FF4EDEBE6386,
 					702C9BFCE865CB6C6B8BFB0D,
 					739573501D1D440A72C5C2E5,
-					955561F4FF4484648FDB9F73,
-					6B67D7B6301182C7621294B6,
 					FAE745870674A07A65690433,
 					24CC7E9A7E87F762D4AB0467,
 					9252537C12447F047243DEE9,
@@ -3061,15 +2988,10 @@
 					24800AF87AD21CE652552EDE,
 					0203D029CE7420984F737E51,
 					3BAE3A1FD0834E798B8602BF,
-					1A415CE073017DDDA7F2E234,
-					63B3CC385B0988C7ABA3B07B,
 					B49852F77C0C392C159A1914,
 					9F431DA23C92CA0F8E3A2A28,
 					BFFD23BD72ECEC9E54936061,
 					FA882EEE408CBBDC7BD90F14,
-					0E62780F9978861D5D2BCF71,
-					E13848868678C0655147C59D,
-					01646F263C203BB412580CB8,
 					6D00BABD3FE1AA0EAA267C1C,
 					AD371C6F383F03EF392B6581,
 					4EF2825142BBAA76FD55FE26,
@@ -3093,8 +3015,6 @@
 					093F0BA37D6C91C7E92AB658,
 					620CF6292EFB911F15916EA6,
 					7B50AD44D4F9610CE4A43414,
-					A5A90525A975EC3B1E40086E,
-					79FC643530710BF2885932C1,
 					69B5045877D4C674E8A4967F,
 					97105BCBC5B1BE4E86D48899,
 					790911EDF00A4BF77327D99A,
@@ -3120,8 +3040,6 @@
 					1B620FC17AAECA4C5DE741E2,
 					19BB86C918F89D1377F8A0E1,
 					89223664B6CB2A912E36B091,
-					AEE1F2B70ED51F7AFEF4E93B,
-					74D0CA6935D890153FB58C56,
 					8F39AD3F7938EFE82D06E89F,
 					BA608CEFC85F7AB9E30E0EB3,
 					D499273B65D901D0A101CAAA,
diff --git a/Builds/VisualStudio2012/open-ephys.vcxproj b/Builds/VisualStudio2012/open-ephys.vcxproj
index a5d50392bfc83a22fa091a8af9c18449b81b8876..1096a85715e768cea0a9d2678b818c6ca66a8bf9 100644
--- a/Builds/VisualStudio2012/open-ephys.vcxproj
+++ b/Builds/VisualStudio2012/open-ephys.vcxproj
@@ -89,7 +89,7 @@
       <Optimization>Disabled</Optimization>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;../../Resources/windows-libs/HDF5/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.3.3;JUCE_APP_VERSION_HEX=0x303;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.3.4;JUCE_APP_VERSION_HEX=0x304;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <PrecompiledHeader/>
@@ -135,7 +135,7 @@
     <ClCompile>
       <Optimization>Full</Optimization>
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;../../Resources/windows-libs/HDF5/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.3.3;JUCE_APP_VERSION_HEX=0x303;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.3.4;JUCE_APP_VERSION_HEX=0x304;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <PrecompiledHeader/>
@@ -183,7 +183,7 @@
       <Optimization>Disabled</Optimization>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;../../Resources/windows-libs/HDF5/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.3.3;JUCE_APP_VERSION_HEX=0x303;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.3.4;JUCE_APP_VERSION_HEX=0x304;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <PrecompiledHeader/>
@@ -227,7 +227,7 @@
     <ClCompile>
       <Optimization>Full</Optimization>
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;../../Resources/windows-libs/HDF5/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.3.3;JUCE_APP_VERSION_HEX=0x303;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.3.4;JUCE_APP_VERSION_HEX=0x304;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <PrecompiledHeader/>
@@ -270,7 +270,6 @@
     <ClCompile Include="..\..\Source\Processors\ArduinoOutput\ArduinoOutputEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\AudioNode\AudioEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\AudioNode\AudioNode.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\AudioResamplingNode\AudioResamplingNode.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Channel\Channel.cpp"/>
     <ClCompile Include="..\..\Source\Processors\ChannelMappingNode\ChannelMappingEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\ChannelMappingNode\ChannelMappingNode.cpp"/>
@@ -282,8 +281,6 @@
     <ClCompile Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000evalboard.cpp"/>
     <ClCompile Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000registers.cpp"/>
     <ClCompile Include="..\..\Source\Processors\DataThreads\RHD2000Thread.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\DataThreads\FileReaderThread.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\DataThreads\FPGAThread.cpp"/>
     <ClCompile Include="..\..\Source\Processors\DataThreads\DataBuffer.cpp"/>
     <ClCompile Include="..\..\Source\Processors\DataThreads\DataThread.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Dsp\Bessel.cpp"/>
@@ -319,15 +316,10 @@
     <ClCompile Include="..\..\Source\Processors\FileReader\FileReaderEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\FilterNode\FilterEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\FilterNode\FilterNode.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\FPGAOutput\FPGAOutput.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\FPGAOutput\FPGAOutputEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\GenericProcessor\GenericProcessor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayCanvas.cpp"/>
     <ClCompile Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayNode.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageCanvas.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageEditor.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageNode.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Merger\Merger.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Merger\MergerEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\MessageCenter\MessageCenter.cpp"/>
@@ -351,8 +343,6 @@
     <ClCompile Include="..\..\Source\Processors\PSTH\PeriStimulusTimeHistogramNode.cpp"/>
     <ClCompile Include="..\..\Source\Processors\PSTH\tictoc.cpp"/>
     <ClCompile Include="..\..\Source\Processors\PSTH\TrialCircularBuffer.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\ReferenceNode\ReferenceNode.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\ReferenceNode\ReferenceNodeEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\ResamplingNode\ResamplingNode.cpp"/>
     <ClCompile Include="..\..\Source\Processors\ResamplingNode\ResamplingNodeEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Serial\PulsePal.cpp"/>
@@ -378,8 +368,6 @@
     <ClCompile Include="..\..\Source\Processors\Visualization\DataWindow.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Visualization\SpikeObject.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Visualization\MatlabLikePlot.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\WiFiOutput\WiFiOutput.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\WiFiOutput\WiFiOutputEditor.cpp"/>
     <ClCompile Include="..\..\Source\UI\EcubeDialogComponent.cpp"/>
     <ClCompile Include="..\..\Source\UI\CustomArrowButton.cpp"/>
     <ClCompile Include="..\..\Source\UI\GraphViewer.cpp"/>
@@ -1525,7 +1513,6 @@
     <ClInclude Include="..\..\Source\Processors\ArduinoOutput\ArduinoOutputEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\AudioNode\AudioEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\AudioNode\AudioNode.h"/>
-    <ClInclude Include="..\..\Source\Processors\AudioResamplingNode\AudioResamplingNode.h"/>
     <ClInclude Include="..\..\Source\Processors\Channel\Channel.h"/>
     <ClInclude Include="..\..\Source\Processors\ChannelMappingNode\ChannelMappingEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\ChannelMappingNode\ChannelMappingNode.h"/>
@@ -1537,8 +1524,6 @@
     <ClInclude Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000evalboard.h"/>
     <ClInclude Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000registers.h"/>
     <ClInclude Include="..\..\Source\Processors\DataThreads\RHD2000Thread.h"/>
-    <ClInclude Include="..\..\Source\Processors\DataThreads\FileReaderThread.h"/>
-    <ClInclude Include="..\..\Source\Processors\DataThreads\FPGAThread.h"/>
     <ClInclude Include="..\..\Source\Processors\DataThreads\DataBuffer.h"/>
     <ClInclude Include="..\..\Source\Processors\DataThreads\DataThread.h"/>
     <ClInclude Include="..\..\Source\Processors\Dsp\Bessel.h"/>
@@ -1580,15 +1565,10 @@
     <ClInclude Include="..\..\Source\Processors\FileReader\FileReaderEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\FilterNode\FilterEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\FilterNode\FilterNode.h"/>
-    <ClInclude Include="..\..\Source\Processors\FPGAOutput\FPGAOutput.h"/>
-    <ClInclude Include="..\..\Source\Processors\FPGAOutput\FPGAOutputEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\GenericProcessor\GenericProcessor.h"/>
     <ClInclude Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayCanvas.h"/>
     <ClInclude Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayNode.h"/>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageCanvas.h"/>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageEditor.h"/>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageNode.h"/>
     <ClInclude Include="..\..\Source\Processors\Merger\Merger.h"/>
     <ClInclude Include="..\..\Source\Processors\Merger\MergerEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\MessageCenter\MessageCenter.h"/>
@@ -1612,8 +1592,6 @@
     <ClInclude Include="..\..\Source\Processors\PSTH\PeriStimulusTimeHistogramNode.h"/>
     <ClInclude Include="..\..\Source\Processors\PSTH\tictoc.h"/>
     <ClInclude Include="..\..\Source\Processors\PSTH\TrialCircularBuffer.h"/>
-    <ClInclude Include="..\..\Source\Processors\ReferenceNode\ReferenceNode.h"/>
-    <ClInclude Include="..\..\Source\Processors\ReferenceNode\ReferenceNodeEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\ResamplingNode\ResamplingNode.h"/>
     <ClInclude Include="..\..\Source\Processors\ResamplingNode\ResamplingNodeEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\Serial\PulsePal.h"/>
@@ -1641,8 +1619,6 @@
     <ClInclude Include="..\..\Source\Processors\Visualization\SpikeObject.h"/>
     <ClInclude Include="..\..\Source\Processors\Visualization\Visualizer.h"/>
     <ClInclude Include="..\..\Source\Processors\Visualization\MatlabLikePlot.h"/>
-    <ClInclude Include="..\..\Source\Processors\WiFiOutput\WiFiOutput.h"/>
-    <ClInclude Include="..\..\Source\Processors\WiFiOutput\WiFiOutputEditor.h"/>
     <ClInclude Include="..\..\Source\UI\EcubeDialogComponent.h"/>
     <ClInclude Include="..\..\Source\UI\CustomArrowButton.h"/>
     <ClInclude Include="..\..\Source\UI\GraphViewer.h"/>
diff --git a/Builds/VisualStudio2012/open-ephys.vcxproj.filters b/Builds/VisualStudio2012/open-ephys.vcxproj.filters
index 937da5cfa2fd273731fb7cac2f41720d21e74a55..b0ccd22aab60f10b7b3e6cf3a0075eda82c9906e 100644
--- a/Builds/VisualStudio2012/open-ephys.vcxproj.filters
+++ b/Builds/VisualStudio2012/open-ephys.vcxproj.filters
@@ -38,9 +38,6 @@
     <Filter Include="open-ephys\Source\Processors\AudioNode">
       <UniqueIdentifier>{117683A8-B332-1FBB-1FA0-8C6C7D231B69}</UniqueIdentifier>
     </Filter>
-    <Filter Include="open-ephys\Source\Processors\AudioResamplingNode">
-      <UniqueIdentifier>{BB0D2303-17CA-2E39-9765-7A701B2AE2F6}</UniqueIdentifier>
-    </Filter>
     <Filter Include="open-ephys\Source\Processors\Channel">
       <UniqueIdentifier>{7374BFF8-0BFC-382A-1DC3-F4B934CF25BC}</UniqueIdentifier>
     </Filter>
@@ -71,18 +68,12 @@
     <Filter Include="open-ephys\Source\Processors\FilterNode">
       <UniqueIdentifier>{189BB62E-5852-A4F3-AC79-704FAAE02870}</UniqueIdentifier>
     </Filter>
-    <Filter Include="open-ephys\Source\Processors\FPGAOutput">
-      <UniqueIdentifier>{995BE2D8-55CB-BBA8-8155-2EFE5F03F143}</UniqueIdentifier>
-    </Filter>
     <Filter Include="open-ephys\Source\Processors\GenericProcessor">
       <UniqueIdentifier>{223ADE1C-7B16-1075-5D22-4771767BF960}</UniqueIdentifier>
     </Filter>
     <Filter Include="open-ephys\Source\Processors\LfpDisplayNode">
       <UniqueIdentifier>{6F781BCA-7DB6-E933-BDDB-D2EAA51713B0}</UniqueIdentifier>
     </Filter>
-    <Filter Include="open-ephys\Source\Processors\LfpTriggeredAverageNode">
-      <UniqueIdentifier>{1150A21B-5E97-AC73-C141-CEF966829E71}</UniqueIdentifier>
-    </Filter>
     <Filter Include="open-ephys\Source\Processors\Merger">
       <UniqueIdentifier>{144C1CD2-E387-1D24-EFF3-C5238BD84182}</UniqueIdentifier>
     </Filter>
@@ -113,9 +104,6 @@
     <Filter Include="open-ephys\Source\Processors\PSTH">
       <UniqueIdentifier>{2714D3F1-1A51-5CEC-5EE2-26686D9EEAF8}</UniqueIdentifier>
     </Filter>
-    <Filter Include="open-ephys\Source\Processors\ReferenceNode">
-      <UniqueIdentifier>{763A6B4C-B0C6-BA22-7FAB-0DEEF8D66097}</UniqueIdentifier>
-    </Filter>
     <Filter Include="open-ephys\Source\Processors\ResamplingNode">
       <UniqueIdentifier>{3135385A-1E61-FB08-3E00-D5C52DFB1BC9}</UniqueIdentifier>
     </Filter>
@@ -146,9 +134,6 @@
     <Filter Include="open-ephys\Source\Processors\Visualization">
       <UniqueIdentifier>{851942D5-FED6-A7B2-6FAB-C278A247FE7A}</UniqueIdentifier>
     </Filter>
-    <Filter Include="open-ephys\Source\Processors\WiFiOutput">
-      <UniqueIdentifier>{F733C561-3FBD-E17D-CC23-601836ADF7E6}</UniqueIdentifier>
-    </Filter>
     <Filter Include="open-ephys\Source\UI">
       <UniqueIdentifier>{717A0FE3-E079-E4BD-8F50-15A1953825C5}</UniqueIdentifier>
     </Filter>
@@ -472,9 +457,6 @@
     <ClCompile Include="..\..\Source\Processors\AudioNode\AudioNode.cpp">
       <Filter>open-ephys\Source\Processors\AudioNode</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\AudioResamplingNode\AudioResamplingNode.cpp">
-      <Filter>open-ephys\Source\Processors\AudioResamplingNode</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\Channel\Channel.cpp">
       <Filter>open-ephys\Source\Processors\Channel</Filter>
     </ClCompile>
@@ -508,12 +490,6 @@
     <ClCompile Include="..\..\Source\Processors\DataThreads\RHD2000Thread.cpp">
       <Filter>open-ephys\Source\Processors\DataThreads</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\DataThreads\FileReaderThread.cpp">
-      <Filter>open-ephys\Source\Processors\DataThreads</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\DataThreads\FPGAThread.cpp">
-      <Filter>open-ephys\Source\Processors\DataThreads</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\DataThreads\DataBuffer.cpp">
       <Filter>open-ephys\Source\Processors\DataThreads</Filter>
     </ClCompile>
@@ -619,12 +595,6 @@
     <ClCompile Include="..\..\Source\Processors\FilterNode\FilterNode.cpp">
       <Filter>open-ephys\Source\Processors\FilterNode</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\FPGAOutput\FPGAOutput.cpp">
-      <Filter>open-ephys\Source\Processors\FPGAOutput</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\FPGAOutput\FPGAOutputEditor.cpp">
-      <Filter>open-ephys\Source\Processors\FPGAOutput</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\GenericProcessor\GenericProcessor.cpp">
       <Filter>open-ephys\Source\Processors\GenericProcessor</Filter>
     </ClCompile>
@@ -637,15 +607,6 @@
     <ClCompile Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayNode.cpp">
       <Filter>open-ephys\Source\Processors\LfpDisplayNode</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageCanvas.cpp">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageEditor.cpp">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageNode.cpp">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\Merger\Merger.cpp">
       <Filter>open-ephys\Source\Processors\Merger</Filter>
     </ClCompile>
@@ -715,12 +676,6 @@
     <ClCompile Include="..\..\Source\Processors\PSTH\TrialCircularBuffer.cpp">
       <Filter>open-ephys\Source\Processors\PSTH</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\ReferenceNode\ReferenceNode.cpp">
-      <Filter>open-ephys\Source\Processors\ReferenceNode</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\ReferenceNode\ReferenceNodeEditor.cpp">
-      <Filter>open-ephys\Source\Processors\ReferenceNode</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\ResamplingNode\ResamplingNode.cpp">
       <Filter>open-ephys\Source\Processors\ResamplingNode</Filter>
     </ClCompile>
@@ -796,12 +751,6 @@
     <ClCompile Include="..\..\Source\Processors\Visualization\MatlabLikePlot.cpp">
       <Filter>open-ephys\Source\Processors\Visualization</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\WiFiOutput\WiFiOutput.cpp">
-      <Filter>open-ephys\Source\Processors\WiFiOutput</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\WiFiOutput\WiFiOutputEditor.cpp">
-      <Filter>open-ephys\Source\Processors\WiFiOutput</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\UI\EcubeDialogComponent.cpp">
       <Filter>open-ephys\Source\UI</Filter>
     </ClCompile>
@@ -2094,9 +2043,6 @@
     <ClInclude Include="..\..\Source\Processors\AudioNode\AudioNode.h">
       <Filter>open-ephys\Source\Processors\AudioNode</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\AudioResamplingNode\AudioResamplingNode.h">
-      <Filter>open-ephys\Source\Processors\AudioResamplingNode</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\Channel\Channel.h">
       <Filter>open-ephys\Source\Processors\Channel</Filter>
     </ClInclude>
@@ -2130,12 +2076,6 @@
     <ClInclude Include="..\..\Source\Processors\DataThreads\RHD2000Thread.h">
       <Filter>open-ephys\Source\Processors\DataThreads</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\DataThreads\FileReaderThread.h">
-      <Filter>open-ephys\Source\Processors\DataThreads</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\DataThreads\FPGAThread.h">
-      <Filter>open-ephys\Source\Processors\DataThreads</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\DataThreads\DataBuffer.h">
       <Filter>open-ephys\Source\Processors\DataThreads</Filter>
     </ClInclude>
@@ -2259,12 +2199,6 @@
     <ClInclude Include="..\..\Source\Processors\FilterNode\FilterNode.h">
       <Filter>open-ephys\Source\Processors\FilterNode</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\FPGAOutput\FPGAOutput.h">
-      <Filter>open-ephys\Source\Processors\FPGAOutput</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\FPGAOutput\FPGAOutputEditor.h">
-      <Filter>open-ephys\Source\Processors\FPGAOutput</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\GenericProcessor\GenericProcessor.h">
       <Filter>open-ephys\Source\Processors\GenericProcessor</Filter>
     </ClInclude>
@@ -2277,15 +2211,6 @@
     <ClInclude Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayNode.h">
       <Filter>open-ephys\Source\Processors\LfpDisplayNode</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageCanvas.h">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageEditor.h">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageNode.h">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\Merger\Merger.h">
       <Filter>open-ephys\Source\Processors\Merger</Filter>
     </ClInclude>
@@ -2355,12 +2280,6 @@
     <ClInclude Include="..\..\Source\Processors\PSTH\TrialCircularBuffer.h">
       <Filter>open-ephys\Source\Processors\PSTH</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\ReferenceNode\ReferenceNode.h">
-      <Filter>open-ephys\Source\Processors\ReferenceNode</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\ReferenceNode\ReferenceNodeEditor.h">
-      <Filter>open-ephys\Source\Processors\ReferenceNode</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\ResamplingNode\ResamplingNode.h">
       <Filter>open-ephys\Source\Processors\ResamplingNode</Filter>
     </ClInclude>
@@ -2442,12 +2361,6 @@
     <ClInclude Include="..\..\Source\Processors\Visualization\MatlabLikePlot.h">
       <Filter>open-ephys\Source\Processors\Visualization</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\WiFiOutput\WiFiOutput.h">
-      <Filter>open-ephys\Source\Processors\WiFiOutput</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\WiFiOutput\WiFiOutputEditor.h">
-      <Filter>open-ephys\Source\Processors\WiFiOutput</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\UI\EcubeDialogComponent.h">
       <Filter>open-ephys\Source\UI</Filter>
     </ClInclude>
diff --git a/Builds/VisualStudio2012/resources.rc b/Builds/VisualStudio2012/resources.rc
index cc5759faef0b71cf1372bd7ab2c0762df6a84c49..9dca811221456380143e32719a2a4b2667ee81af 100644
--- a/Builds/VisualStudio2012/resources.rc
+++ b/Builds/VisualStudio2012/resources.rc
@@ -7,7 +7,7 @@
 #include <windows.h>
 
 VS_VERSION_INFO VERSIONINFO
-FILEVERSION  0,3,3,0
+FILEVERSION  0,3,4,0
 BEGIN
   BLOCK "StringFileInfo"
   BEGIN
@@ -15,9 +15,9 @@ BEGIN
     BEGIN
       VALUE "CompanyName",  "Open Ephys\0"
       VALUE "FileDescription",  "open-ephys\0"
-      VALUE "FileVersion",  "0.3.3\0"
+      VALUE "FileVersion",  "0.3.4\0"
       VALUE "ProductName",  "open-ephys\0"
-      VALUE "ProductVersion",  "0.3.3\0"
+      VALUE "ProductVersion",  "0.3.4\0"
     END
   END
 
diff --git a/Builds/VisualStudio2013/open-ephys.sln b/Builds/VisualStudio2013/open-ephys.sln
index 662031ed0931146b2134f1fc184c05eedda69cc9..59a9d10ba28a4b47817570df74b1433044daefbb 100644
--- a/Builds/VisualStudio2013/open-ephys.sln
+++ b/Builds/VisualStudio2013/open-ephys.sln
@@ -1,31 +1,21 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+Microsoft Visual Studio Solution File, Format Version 11.00
 # Visual Studio 2013
-VisualStudioVersion = 12.0.30501.0
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}"
+Project("{5A05F353-1D63-394C-DFB0-981BB2309002}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
-		Debug|x64 = Debug|x64
-		Debug64|Win32 = Debug64|Win32
-		Debug64|x64 = Debug64|x64
 		Release|Win32 = Release|Win32
-		Release|x64 = Release|x64
-		Release64|Win32 = Release64|Win32
+		Debug64|x64 = Debug64|x64
 		Release64|x64 = Release64|x64
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|Win32.ActiveCfg = Debug|Win32
 		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|Win32.Build.0 = Debug|Win32
-		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|x64.ActiveCfg = Debug|Win32
-		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|Win32.ActiveCfg = Debug64|x64
-		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.ActiveCfg = Debug64|x64
-		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.Build.0 = Debug64|x64
 		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|Win32.ActiveCfg = Release|Win32
 		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|Win32.Build.0 = Release|Win32
-		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|x64.ActiveCfg = Release|Win32
-		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|Win32.ActiveCfg = Release64|x64
+		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.ActiveCfg = Debug64|x64
+		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.Build.0 = Debug64|x64
 		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|x64.ActiveCfg = Release64|x64
 		{9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|x64.Build.0 = Release64|x64
 	EndGlobalSection
diff --git a/Builds/VisualStudio2013/open-ephys.vcxproj b/Builds/VisualStudio2013/open-ephys.vcxproj
index ae72d3d461febee00924cea722b54e0998733d28..32fea9560b293910ff4a354f2949343c33df6497 100644
--- a/Builds/VisualStudio2013/open-ephys.vcxproj
+++ b/Builds/VisualStudio2013/open-ephys.vcxproj
@@ -89,7 +89,7 @@
       <Optimization>Disabled</Optimization>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;../../Resources/windows-libs/HDF5/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.3;JUCE_APP_VERSION_HEX=0x303;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.4;JUCE_APP_VERSION_HEX=0x304;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <PrecompiledHeader/>
@@ -136,7 +136,7 @@
     <ClCompile>
       <Optimization>Full</Optimization>
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;../../Resources/windows-libs/HDF5/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.3;JUCE_APP_VERSION_HEX=0x303;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.4;JUCE_APP_VERSION_HEX=0x304;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <PrecompiledHeader/>
@@ -185,7 +185,7 @@
       <Optimization>Disabled</Optimization>
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;../../Resources/windows-libs/HDF5/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.3;JUCE_APP_VERSION_HEX=0x303;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.4;JUCE_APP_VERSION_HEX=0x304;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <PrecompiledHeader/>
@@ -230,7 +230,7 @@
     <ClCompile>
       <Optimization>Full</Optimization>
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;../../Resources/windows-libs/HDF5/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.3;JUCE_APP_VERSION_HEX=0x303;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.4;JUCE_APP_VERSION_HEX=0x304;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <RuntimeTypeInfo>true</RuntimeTypeInfo>
       <PrecompiledHeader/>
@@ -274,7 +274,6 @@
     <ClCompile Include="..\..\Source\Processors\ArduinoOutput\ArduinoOutputEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\AudioNode\AudioEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\AudioNode\AudioNode.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\AudioResamplingNode\AudioResamplingNode.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Channel\Channel.cpp"/>
     <ClCompile Include="..\..\Source\Processors\ChannelMappingNode\ChannelMappingEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\ChannelMappingNode\ChannelMappingNode.cpp"/>
@@ -286,8 +285,6 @@
     <ClCompile Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000evalboard.cpp"/>
     <ClCompile Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000registers.cpp"/>
     <ClCompile Include="..\..\Source\Processors\DataThreads\RHD2000Thread.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\DataThreads\FileReaderThread.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\DataThreads\FPGAThread.cpp"/>
     <ClCompile Include="..\..\Source\Processors\DataThreads\DataBuffer.cpp"/>
     <ClCompile Include="..\..\Source\Processors\DataThreads\DataThread.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Dsp\Bessel.cpp"/>
@@ -323,15 +320,10 @@
     <ClCompile Include="..\..\Source\Processors\FileReader\FileReaderEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\FilterNode\FilterEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\FilterNode\FilterNode.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\FPGAOutput\FPGAOutput.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\FPGAOutput\FPGAOutputEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\GenericProcessor\GenericProcessor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayCanvas.cpp"/>
     <ClCompile Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayNode.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageCanvas.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageEditor.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageNode.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Merger\Merger.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Merger\MergerEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\MessageCenter\MessageCenter.cpp"/>
@@ -355,8 +347,6 @@
     <ClCompile Include="..\..\Source\Processors\PSTH\PeriStimulusTimeHistogramNode.cpp"/>
     <ClCompile Include="..\..\Source\Processors\PSTH\tictoc.cpp"/>
     <ClCompile Include="..\..\Source\Processors\PSTH\TrialCircularBuffer.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\ReferenceNode\ReferenceNode.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\ReferenceNode\ReferenceNodeEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\ResamplingNode\ResamplingNode.cpp"/>
     <ClCompile Include="..\..\Source\Processors\ResamplingNode\ResamplingNodeEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Serial\PulsePal.cpp"/>
@@ -382,8 +372,6 @@
     <ClCompile Include="..\..\Source\Processors\Visualization\DataWindow.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Visualization\SpikeObject.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Visualization\MatlabLikePlot.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\WiFiOutput\WiFiOutput.cpp"/>
-    <ClCompile Include="..\..\Source\Processors\WiFiOutput\WiFiOutputEditor.cpp"/>
     <ClCompile Include="..\..\Source\UI\EcubeDialogComponent.cpp"/>
     <ClCompile Include="..\..\Source\UI\CustomArrowButton.cpp"/>
     <ClCompile Include="..\..\Source\UI\GraphViewer.cpp"/>
@@ -1529,7 +1517,6 @@
     <ClInclude Include="..\..\Source\Processors\ArduinoOutput\ArduinoOutputEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\AudioNode\AudioEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\AudioNode\AudioNode.h"/>
-    <ClInclude Include="..\..\Source\Processors\AudioResamplingNode\AudioResamplingNode.h"/>
     <ClInclude Include="..\..\Source\Processors\Channel\Channel.h"/>
     <ClInclude Include="..\..\Source\Processors\ChannelMappingNode\ChannelMappingEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\ChannelMappingNode\ChannelMappingNode.h"/>
@@ -1541,8 +1528,6 @@
     <ClInclude Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000evalboard.h"/>
     <ClInclude Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000registers.h"/>
     <ClInclude Include="..\..\Source\Processors\DataThreads\RHD2000Thread.h"/>
-    <ClInclude Include="..\..\Source\Processors\DataThreads\FileReaderThread.h"/>
-    <ClInclude Include="..\..\Source\Processors\DataThreads\FPGAThread.h"/>
     <ClInclude Include="..\..\Source\Processors\DataThreads\DataBuffer.h"/>
     <ClInclude Include="..\..\Source\Processors\DataThreads\DataThread.h"/>
     <ClInclude Include="..\..\Source\Processors\Dsp\Bessel.h"/>
@@ -1584,15 +1569,10 @@
     <ClInclude Include="..\..\Source\Processors\FileReader\FileReaderEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\FilterNode\FilterEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\FilterNode\FilterNode.h"/>
-    <ClInclude Include="..\..\Source\Processors\FPGAOutput\FPGAOutput.h"/>
-    <ClInclude Include="..\..\Source\Processors\FPGAOutput\FPGAOutputEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\GenericProcessor\GenericProcessor.h"/>
     <ClInclude Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayCanvas.h"/>
     <ClInclude Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayNode.h"/>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageCanvas.h"/>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageEditor.h"/>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageNode.h"/>
     <ClInclude Include="..\..\Source\Processors\Merger\Merger.h"/>
     <ClInclude Include="..\..\Source\Processors\Merger\MergerEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\MessageCenter\MessageCenter.h"/>
@@ -1616,8 +1596,6 @@
     <ClInclude Include="..\..\Source\Processors\PSTH\PeriStimulusTimeHistogramNode.h"/>
     <ClInclude Include="..\..\Source\Processors\PSTH\tictoc.h"/>
     <ClInclude Include="..\..\Source\Processors\PSTH\TrialCircularBuffer.h"/>
-    <ClInclude Include="..\..\Source\Processors\ReferenceNode\ReferenceNode.h"/>
-    <ClInclude Include="..\..\Source\Processors\ReferenceNode\ReferenceNodeEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\ResamplingNode\ResamplingNode.h"/>
     <ClInclude Include="..\..\Source\Processors\ResamplingNode\ResamplingNodeEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\Serial\PulsePal.h"/>
@@ -1645,8 +1623,6 @@
     <ClInclude Include="..\..\Source\Processors\Visualization\SpikeObject.h"/>
     <ClInclude Include="..\..\Source\Processors\Visualization\Visualizer.h"/>
     <ClInclude Include="..\..\Source\Processors\Visualization\MatlabLikePlot.h"/>
-    <ClInclude Include="..\..\Source\Processors\WiFiOutput\WiFiOutput.h"/>
-    <ClInclude Include="..\..\Source\Processors\WiFiOutput\WiFiOutputEditor.h"/>
     <ClInclude Include="..\..\Source\UI\EcubeDialogComponent.h"/>
     <ClInclude Include="..\..\Source\UI\CustomArrowButton.h"/>
     <ClInclude Include="..\..\Source\UI\GraphViewer.h"/>
diff --git a/Builds/VisualStudio2013/open-ephys.vcxproj.filters b/Builds/VisualStudio2013/open-ephys.vcxproj.filters
index dc72e411330d13256b1875f07360900789a7679f..1251522bb6537167fe39418f84eefb817ea90604 100644
--- a/Builds/VisualStudio2013/open-ephys.vcxproj.filters
+++ b/Builds/VisualStudio2013/open-ephys.vcxproj.filters
@@ -38,9 +38,6 @@
     <Filter Include="open-ephys\Source\Processors\AudioNode">
       <UniqueIdentifier>{117683A8-B332-1FBB-1FA0-8C6C7D231B69}</UniqueIdentifier>
     </Filter>
-    <Filter Include="open-ephys\Source\Processors\AudioResamplingNode">
-      <UniqueIdentifier>{BB0D2303-17CA-2E39-9765-7A701B2AE2F6}</UniqueIdentifier>
-    </Filter>
     <Filter Include="open-ephys\Source\Processors\Channel">
       <UniqueIdentifier>{7374BFF8-0BFC-382A-1DC3-F4B934CF25BC}</UniqueIdentifier>
     </Filter>
@@ -71,18 +68,12 @@
     <Filter Include="open-ephys\Source\Processors\FilterNode">
       <UniqueIdentifier>{189BB62E-5852-A4F3-AC79-704FAAE02870}</UniqueIdentifier>
     </Filter>
-    <Filter Include="open-ephys\Source\Processors\FPGAOutput">
-      <UniqueIdentifier>{995BE2D8-55CB-BBA8-8155-2EFE5F03F143}</UniqueIdentifier>
-    </Filter>
     <Filter Include="open-ephys\Source\Processors\GenericProcessor">
       <UniqueIdentifier>{223ADE1C-7B16-1075-5D22-4771767BF960}</UniqueIdentifier>
     </Filter>
     <Filter Include="open-ephys\Source\Processors\LfpDisplayNode">
       <UniqueIdentifier>{6F781BCA-7DB6-E933-BDDB-D2EAA51713B0}</UniqueIdentifier>
     </Filter>
-    <Filter Include="open-ephys\Source\Processors\LfpTriggeredAverageNode">
-      <UniqueIdentifier>{1150A21B-5E97-AC73-C141-CEF966829E71}</UniqueIdentifier>
-    </Filter>
     <Filter Include="open-ephys\Source\Processors\Merger">
       <UniqueIdentifier>{144C1CD2-E387-1D24-EFF3-C5238BD84182}</UniqueIdentifier>
     </Filter>
@@ -113,9 +104,6 @@
     <Filter Include="open-ephys\Source\Processors\PSTH">
       <UniqueIdentifier>{2714D3F1-1A51-5CEC-5EE2-26686D9EEAF8}</UniqueIdentifier>
     </Filter>
-    <Filter Include="open-ephys\Source\Processors\ReferenceNode">
-      <UniqueIdentifier>{763A6B4C-B0C6-BA22-7FAB-0DEEF8D66097}</UniqueIdentifier>
-    </Filter>
     <Filter Include="open-ephys\Source\Processors\ResamplingNode">
       <UniqueIdentifier>{3135385A-1E61-FB08-3E00-D5C52DFB1BC9}</UniqueIdentifier>
     </Filter>
@@ -146,9 +134,6 @@
     <Filter Include="open-ephys\Source\Processors\Visualization">
       <UniqueIdentifier>{851942D5-FED6-A7B2-6FAB-C278A247FE7A}</UniqueIdentifier>
     </Filter>
-    <Filter Include="open-ephys\Source\Processors\WiFiOutput">
-      <UniqueIdentifier>{F733C561-3FBD-E17D-CC23-601836ADF7E6}</UniqueIdentifier>
-    </Filter>
     <Filter Include="open-ephys\Source\UI">
       <UniqueIdentifier>{717A0FE3-E079-E4BD-8F50-15A1953825C5}</UniqueIdentifier>
     </Filter>
@@ -472,9 +457,6 @@
     <ClCompile Include="..\..\Source\Processors\AudioNode\AudioNode.cpp">
       <Filter>open-ephys\Source\Processors\AudioNode</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\AudioResamplingNode\AudioResamplingNode.cpp">
-      <Filter>open-ephys\Source\Processors\AudioResamplingNode</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\Channel\Channel.cpp">
       <Filter>open-ephys\Source\Processors\Channel</Filter>
     </ClCompile>
@@ -508,12 +490,6 @@
     <ClCompile Include="..\..\Source\Processors\DataThreads\RHD2000Thread.cpp">
       <Filter>open-ephys\Source\Processors\DataThreads</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\DataThreads\FileReaderThread.cpp">
-      <Filter>open-ephys\Source\Processors\DataThreads</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\DataThreads\FPGAThread.cpp">
-      <Filter>open-ephys\Source\Processors\DataThreads</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\DataThreads\DataBuffer.cpp">
       <Filter>open-ephys\Source\Processors\DataThreads</Filter>
     </ClCompile>
@@ -619,12 +595,6 @@
     <ClCompile Include="..\..\Source\Processors\FilterNode\FilterNode.cpp">
       <Filter>open-ephys\Source\Processors\FilterNode</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\FPGAOutput\FPGAOutput.cpp">
-      <Filter>open-ephys\Source\Processors\FPGAOutput</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\FPGAOutput\FPGAOutputEditor.cpp">
-      <Filter>open-ephys\Source\Processors\FPGAOutput</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\GenericProcessor\GenericProcessor.cpp">
       <Filter>open-ephys\Source\Processors\GenericProcessor</Filter>
     </ClCompile>
@@ -637,15 +607,6 @@
     <ClCompile Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayNode.cpp">
       <Filter>open-ephys\Source\Processors\LfpDisplayNode</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageCanvas.cpp">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageEditor.cpp">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageNode.cpp">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\Merger\Merger.cpp">
       <Filter>open-ephys\Source\Processors\Merger</Filter>
     </ClCompile>
@@ -715,12 +676,6 @@
     <ClCompile Include="..\..\Source\Processors\PSTH\TrialCircularBuffer.cpp">
       <Filter>open-ephys\Source\Processors\PSTH</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\ReferenceNode\ReferenceNode.cpp">
-      <Filter>open-ephys\Source\Processors\ReferenceNode</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\ReferenceNode\ReferenceNodeEditor.cpp">
-      <Filter>open-ephys\Source\Processors\ReferenceNode</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\ResamplingNode\ResamplingNode.cpp">
       <Filter>open-ephys\Source\Processors\ResamplingNode</Filter>
     </ClCompile>
@@ -796,12 +751,6 @@
     <ClCompile Include="..\..\Source\Processors\Visualization\MatlabLikePlot.cpp">
       <Filter>open-ephys\Source\Processors\Visualization</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\WiFiOutput\WiFiOutput.cpp">
-      <Filter>open-ephys\Source\Processors\WiFiOutput</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\Source\Processors\WiFiOutput\WiFiOutputEditor.cpp">
-      <Filter>open-ephys\Source\Processors\WiFiOutput</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\Source\UI\EcubeDialogComponent.cpp">
       <Filter>open-ephys\Source\UI</Filter>
     </ClCompile>
@@ -2094,9 +2043,6 @@
     <ClInclude Include="..\..\Source\Processors\AudioNode\AudioNode.h">
       <Filter>open-ephys\Source\Processors\AudioNode</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\AudioResamplingNode\AudioResamplingNode.h">
-      <Filter>open-ephys\Source\Processors\AudioResamplingNode</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\Channel\Channel.h">
       <Filter>open-ephys\Source\Processors\Channel</Filter>
     </ClInclude>
@@ -2130,12 +2076,6 @@
     <ClInclude Include="..\..\Source\Processors\DataThreads\RHD2000Thread.h">
       <Filter>open-ephys\Source\Processors\DataThreads</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\DataThreads\FileReaderThread.h">
-      <Filter>open-ephys\Source\Processors\DataThreads</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\DataThreads\FPGAThread.h">
-      <Filter>open-ephys\Source\Processors\DataThreads</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\DataThreads\DataBuffer.h">
       <Filter>open-ephys\Source\Processors\DataThreads</Filter>
     </ClInclude>
@@ -2259,12 +2199,6 @@
     <ClInclude Include="..\..\Source\Processors\FilterNode\FilterNode.h">
       <Filter>open-ephys\Source\Processors\FilterNode</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\FPGAOutput\FPGAOutput.h">
-      <Filter>open-ephys\Source\Processors\FPGAOutput</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\FPGAOutput\FPGAOutputEditor.h">
-      <Filter>open-ephys\Source\Processors\FPGAOutput</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\GenericProcessor\GenericProcessor.h">
       <Filter>open-ephys\Source\Processors\GenericProcessor</Filter>
     </ClInclude>
@@ -2277,15 +2211,6 @@
     <ClInclude Include="..\..\Source\Processors\LfpDisplayNode\LfpDisplayNode.h">
       <Filter>open-ephys\Source\Processors\LfpDisplayNode</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageCanvas.h">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageEditor.h">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\LfpTriggeredAverageNode\LfpTriggeredAverageNode.h">
-      <Filter>open-ephys\Source\Processors\LfpTriggeredAverageNode</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\Merger\Merger.h">
       <Filter>open-ephys\Source\Processors\Merger</Filter>
     </ClInclude>
@@ -2355,12 +2280,6 @@
     <ClInclude Include="..\..\Source\Processors\PSTH\TrialCircularBuffer.h">
       <Filter>open-ephys\Source\Processors\PSTH</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\ReferenceNode\ReferenceNode.h">
-      <Filter>open-ephys\Source\Processors\ReferenceNode</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\ReferenceNode\ReferenceNodeEditor.h">
-      <Filter>open-ephys\Source\Processors\ReferenceNode</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\ResamplingNode\ResamplingNode.h">
       <Filter>open-ephys\Source\Processors\ResamplingNode</Filter>
     </ClInclude>
@@ -2442,12 +2361,6 @@
     <ClInclude Include="..\..\Source\Processors\Visualization\MatlabLikePlot.h">
       <Filter>open-ephys\Source\Processors\Visualization</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\WiFiOutput\WiFiOutput.h">
-      <Filter>open-ephys\Source\Processors\WiFiOutput</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\Source\Processors\WiFiOutput\WiFiOutputEditor.h">
-      <Filter>open-ephys\Source\Processors\WiFiOutput</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\Source\UI\EcubeDialogComponent.h">
       <Filter>open-ephys\Source\UI</Filter>
     </ClInclude>
diff --git a/Builds/VisualStudio2013/resources.rc b/Builds/VisualStudio2013/resources.rc
index cc5759faef0b71cf1372bd7ab2c0762df6a84c49..9dca811221456380143e32719a2a4b2667ee81af 100644
--- a/Builds/VisualStudio2013/resources.rc
+++ b/Builds/VisualStudio2013/resources.rc
@@ -7,7 +7,7 @@
 #include <windows.h>
 
 VS_VERSION_INFO VERSIONINFO
-FILEVERSION  0,3,3,0
+FILEVERSION  0,3,4,0
 BEGIN
   BLOCK "StringFileInfo"
   BEGIN
@@ -15,9 +15,9 @@ BEGIN
     BEGIN
       VALUE "CompanyName",  "Open Ephys\0"
       VALUE "FileDescription",  "open-ephys\0"
-      VALUE "FileVersion",  "0.3.3\0"
+      VALUE "FileVersion",  "0.3.4\0"
       VALUE "ProductName",  "open-ephys\0"
-      VALUE "ProductVersion",  "0.3.3\0"
+      VALUE "ProductVersion",  "0.3.4\0"
     END
   END
 
diff --git a/JuceLibraryCode/JuceHeader.h b/JuceLibraryCode/JuceHeader.h
index 94eac05313a9f059ed97531c4e75e7bb3353edf6..fb111b6443002a8d2a511e978f5e51fe63217d21 100644
--- a/JuceLibraryCode/JuceHeader.h
+++ b/JuceLibraryCode/JuceHeader.h
@@ -39,8 +39,8 @@
 namespace ProjectInfo
 {
     const char* const  projectName    = "open-ephys";
-    const char* const  versionString  = "0.3.3";
-    const int          versionNumber  = 0x303;
+    const char* const  versionString  = "0.3.4";
+    const int          versionNumber  = 0x304;
 }
 
 #endif   // __APPHEADERFILE_YNSYIRR__
diff --git a/Source/Processors/ArduinoOutput/ArduinoOutput.cpp b/Source/Processors/ArduinoOutput/ArduinoOutput.cpp
index 053020e76980a015ff39f4b531e81b38f337fb8c..a26c70c3a3965cfd6ff9a39ea2518a30d7504657 100755
--- a/Source/Processors/ArduinoOutput/ArduinoOutput.cpp
+++ b/Source/Processors/ArduinoOutput/ArduinoOutput.cpp
@@ -138,8 +138,7 @@ bool ArduinoOutput::disable()
 }
 
 void ArduinoOutput::process(AudioSampleBuffer& buffer,
-                            MidiBuffer& events,
-                            int& nSamples)
+                            MidiBuffer& events)
 {
 
 
diff --git a/Source/Processors/ArduinoOutput/ArduinoOutput.h b/Source/Processors/ArduinoOutput/ArduinoOutput.h
index 86f6480dbedf6b8bdff342f5505bfd7f12847921..da49269f6c014c2da8d1d8094867225e9edaf43f 100755
--- a/Source/Processors/ArduinoOutput/ArduinoOutput.h
+++ b/Source/Processors/ArduinoOutput/ArduinoOutput.h
@@ -51,7 +51,7 @@ public:
     ~ArduinoOutput();
 
     /** Searches for events and triggers the Arduino output when appropriate. */
-    void process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& events);
 
     /** Currently unused. Future uses may include changing the TTL trigger channel
     or the output channel of the Arduino. */
diff --git a/Source/Processors/AudioNode/AudioNode.cpp b/Source/Processors/AudioNode/AudioNode.cpp
index 53d3339624768a4e73a505a4eb46cbb93b912d45..aaf2460194076bc1409580092b9de8523b1f515f 100755
--- a/Source/Processors/AudioNode/AudioNode.cpp
+++ b/Source/Processors/AudioNode/AudioNode.cpp
@@ -26,12 +26,10 @@
 #include "AudioNode.h"
 
 AudioNode::AudioNode()
-    : GenericProcessor("Audio Node"), audioEditor(0), volume(0.00001f), noiseGateLevel(0.0f),
-      bufferA(2,10000),
-      bufferB(2,10000)
+    : GenericProcessor("Audio Node"), audioEditor(0), volume(0.00001f), noiseGateLevel(0.0f)
 {
 
-    settings.numInputs = 2048;
+    settings.numInputs = 4096;
     settings.numOutputs = 2;
 
     // 128 inputs, 2 outputs (left and right channel)
@@ -39,19 +37,13 @@ AudioNode::AudioNode()
 
     nextAvailableChannel = 2; // keep first two channels empty
 
-    numSamplesExpected = 1024;
-
-    samplesInOverflowBuffer = 0;
-    samplesInBackupBuffer = 0;
+    tempBuffer = new AudioSampleBuffer(16, 1024);
 
 }
 
 
 AudioNode::~AudioNode()
 {
-
-
-
 }
 
 AudioProcessorEditor* AudioNode::createEditor()
@@ -71,9 +63,6 @@ void AudioNode::resetConnections()
 
     channelPointers.clear();
 
-    samplesInOverflowBuffer = 0;
-    samplesInBackupBuffer = 0;
-
 }
 
 void AudioNode::updateBufferSize()
@@ -165,24 +154,79 @@ void AudioNode::prepareToPlay(double sampleRate_, int estimatedSamplesPerBlock)
     // std::cout << "Processor sample rate: " << getSampleRate() << std::endl;
     // std::cout << "Audio card sample rate: " << sampleRate_ << std::endl;
     // std::cout << "Samples per block: " << estimatedSamplesPerBlock << std::endl;
+	if (sampleRate_ != destBufferSampleRate || estimatedSamplesPerBlock != estimatedSamples)
+	{
+		destBufferSampleRate = sampleRate_;
+		estimatedSamples = estimatedSamplesPerBlock;
+		recreateBuffers();
+	}
 
-    numSamplesExpected = (int)(getSampleRate()/sampleRate_*float(estimatedSamplesPerBlock)) + 1;
-    // processor sample rate divided by sound card sample rate
-
-    samplesInBackupBuffer = 0;
-    samplesInOverflowBuffer = 0;
+}
 
+void AudioNode::recreateBuffers()
+{
+	numSamplesExpected.clear();
+    samplesInBackupBuffer.clear();
+    samplesInOverflowBuffer.clear();
+    ratio.clear();
+    filters.clear();
     bufferA.clear();
     bufferB.clear();
+    bufferSwap.clear();
+
+    for (int i = 0; i < channelPointers.size(); i++)
+    {
+        // processor sample rate divided by sound card sample rate
+        numSamplesExpected.add((int)(channelPointers[i]->sampleRate/destBufferSampleRate*float(estimatedSamples)) + 1);
+        samplesInBackupBuffer.add(0);
+        samplesInOverflowBuffer.add(0);
+        sourceBufferSampleRate.add(channelPointers[i]->sampleRate);
+
+        filters.add(new Dsp::SmoothedFilterDesign<Dsp::RBJ::Design::LowPass, 1> (1024));
+
+        ratio.add(float(numSamplesExpected[i])/float(estimatedSamples));
+        updateFilter(i);
+
+        bufferA.add(new AudioSampleBuffer(1,10000));
+        bufferB.add(new AudioSampleBuffer(1,10000));
+        bufferSwap.add(false);
+
+    }
+
+    tempBuffer->setSize(getNumInputs(), 4096);
+}
+
+bool AudioNode::enable()
+{
+	recreateBuffers();
+	return true;
+}
+
+void AudioNode::updateFilter(int i)
+{
+
+    double cutoffFreq = (ratio[i] > 1.0) ? 2 * destBufferSampleRate  // downsample
+                        : destBufferSampleRate / 2; // upsample
+
+    double sampleFreq = (ratio[i] > 1.0) ? sourceBufferSampleRate[i] // downsample
+                        : destBufferSampleRate;  // upsample
+
+    Dsp::Params params;
+    params[0] = sampleFreq; // sample rate
+    params[1] = cutoffFreq; // cutoff frequency
+    params[2] = 1.25; //Q //
+
+    filters[i]->setParams(params);
 
-    bufferSwap = false;
 }
 
 void AudioNode::process(AudioSampleBuffer& buffer,
-                        MidiBuffer& midiMessages,
-                        int& nSamples)
+                        MidiBuffer& events)
 {
     float gain;
+    int valuesNeeded = buffer.getNumSamples(); // samples needed to fill out the buffer
+
+    //std::cout << "Buffer size: " << buffer.getNumChannels() << std::endl;
 
     // clear the left and right channels
     buffer.clear(0,0,buffer.getNumSamples());
@@ -194,186 +238,229 @@ void AudioNode::process(AudioSampleBuffer& buffer,
         AudioSampleBuffer* overflowBuffer;
         AudioSampleBuffer* backupBuffer;
 
-        if (!bufferSwap)
+        if (channelPointers.size() > 0) // we have some channels
         {
-            overflowBuffer = &bufferA;
-            backupBuffer = &bufferB;
-            bufferSwap = true;
-        }
-        else
-        {
-            overflowBuffer = &bufferB;
-            backupBuffer = &bufferA;
-            bufferSwap = false;
-        }
-
-        backupBuffer->clear();
 
-        samplesInOverflowBuffer = samplesInBackupBuffer; // size of buffer after last round
-        samplesInBackupBuffer = 0;
+            tempBuffer->clear();
 
-        int samplesToCopy = 0;
-        int orphanedSamples = 0;
-
-        if (channelPointers.size() > 0)
-        {
-            bool copiedBuffer = false;
-
-            for (int i = 2; i < buffer.getNumChannels(); i++)
+            for (int i = 0; i < buffer.getNumChannels()-2; i++) // cycle through them all
             {
 
-                if (channelPointers[i-2]->isMonitored)
+                if (channelPointers[i]->isMonitored)
                 {
 
-                    if (!copiedBuffer)
-                    {
-                        // 1. copy overflow buffer
+                    //std::cout << "Processing channel " << i << std::endl;
 
-                        samplesToCopy = ((samplesInOverflowBuffer <= numSamplesExpected) ?
-                                         samplesInOverflowBuffer :
-                                         numSamplesExpected);
+                    if (!bufferSwap[i])
+                    {
+                        overflowBuffer = bufferA[i];
+                        backupBuffer = bufferB[i];
 
-                        //  std::cout << " " << std::endl;
-                        //  std::cout << "Copying " << samplesToCopy << " samples from overflow buffer of " << samplesInOverflowBuffer << " samples." << std::endl;
+                        bufferSwap.set(i,true);
+                    }
+                    else
+                    {
+                        overflowBuffer = bufferB[i];
+                        backupBuffer = bufferA[i];
 
-                        if (samplesToCopy > 0)
-                        {
+                        bufferSwap.set(i,false);
+                    }
 
-                            buffer.addFrom(0,    // destination channel
-                                           0,                // destination start sample
-                                           *overflowBuffer,  // source
-                                           0,                // source channel
-                                           0,                // source start sample
-                                           samplesToCopy,    // number of samples
-                                           1.0f              // gain to apply
-                                          );
+                    backupBuffer->clear();
 
-                            buffer.addFrom(1,       // destination channel
-                                           0,           // destination start sample
-                                           *overflowBuffer,      // source
-                                           1,           // source channel
-                                           0,           // source start sample
-                                           samplesToCopy, //  number of samples
-                                           1.0f       // gain to apply
-                                          );
+                    samplesInOverflowBuffer.set(i,samplesInBackupBuffer[i]); // size of buffer after last round
+                    samplesInBackupBuffer.set(i,0);
 
+                    int orphanedSamples = 0;
 
-                            int leftoverSamples = samplesInOverflowBuffer - samplesToCopy;
+                    // 1. copy overflow buffer
 
-                            //     std::cout << "Samples remaining in overflow buffer: " << leftoverSamples << std::endl;
+                    int samplesToCopyFromOverflowBuffer =
+                        ((samplesInOverflowBuffer[i] <= numSamplesExpected[i]) ?
+                         samplesInOverflowBuffer[i] :
+                         numSamplesExpected[i]);
 
-                            if (leftoverSamples > 0)
-                            {
+                    //std::cout << "Copying " << samplesToCopyFromOverflowBuffer << " samples from overflow buffer of " << samplesInOverflowBuffer[i] << " samples." << std::endl;
 
-                                // move remaining samples to the backup buffer
+                    if (samplesToCopyFromOverflowBuffer > 0) // need to re-add samples from backup buffer
+                    {
 
-                                backupBuffer->addFrom(0, // destination channel
-                                                      0,                     // destination start sample
-                                                      *overflowBuffer,       // source
-                                                      0,                     // source channel
-                                                      samplesToCopy,         // source start sample
-                                                      leftoverSamples,       // number of samples
-                                                      1.0f                   // gain to apply
-                                                     );
+                        tempBuffer->addFrom(i,    // destination channel
+                                            0,                // destination start sample
+                                            *overflowBuffer,  // source
+                                            0,                // source channel
+                                            0,                // source start sample
+                                            samplesToCopyFromOverflowBuffer,    // number of samples
+                                            1.0f              // gain to apply
+                                           );
 
-                                backupBuffer->addFrom(1,  // destination channel
-                                                      0,                     // destination start sample
-                                                      *overflowBuffer,        // source
-                                                      1,                     // source channel
-                                                      samplesToCopy,         // source start sample
-                                                      leftoverSamples,       // number of samples
-                                                      1.0f                   // gain to apply
-                                                     );
+                        int leftoverSamples = samplesInOverflowBuffer[i] - samplesToCopyFromOverflowBuffer;
 
-                            }
+                        // std::cout << "Samples remaining in overflow buffer: " << leftoverSamples << std::endl;
 
-                            samplesInBackupBuffer = leftoverSamples;
+                        if (leftoverSamples > 0) // move remaining samples to the backup buffer
+                        {
 
+                            backupBuffer->addFrom(0, // destination channel
+                                                  0,                     // destination start sample
+                                                  *overflowBuffer,       // source
+                                                  0,                     // source channel
+                                                  samplesToCopyFromOverflowBuffer,         // source start sample
+                                                  leftoverSamples,       // number of samples
+                                                  1.0f                   // gain to apply
+                                                 );
                         }
 
-                        copiedBuffer = true;
-
-                    } // copying buffer
+                        samplesInBackupBuffer.set(i,leftoverSamples);
+                    }
 
-                    gain = volume/(float(0x7fff) * channelPointers[i-2]->bitVolts);
+                    gain = volume/(float(0x7fff) * channelPointers[i]->bitVolts);
                     // Data are floats in units of microvolts, so dividing by bitVolts and 0x7fff (max value for 16b signed)
                     // rescales to between -1 and +1. Audio output starts So, maximum gain applied to maximum data would be 10.
 
-                    int remainingSamples = numSamplesExpected - samplesToCopy;
+                    int remainingSamples = numSamplesExpected[i] - samplesToCopyFromOverflowBuffer;
 
-                    //  std::cout << "Copying " << remainingSamples << " samples from incoming buffer of " << nSamples << " samples." << std::endl;
+                    int samplesAvailable = numSamples.at(channelPointers[i]->sourceNodeId);
 
-                    int samplesToCopy2 = ((remainingSamples <= nSamples) ?
-                                          remainingSamples :
-                                          nSamples);
+                    int samplesToCopyFromIncomingBuffer = ((remainingSamples <= samplesAvailable) ?
+                                                           remainingSamples :
+                                                           samplesAvailable);
 
-                    if (samplesToCopy2 > 0)
+                    //std::cout << "Copying " << samplesToCopyFromIncomingBuffer << " samples from incoming buffer of " << samplesAvailable << " samples." << std::endl;
+
+
+                    if (samplesToCopyFromIncomingBuffer > 0)
                     {
 
-                        buffer.addFrom(0,       // destination channel
-                                       samplesToCopy,           // destination start sample
-                                       buffer,      // source
-                                       i,           // source channel
-                                       0,           // source start sample
-                                       remainingSamples, //  number of samples
-                                       gain       // gain to apply
-                                      );
-
-                        buffer.addFrom(1,       // destination channel
-                                       samplesToCopy,           // destination start sample
-                                       buffer,      // source
-                                       i,           // source channel
-                                       0,           // source start sample
-                                       remainingSamples, //  number of samples
-                                       gain       // gain to apply
-                                      );
+                        tempBuffer->addFrom(i,       // destination channel
+                                            samplesToCopyFromOverflowBuffer,           // destination start sample
+                                            buffer,      // source
+                                            i+2,           // source channel (add 2 to account for output channels)
+                                            0,           // source start sample
+                                            samplesToCopyFromIncomingBuffer, //  number of samples
+                                            gain       // gain to apply
+                                           );
+
+                        //if (destBufferPos == 0)
+                        //  std::cout << "Temp buffer 0 value: " << *tempBuffer->getReadPointer(i,0) << std::endl;
 
                     }
 
-                    orphanedSamples = nSamples - samplesToCopy2;
+                    orphanedSamples = samplesAvailable - samplesToCopyFromIncomingBuffer;
 
                     // std::cout << "Samples remaining in incoming buffer: " << orphanedSamples << std::endl;
 
-
-                    if (orphanedSamples > 0 && (samplesInBackupBuffer + orphanedSamples < backupBuffer->getNumSamples()))
+                    if (orphanedSamples > 0 && (samplesInBackupBuffer[i] + orphanedSamples < backupBuffer->getNumSamples()))
                     {
-                        backupBuffer->addFrom(0,       // destination channel
-                                              samplesInBackupBuffer,           // destination start sample
-                                              buffer,      // source
-                                              i,           // source channel
-                                              remainingSamples,           // source start sample
-                                              orphanedSamples, //  number of samples
-                                              gain       // gain to apply
-                                             );
 
-                        backupBuffer->addFrom(0,       // destination channel
-                                              samplesInBackupBuffer,           // destination start sample
-                                              buffer,      // source
-                                              i,           // source channel
-                                              remainingSamples,           // source start sample
-                                              orphanedSamples, //  number of samples
-                                              gain       // gain to apply
+                        backupBuffer->addFrom(0,                            // destination channel
+                                              samplesInBackupBuffer[i],     // destination start sample
+                                              buffer,                       // source
+                                              i+2,                          // source channel (add 2 to account for output channels)
+                                              remainingSamples,             // source start sample
+                                              orphanedSamples,              //  number of samples
+                                              gain                          // gain to apply
                                              );
 
-					}
-					else {
-						samplesInBackupBuffer = 0; // just throw out the buffer in the case of an overrun
-											       // not ideal, but the output still sounds fine
-					}
+                        samplesInBackupBuffer.set(i, samplesInBackupBuffer[i] + orphanedSamples);
 
-                    // Simple implementation of a "noise gate" on audio output
-                    expander.process(buffer.getWritePointer(0), // left channel
-                                       buffer.getWritePointer(1), // right channel
-                                       buffer.getNumSamples());
+                    }
 
-                }
-            }
+                    // now that our tempBuffer is ready, we can filter it and copy it into the
+                    // original buffer
 
-        }
+                    //std::cout << "Ratio = " << ratio[i] << ", gain = " << gain << std::endl;
+                    //std::cout << "Values needed = " << valuesNeeded << ", channel = " << i << std::endl;
 
-        samplesInBackupBuffer += orphanedSamples;
-        nSamples = numSamplesExpected;
+                    if (ratio[i] > 1.00001)
+                    {
+                        // pre-apply filter before downsampling
+                        float* ptr = tempBuffer->getWritePointer(i);
+                        filters[i]->process(numSamplesExpected[i], &ptr);
+                    }
 
+                    // initialize variables
+                    int sourceBufferPos = 0;
+                    int sourceBufferSize = numSamplesExpected[i];
+                    float subSampleOffset = 0.0;
+                    int nextPos = (sourceBufferPos + 1) % sourceBufferSize;
+
+                    int destBufferPos;
+
+                    // code modified from "juce_ResamplingAudioSource.cpp":
+
+                    for (destBufferPos = 0; destBufferPos < valuesNeeded; destBufferPos++)
+                    {
+                        float gain = 1.0;
+                        float alpha = (float) subSampleOffset;
+                        float invAlpha = 1.0f - alpha;
+
+                        // std::cout << "Copying sample " << sourceBufferPos << std::endl;
+
+                        buffer.addFrom(0,    // destChannel
+                                       destBufferPos,  // destSampleOffset
+                                       *tempBuffer,     // source
+                                       i,    // sourceChannel
+                                       sourceBufferPos,// sourceSampleOffset
+                                       1,        // number of samples
+                                       invAlpha*gain);      // gain to apply to source
+
+                        buffer.addFrom(0,    // destChannel
+                                       destBufferPos,   // destSampleOffset
+                                       *tempBuffer,     // source
+                                       i,      // sourceChannel
+                                       nextPos,      // sourceSampleOffset
+                                       1,        // number of samples
+                                       alpha*gain);       // gain to apply to source
+
+                        // if (destBufferPos == 0)
+                        //std::cout << "Output buffer 0 value: " << *buffer.getReadPointer(i+2,destBufferPos) << std::endl;
+
+                        subSampleOffset += ratio[i];
+
+                        while (subSampleOffset >= 1.0)
+                        {
+                            if (++sourceBufferPos >= sourceBufferSize)
+                                sourceBufferPos = 0;
+
+                            nextPos = (sourceBufferPos + 1) % sourceBufferSize;
+                            subSampleOffset -= 1.0;
+                        }
+                    }
+
+                    if (ratio[i] < 0.99999)
+                    {
+                        // apply the filter after upsampling
+                        float* ptr = buffer.getWritePointer(0);
+                        filters[i]->process(destBufferPos, &ptr);
+                    }
+
+                    // now copy the channel into the output zone
+
+                    // buffer.addFrom(0,    // destChannel
+                    //                0,  // destSampleOffset
+                    //                buffer,     // source
+                    //                 i+2,    // sourceChannel
+                    //                 0,// sourceSampleOffset
+                    //                 valuesNeeded,        // number of samples
+                    //                 1.0);      // gain to apply to source
+
+                } // if channelPointers[i]->isMonitored
+            } // end cycling through channels
+
+            // Simple implementation of a "noise gate" on audio output
+            expander.process(buffer.getWritePointer(0), // expand the left channel
+                             buffer.getNumSamples());
+
+            // copy the signal into the right channel (no stereo audio yet!)
+            buffer.addFrom(1,    // destChannel
+                           0,  // destSampleOffset
+                           buffer,     // source
+                           0,    // sourceChannel
+                           0,// sourceSampleOffset
+                           valuesNeeded,        // number of samples
+                           1.0);      // gain to apply to source
+        }
     }
 }
 
@@ -381,15 +468,15 @@ void AudioNode::process(AudioSampleBuffer& buffer,
 
 Expander::Expander()
 {
-  threshold = 1.f;
-  output = 1.f;
-    
-  env = 0.f;
-  gain = 1.f;
-
-  setAttack(1.0f);
-  setRelease(1.0f);
-  setRatio(1.2); // ratio > 1.0 will decrease gain below threshold
+    threshold = 1.f;
+    output = 1.f;
+
+    env = 0.f;
+    gain = 1.f;
+
+    setAttack(1.0f);
+    setRelease(1.0f);
+    setRatio(1.2); // ratio > 1.0 will decrease gain below threshold
 }
 
 void Expander::setThreshold(float value)
@@ -422,24 +509,23 @@ void Expander::setRelease(float value)
 }
 
 
-void Expander::process(float* leftChan, float* rightChan, int numSamples)
+void Expander::process(float* sampleData, int numSamples)
 {
-  float det, transfer_gain;
+    float det, transfer_gain;
 
-  for(int i = 0; i < numSamples; i++)
-  {
-      det = jmax(fabs(leftChan[i]),fabs(rightChan[i]));
-      det += 10e-30f; /* add tiny DC offset (-600dB) to prevent denormals */
+    for (int i = 0; i < numSamples; i++)
+    {
+        det = fabs(sampleData[i]);
+        det += 10e-30f; /* add tiny DC offset (-600dB) to prevent denormals */
 
-      env = det >= env ? det : det + envelope_decay*(env-det);
+        env = det >= env ? det : det + envelope_decay*(env-det);
 
-      transfer_gain = env < threshold ? pow(env, transfer_A) * transfer_B : output;
+        transfer_gain = env < threshold ? pow(env, transfer_A) * transfer_B : output;
 
-      gain = transfer_gain < gain ?
-                      transfer_gain + attack * (gain - transfer_gain) :
-                      transfer_gain + release * (gain - transfer_gain);
+        gain = transfer_gain < gain ?
+               transfer_gain + attack * (gain - transfer_gain) :
+               transfer_gain + release * (gain - transfer_gain);
 
-      leftChan[i] = leftChan[i] * gain; 
-      rightChan[i] = rightChan[i] * gain;
-  }
+        sampleData[i] = sampleData[i] * gain;
+    }
 }
\ No newline at end of file
diff --git a/Source/Processors/AudioNode/AudioNode.h b/Source/Processors/AudioNode/AudioNode.h
index c6fda84453558d968420e3f5abe250bc1a1f1639..2f65e6a3009980ad6af4a67fe3de12936799fe70 100755
--- a/Source/Processors/AudioNode/AudioNode.h
+++ b/Source/Processors/AudioNode/AudioNode.h
@@ -30,6 +30,7 @@
 
 #include "../GenericProcessor/GenericProcessor.h"
 #include "AudioEditor.h"
+#include "../Dsp/Dsp.h"
 
 #include "../Channel/Channel.h"
 
@@ -67,7 +68,7 @@ public:
   void setRelease(float);
   void reset();
 
-  void process(float* leftChan, float* rightChan, int numSamples);
+  void process(float* sampleData, int numSamples);
 
 private:
     float   threshold;
@@ -88,7 +89,7 @@ public:
 
     /** Handle incoming data and decide which channels to monitor
     */
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
 
     /** Used to change audio monitoring parameters (such as channels to monitor and volume) while acquisition is active.
     */
@@ -119,7 +120,12 @@ public:
 
     void prepareToPlay(double sampleRate_, int estimatedSamplesPerBlock);
 
+    void updateFilter(int i);
+
+	bool enable();
+
 private:
+	void recreateBuffers();
 
     Array<int> leftChan;
     Array<int> rightChan;
@@ -129,18 +135,30 @@ private:
     /** An array of pointers to the channels that feed into the AudioNode. */
     Array<Channel*> channelPointers;
 
-    AudioSampleBuffer bufferA;
-    AudioSampleBuffer bufferB;
+    OwnedArray<AudioSampleBuffer> bufferA;
+    OwnedArray<AudioSampleBuffer> bufferB;
 
-    int numSamplesExpected;
+    Array<int> numSamplesExpected;
 
-    int samplesInBackupBuffer;
-    int samplesInOverflowBuffer;
+    Array<int> samplesInBackupBuffer;
+    Array<int> samplesInOverflowBuffer;
+    Array<double> sourceBufferSampleRate;
+    double destBufferSampleRate;
+	int estimatedSamples;
 
-    bool bufferSwap;
+    Array<bool> bufferSwap;
 
     Expander expander;
 
+    // sample rate, timebase, and ratio info:
+    Array<double> ratio;
+
+    // major objects:
+    OwnedArray<Dsp::Filter> filters;
+
+    // Temporary buffer for data
+    ScopedPointer<AudioSampleBuffer> tempBuffer;
+
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioNode);
 
 };
diff --git a/Source/Processors/AudioResamplingNode/AudioResamplingNode.cpp b/Source/Processors/AudioResamplingNode/AudioResamplingNode.cpp
index 3fb680a5217d94b5c6d474196c6ea3b952aab330..69fa7cbaba6472f532437b756782efa62d974166 100644
--- a/Source/Processors/AudioResamplingNode/AudioResamplingNode.cpp
+++ b/Source/Processors/AudioResamplingNode/AudioResamplingNode.cpp
@@ -140,11 +140,10 @@ void AudioResamplingNode::releaseResources()
 }
 
 void AudioResamplingNode::process(AudioSampleBuffer& buffer,
-                                  MidiBuffer& midiMessages,
-                                  int& nSamples)
+                                  MidiBuffer& midiMessages)
 {
 
-    int nSamps = nSamples;
+    int nSamps = buffer.getNumSamples(); // WRONG!!!!
     int valuesNeeded;
 
     if (destBufferIsTempBuffer)
diff --git a/Source/Processors/AudioResamplingNode/AudioResamplingNode.h b/Source/Processors/AudioResamplingNode/AudioResamplingNode.h
index 77cda548eaa6c289bbcc27162632b62881a9c740..2d2ef308676b5658691696a53e248e3b37dd5d1d 100644
--- a/Source/Processors/AudioResamplingNode/AudioResamplingNode.h
+++ b/Source/Processors/AudioResamplingNode/AudioResamplingNode.h
@@ -59,7 +59,7 @@ public:
 
     void prepareToPlay(double sampleRate, int estimatedSamplesPerBlock);
     void releaseResources();
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     void setParameter(int parameterIndex, float newValue);
 
     AudioSampleBuffer* getContinuousBuffer()
diff --git a/Source/Processors/Channel/Channel.cpp b/Source/Processors/Channel/Channel.cpp
index f5cdd31deeddbd0177f1227bc04bdd10e24d8178..d7f7ec265734b0310c7d4fc56ec50eef66d8ab61 100644
--- a/Source/Processors/Channel/Channel.cpp
+++ b/Source/Processors/Channel/Channel.cpp
@@ -24,49 +24,63 @@
 #include "Channel.h"
 
 
-Channel::Channel(GenericProcessor* p, int n) : num(n), eventType(0), processor(p), sampleRate(44100.0),
-	 isEventChannel(false), isADCchannel(false), isMonitored(false),  isEnabled(true), recordIndex(-1), 
-	 type(DATA_CHANNEL),bitVolts(1.0f), isRecording(false)
+Channel::Channel(GenericProcessor* p, int n, ChannelType t) : index(n), processor(p), type(t), nodeIndex(0)
 {
-    nodeId = p->getNodeId();
+    reset();
+}
 
+void Channel::reset()
+{
     createDefaultName();
+
+    nodeId = processor->getNodeId();
+
+    sampleRate = 44100.0f;
+    bitVolts = 1.0f;
+    sourceNodeId = -1;
+    isMonitored = false;
+    isEnabled = true;
+    recordIndex = -1;
+    probeId = -1;
+    x = 0.0f;
+    y = 0.0f;
+    z = 0.0f;
+    impedance = 0.0f;
+    isRecording = false;
+
 }
 
 Channel::Channel(const Channel& ch)
 {
+    index = ch.index;
+    nodeIndex = ch.nodeIndex;
+    nodeId = ch.nodeId;
     processor = ch.processor;
-    isEventChannel = ch.isEventChannel;
-    isEnabled = ch.isEnabled;
-    isMonitored = false;
-    isADCchannel = ch.isADCchannel;
     sampleRate = ch.sampleRate;
     bitVolts = ch.bitVolts;
+    type = ch.type;
+    sourceNodeId = ch.sourceNodeId;
+    isMonitored = ch.isMonitored;
+    isEnabled = ch.isEnabled;
+    recordIndex = ch.recordIndex;
     name = ch.name;
-    eventType = ch.eventType;
-    nodeId = ch.nodeId;
-    num = ch.num;
-	type = ch.type;
-
-    originalStream = ch.originalStream;
-    originalChannel = ch.originalChannel;
+    probeId = ch.probeId;
+    x = ch.x;
+    y = ch.y;
+    z = ch.z;
+    impedance = ch.impedance;
 
     setRecordState(false);
 }
 
-float Channel::getChannelGain()
+float Channel::getBitVolts()
 {
     return bitVolts;
 }
 
-String Channel::getChannelName()
+void Channel::setBitVolts(float bv)
 {
-    return name;
-}
-
-void Channel::setGain(float gain)
-{
-    bitVolts = gain;
+    bitVolts = bv;
 }
 
 
@@ -85,19 +99,19 @@ String Channel::getName()
 void Channel::setRecordState(bool t)
 {
 
-   isRecording = t;
-   //std::cout << "Setting record status for channel " <<
-     //            nodeId << " - " << num << " to " << t << std::endl;
+    isRecording = t;
+    //std::cout << "Setting record status for channel " <<
+    //            nodeId << " - " << num << " to " << t << std::endl;
 
 }
 
-void Channel::setType(channelType t)
+void Channel::setType(ChannelType t)
 {
     type = t;
 }
 
 
-channelType Channel::getType()
+ChannelType Channel::getType()
 {
     return type;
 }
@@ -107,17 +121,34 @@ void Channel::setName(String name_)
     name = name_;
 }
 
-void Channel::reset()
-{
-    createDefaultName();
-
-    sampleRate = 44100.0f;
-    bitVolts = 1.0f;
 
-}
 
 void Channel::createDefaultName()
 {
-    name = String("CH");
-    name += (num + 1);
+    switch (type)
+    {
+        case HEADSTAGE_CHANNEL:
+            name = String("CH");
+            break;
+        case AUX_CHANNEL:
+            name = String("AUX");
+            break;
+        case ADC_CHANNEL:
+            name = String("ADC");
+            break;
+        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");
+            break;
+    }
+
+    name += index;
 }
diff --git a/Source/Processors/Channel/Channel.h b/Source/Processors/Channel/Channel.h
index 737f1bb2835d0b4feb842b891a7de7a9366527b2..da60b7105b2a4481b7d8f361c3b173e1e861b575 100644
--- a/Source/Processors/Channel/Channel.h
+++ b/Source/Processors/Channel/Channel.h
@@ -43,6 +43,11 @@ class GenericProcessor;
   AudioNode and RecordNode, which need to access/update Channel
   information for multiple processors at once.
 
+  Every processor has a Channel object for each channel it must deal with.
+  Usually, settings for each channel will be copied from a source
+  node to its destination, but sometimes particular parameters will
+  be updated.
+
   @see GenericProcessor, RecordNode, AudioNode
 
 */
@@ -53,26 +58,27 @@ class Channel
 {
 public:
 
+    //--------- CONSTRUCTOR / DESTRUCTOR --------//
+
     /** Default constructor for creating Channels from scratch. */
-    Channel(GenericProcessor* p, int n);
+    Channel(GenericProcessor*, int, ChannelType);
 
     /** Copy constructor. */
     Channel(const Channel& ch);
 
+    //--------- GET / SET METHODS --------//
+
     /** Returns the name of a given channel. */
     String getName();
 
     /** Sets the name of a given channel. */
     void setName(String);
 
-   /** Sets the type of a given channel. */
-    void setType(channelType t);
+    /** Sets the type of a given channel. */
+    void setType(ChannelType t);
 
-   /** Sets the type of a given channel. */
-    channelType getType();
-
-    /** Restores the default settings for a given channel. */
-    void reset();
+    /** Sets the type of a given channel. */
+    ChannelType getType();
 
     /** Sets the processor to which a channel belongs. */
     void setProcessor(GenericProcessor*);
@@ -81,53 +87,77 @@ public:
     void setRecordState(bool t); // {isRecording = t;}
 
     /** Sets whether or not the channel will record. */
-    bool getRecordState() {return isRecording;}
+    bool getRecordState()
+    {
+        return isRecording;
+    }
 
-    /** Sets a new channel gain by modifying bitVolts */
-    void setGain(float gain);
+    /** Sets the bitVolts value for this channel. */
+    void setBitVolts(float bitVolts);
 
-    /** returns channel's name */
-    String getChannelName();
+    /** Returns the bitVolts value for this channel. */
+    float getBitVolts();
 
-    /** returns current gain */
-    float getChannelGain();
+    // -------- OTHER METHODS ---------//
 
-    /** The channel number.*/
-    int num;
+    /** Restores the default settings for a given channel. */
+    void reset();
+
+    //--------------PUBLIC MEMBERS ---------------- //
+
+    /** Channel index within the source processor */
+    int nodeIndex;
+
+    /** Channel index within the source processor relative to channel type */
+    int index;
 
     /** The ID of the channel's processor.*/
     int nodeId;
 
-    /** Used for EventChannels only.*/
-    int eventType;
-
     /** Pointer to the channel's parent processor. */
     GenericProcessor* processor;
 
-    int originalStream;
-    int originalChannel;
+    /** Sample rate expected for this channel. */
+    float sampleRate;
 
+    /** Bit volts for this channel (i.e., by what must we multiply the ADC integer value to
+        convert to the original voltage measurement?). */
+    float bitVolts;
 
-    // crucial information:
-    float sampleRate;
-    channelType type;
-    
-     // boolean values:
-    bool isEventChannel;
-    bool isADCchannel;
+    /** Channel "type": neural data, aux, adc, event **/
+    ChannelType type;
+
+    /** ID of source node. This is crucial for properly updating timestamps and sample counts. */
+    int sourceNodeId;
+
+    /** Toggled when audio monitoring of this channel is enabled or disabled. */
     bool isMonitored;
+
+    /** Toggled when a channel is disabled from further processing. */
     bool isEnabled;
 
-    // file info (for disk writing). Meaning depends on RecordEngine
-	int recordIndex;
+    /** File info (for disk writing). Meaning depends on the RecordEngine being used. */
+    int recordIndex;
 
+    /** Holds the name of this channel */
     String name;
 
-    float bitVolts;
+    /** The ID of the probe that this channel belongs to (if any) */
+    int probeId;
+
+    /** x,y,z location of this channel in space */
+    float x,y,z;
+
+    /** Impedance of this channel. */
+    float impedance;
+
 
 private:
 
-    bool isRecording; 
+    //-------------- PRIVATE MEMBERS ---------------- //
+
+    /** Stores whether or not the channel is being recorded. */
+    bool isRecording;
 
     /** Generates a default name, based on the channel number. */
     void createDefaultName();
diff --git a/Source/Processors/ChannelMappingNode/ChannelMappingNode.cpp b/Source/Processors/ChannelMappingNode/ChannelMappingNode.cpp
index fd632c8eef455da9859b51b0e2991ef8a3866f46..f783bac35032036fdd97d61406aae32623c2bc4f 100644
--- a/Source/Processors/ChannelMappingNode/ChannelMappingNode.cpp
+++ b/Source/Processors/ChannelMappingNode/ChannelMappingNode.cpp
@@ -28,7 +28,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
 ChannelMappingNode::ChannelMappingNode()
-    : GenericProcessor("Channel Map"), previousChannelCount(0), channelBuffer(1,10000)
+    : GenericProcessor("Channel Map"), channelBuffer(1,10000)
 {
     referenceArray.resize(1024); // make room for 1024 channels
     channelArray.resize(1024);
@@ -68,61 +68,25 @@ void ChannelMappingNode::updateSettings()
     if (getNumInputs() > 0)
         channelBuffer.setSize(getNumInputs(), 10000);
 
-	previousChannelCount = getNumInputs();
 	if (editorIsConfigured)
 	{
-		OwnedArray<Channel> tempArray;
-		channels.swapWith(tempArray);
-		j=0;
-		for (int i=0; i < getNumInputs(); i++)
-		{
-			int realChan = channelArray[i];
-			if (enabledChannelArray[realChan])
-			{
-				channels.add(tempArray[realChan]);
-				j++;
-			}
-		}
-		tempArray.clear(false);
-		settings.numOutputs=j;
+	    OwnedArray<Channel> oldChannels;
+		oldChannels.swapWith(channels);
+	    channels.clear();
+
+	    settings.numOutputs = 0;
+
+	    for (int i = 0; i < getNumInputs(); i++)
+	    {
+	        if (enabledChannelArray[channelArray[i]])
+	        {
+	            channels.add(oldChannels[channelArray[i]]);
+				oldChannels.set(channelArray[i],nullptr,false);
+	            settings.numOutputs++;
+	        }
+
+	    }
 	}
-	/*
-    if (getNumInputs() != previousChannelCount)
-    {
-        previousChannelCount = getNumInputs();
-        if (editorIsConfigured)
-        {
-            j = 0;
-            for (int i = 0; i < getNumInputs(); i++)
-            {
-                if (enabledChannelArray[i])
-                {
-                    j++;
-                }
-                else
-                {
-                    channels.remove(j);
-                }
-            }
-            settings.numOutputs = j;
-        }
-    }
-    else
-    {
-        j = 0;
-        for (int i = 0; i < getNumInputs(); i++)
-        {
-            if (enabledChannelArray[i])
-            {
-                j++;
-            }
-            else
-            {
-                channels.remove(j);
-            }
-        }
-        settings.numOutputs=j;
-    }*/
 
 }
 
@@ -154,8 +118,7 @@ void ChannelMappingNode::setParameter(int parameterIndex, float newValue)
 }
 
 void ChannelMappingNode::process(AudioSampleBuffer& buffer,
-                                 MidiBuffer& midiMessages,
-                                 int& nSamples)
+                                 MidiBuffer& midiMessages)
 {
     int j=0;
     int i=0;
@@ -177,7 +140,7 @@ void ChannelMappingNode::process(AudioSampleBuffer& buffer,
                            channelBuffer, // source
                            realChan, // sourceChannel
                            0, // sourceStartSample
-                           nSamples, // numSamples
+                           getNumSamples(j), // numSamples
                            1.0f // gain to apply to source (positive for original signal)
                           );
 
@@ -190,7 +153,7 @@ void ChannelMappingNode::process(AudioSampleBuffer& buffer,
                                channelBuffer, // source
                                referenceChannels[referenceArray[realChan]], // sourceChannel
                                0, // sourceStartSample
-                               nSamples, // numSamples
+                               getNumSamples(j), // numSamples
                                -1.0f // gain to apply to source (negative for reference)
                               );
             }
diff --git a/Source/Processors/ChannelMappingNode/ChannelMappingNode.h b/Source/Processors/ChannelMappingNode/ChannelMappingNode.h
index 46f5572589685ad9f1b81724c517aca99c06d638..0fa50e9c2cd977f3293cd7eb86395ad545aff7c2 100644
--- a/Source/Processors/ChannelMappingNode/ChannelMappingNode.h
+++ b/Source/Processors/ChannelMappingNode/ChannelMappingNode.h
@@ -50,7 +50,7 @@ public:
     ChannelMappingNode();
     ~ChannelMappingNode();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     void setParameter(int parameterIndex, float newValue);
 
     AudioProcessorEditor* createEditor();
@@ -69,7 +69,6 @@ private:
     Array<int> channelArray;
     Array<bool> enabledChannelArray;
 
-    int previousChannelCount;
     bool editorIsConfigured;
 
     AudioSampleBuffer channelBuffer;
diff --git a/Source/Processors/DataThreads/DataThread.h b/Source/Processors/DataThreads/DataThread.h
index e22a48622d39b6aaa204958af3a1aa570710297d..d6ae6e3faf006baa2662a3f8a86c662047a9092e 100755
--- a/Source/Processors/DataThreads/DataThread.h
+++ b/Source/Processors/DataThreads/DataThread.h
@@ -79,25 +79,31 @@ public:
     /** Stops data transfer.*/
     virtual bool stopAcquisition() = 0;
 
-    /** Returns the number of continuous channels the data source can provide.*/
-    virtual int getNumChannels() = 0;
+    /** Returns the number of continuous headstage channels the data source can provide.*/
+    virtual int getNumHeadstageOutputs() = 0;
+
+    /** Returns the number of continuous aux channels the data source can provide.*/
+    virtual int getNumAuxOutputs() {return 0;}
+
+    /** Returns the number of continuous ADC channels the data source can provide.*/
+    virtual int getNumAdcOutputs() {return 0;}
 
     /** Returns the sample rate of the data source.*/
     virtual float getSampleRate() = 0;
 
     /** Returns the volts per bit of the data source.*/
-    virtual float getBitVolts(int chan) = 0;
+    virtual float getBitVolts(Channel* chan) = 0;
 
     /** Returns the number of event channels of the data source.*/
     virtual int getNumEventChannels()
     {
         return 0;
     }
-    virtual int modifyChannelName(channelType t, int stream, int ch, String newName)
+    virtual int modifyChannelName(ChannelType t, int stream, int ch, String newName)
     {
         return -1;
     }
-    virtual int modifyChannelGain(channelType t, int stream, int ch, float gain)
+    virtual int modifyChannelGain(ChannelType t, int stream, int ch, float gain)
     {
         return -1;
     }
@@ -105,7 +111,7 @@ public:
     {
     }
 
-    virtual void getChannelsInfo(StringArray &Names, Array<channelType> &type, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains)
+    virtual void getChannelsInfo(StringArray &Names, Array<ChannelType> &type, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains)
     {
     };
     virtual void getEventChannelNames(StringArray &names)
diff --git a/Source/Processors/DataThreads/EcubeThread.cpp b/Source/Processors/DataThreads/EcubeThread.cpp
index d435cea3717c4ea9a331159be698cd50fbda33bf..536f836a376ae738a78e98ab5c0aca7f846d4e36 100644
--- a/Source/Processors/DataThreads/EcubeThread.cpp
+++ b/Source/Processors/DataThreads/EcubeThread.cpp
@@ -293,7 +293,7 @@ EcubeThread::EcubeThread(SourceNode* sn) : DataThread(sn), numberingScheme(1), a
         throw std::runtime_error(std::string(e.Description()));
     }
 }
-void EcubeThread::getChannelsInfo(StringArray &Names_, Array<channelType> &type_, Array<int> &stream_, Array<int> &originalChannelNumber_, Array<float> &gains_)
+void EcubeThread::getChannelsInfo(StringArray &Names_, Array<ChannelType> &type_, Array<int> &stream_, Array<int> &originalChannelNumber_, Array<float> &gains_)
 {
     Names_ = Names;
     type_ = type;
@@ -312,14 +312,18 @@ void EcubeThread::setDefaultChannelNamesAndType()
     gains.clear();
     originalChannelNumber.clear();
     String prefix;
-    channelType common_type;
+    ChannelType common_type;
 
     int numch = getNumChannels();
 
     if (pDevInt->data_format == EcubeDevInt::dfSeparateChannelsAnalog)
     {
         prefix = "HS_CH";
+<<<<<<< HEAD
         common_type = DATA_CHANNEL;
+=======
+        common_type = HEADSTAGE_CHANNEL;
+>>>>>>> multisamplerate
     }
     else if (pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog)
     {
@@ -376,6 +380,29 @@ EcubeThread::~EcubeThread()
     waitForThreadToExit(-1);
 }
 
+int EcubeThread::getNumHeadstageOutputs()
+{
+    if (pDevInt->data_format == EcubeDevInt::dfSeparateChannelsAnalog)
+        return pDevInt->n_channel_objects;
+    else
+        return 0;
+}
+
+int EcubeThread::getNumAdcOutputs()
+{
+    if (pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog)
+        return 32;
+    else if (pDevInt->data_format == EcubeDevInt::dfDigital)
+        return 64;
+    else
+        return 0;
+}
+
+int EcubeThread::getNumAuxOutputs()
+{
+	return 0;
+}
+
 int EcubeThread::getNumChannels()
 {
     if (pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog)
@@ -410,6 +437,14 @@ float EcubeThread::getSampleRate()
 }
 
 float EcubeThread::getBitVolts(int chan)
+{
+	if (pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog || pDevInt->data_format == EcubeDevInt::dfDigital)
+		return 10.0/32768; // Volts per bit for front panel analog input and fictive v/bit for the digital input
+	else
+		return 6.25e3 / 32768; // Microvolts per bit for the headstage channels
+}
+
+float EcubeThread::getBitVolts(Channel* chan)
 {
     if (pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog || pDevInt->data_format == EcubeDevInt::dfDigital)
         return 10.0 / 32768; // Volts per bit for front panel analog input and fictive v/bit for the digital input
@@ -506,7 +541,11 @@ bool EcubeThread::updateBuffer()
                     const short* pData = (const short*)dp;
                     for (unsigned j = 0; j < datasize; j++)
                     {
+<<<<<<< HEAD
                         pDevInt->interleaving_buffer[j] = pData[j] * 10.0 / 32768; // Convert into volts
+=======
+                        pDevInt->interleaving_buffer[j] = pData[j] * 10.0/32768; // Convert into volts
+>>>>>>> multisamplerate
                     }
                     unsigned long datasam = datasize / 32;
                     int64 cts = pDevInt->buf_timestamp64 / 3200; // Convert eCube's 80MHz timestamps into number of samples on the Panel Analog input (orig sample rate 1144)
diff --git a/Source/Processors/DataThreads/EcubeThread.h b/Source/Processors/DataThreads/EcubeThread.h
index 22ef74931ae18dffca2c5e38e5d6c535c818668f..44be9a7011cf4eb55de9fbc66ce2efb5ec9e1d70 100644
--- a/Source/Processors/DataThreads/EcubeThread.h
+++ b/Source/Processors/DataThreads/EcubeThread.h
@@ -76,6 +76,12 @@ public:
     /** Returns the number of continuous channels the data source can provide.*/
     virtual int getNumChannels();
 
+	virtual int getNumHeadstageOutputs();
+
+	virtual int getNumAdcOutputs();
+
+	virtual int getNumAuxOutputs();
+
     /** Returns the number of event channels of the data source.*/
     virtual int getNumEventChannels();
 
@@ -88,7 +94,9 @@ public:
     /** Returns the volts per bit of a given data channel.*/
     virtual float getBitVolts(int chan);
 
-    virtual void getChannelsInfo(StringArray &Names, Array<channelType> &type, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains);
+	virtual float getBitVolts(Channel* chan);
+
+    virtual void getChannelsInfo(StringArray &Names, Array<ChannelType> &type, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains);
     void setDefaultNamingScheme(int scheme);
     /** Changes the names of channels, if the thread needs custom names. */
     virtual void updateChannelNames();
@@ -100,7 +108,7 @@ private:
     // used for data stream names...
     int numberingScheme;
     StringArray Names;
-    Array<channelType> type;
+    Array<ChannelType> type;
     Array<float> gains;
     Array<int> stream;
     Array<int> originalChannelNumber;
diff --git a/Source/Processors/DataThreads/RHD2000Editor.cpp b/Source/Processors/DataThreads/RHD2000Editor.cpp
index b40c3519534614db5b67bb4861567a8ea3272735..b2c3fea9d80b0b74b06c037976b4d81b0e91b643 100644
--- a/Source/Processors/DataThreads/RHD2000Editor.cpp
+++ b/Source/Processors/DataThreads/RHD2000Editor.cpp
@@ -165,7 +165,7 @@ void FPGAchannelList::update()
     streamNames.add("Port D2");
     streamNames.add("ADC");
 
-    for (int k=0; k<MAX_NUM_DATA_STREAMS+1; k++)
+    for (int k = 0; k < MAX_NUM_DATA_STREAMS + 1; k++)
     {
         if (streamActive[k])
         {
@@ -181,12 +181,12 @@ void FPGAchannelList::update()
 
     }
 
-    // add buttons for all DATA,AUX,channels
-    for (int k=0; k<numChannels; k++)
+    // add buttons for all DATA, AUX, channels
+    for (int k = 0; k < numChannels; k++)
     {
         int channelGainIndex = 1;
-		float ch_gain = oldgains[k]/static_cast<SourceNode*>(proc)->getBitVolts(k);
-        for (int j=0; j<gains.size(); j++)
+		float ch_gain = 1.0f; ///%oldgains[k]/static_cast<SourceNode*>(proc)->getBitVolts(k);
+        for (int j = 0; j < gains.size(); j++)
         {
             if (fabs(gains[j]-ch_gain) < 1e-3)
             {
@@ -244,7 +244,7 @@ void FPGAchannelList::enableAll()
 
 }
 
-void FPGAchannelList::setNewGain(int stream, int channel, channelType type, float gain)
+void FPGAchannelList::setNewGain(int stream, int channel, ChannelType type, float gain)
 {
     float newGain;
 	int realChan;
@@ -258,11 +258,11 @@ void FPGAchannelList::setNewGain(int stream, int channel, channelType type, floa
 	{
 		realChan = channel;
 	}
-	newGain = p->getBitVolts(realChan)*gain;
+	//newGain = p->getBitVolts(realChan)*gain;
     p->modifyChannelGain(stream, channel, type, newGain, true);
 }
 
-void FPGAchannelList::setNewName(int stream, int channelIndex, channelType t, String newName)
+void FPGAchannelList::setNewName(int stream, int channelIndex, ChannelType t, String newName)
 {
     proc->modifyChannelName(t, stream, channelIndex, newName, true);
 }
@@ -301,7 +301,7 @@ void FPGAchannelList::updateImpedance(Array<int> streams, Array<int> channels, A
     {
         for (int j=k; j<stream.size(); j++)
         {
-            if (stream[j] == streams[k] && types[j] == DATA_CHANNEL && orig_number[j] == channels[k])
+            if (stream[j] == streams[k] && types[j] == HEADSTAGE_CHANNEL && orig_number[j] == channels[k])
             {
                 channelComponents[j]->setImpedanceValues(magnitude[k],phase[k]);
                 break;
@@ -314,7 +314,7 @@ void FPGAchannelList::updateImpedance(Array<int> streams, Array<int> channels, A
 
 
 /****************************************************/
-FPGAchannelComponent::FPGAchannelComponent(FPGAchannelList* cl, int stream_, int ch, channelType t, int gainIndex_, String N, Array<float> gains_) :   gains(gains_), channelList(cl), channel(ch), name(N), stream(stream_), type(t), gainIndex(gainIndex_)
+FPGAchannelComponent::FPGAchannelComponent(FPGAchannelList* cl, int stream_, int ch, ChannelType t, int gainIndex_, String N, Array<float> gains_) :   gains(gains_), channelList(cl), channel(ch), name(N), stream(stream_), type(t), gainIndex(gainIndex_)
 {
     Font f = Font("Small Text", 13, Font::plain);
 
@@ -353,7 +353,7 @@ FPGAchannelComponent::FPGAchannelComponent(FPGAchannelList* cl, int stream_, int
         gainComboBox = nullptr;
     }
 
-    if (type == DATA_CHANNEL)
+    if (type == HEADSTAGE_CHANNEL)
     {
         impedance = new Label("Impedance","? Ohm");
         impedance->setFont(Font("Default", 13, Font::plain));
@@ -710,7 +710,7 @@ void RHD2000Editor::measureImpedance()
 		for (int i = 0; i < channel.size(); i++)
 		{
 			XmlElement* chan = new XmlElement("CHANNEL");
-			chan->setAttribute("name",board->getChannelName(DATA_CHANNEL,stream[i],channel[i]));
+			chan->setAttribute("name",board->getChannelName(HEADSTAGE_CHANNEL,stream[i],channel[i]));
 			chan->setAttribute("stream",stream[i]);
 			chan->setAttribute("channel_number",channel[i]);
 			chan->setAttribute("magnitude",magnitude[i]);
diff --git a/Source/Processors/DataThreads/RHD2000Editor.h b/Source/Processors/DataThreads/RHD2000Editor.h
index 4caa6630cf1633bf7e5a9f851e83cf075d79d7bb..6a997b6c5c3a469ff9a9bcc24e4c8eca09dca1e4 100644
--- a/Source/Processors/DataThreads/RHD2000Editor.h
+++ b/Source/Processors/DataThreads/RHD2000Editor.h
@@ -59,8 +59,8 @@ public:
     
     FPGAchannelList(GenericProcessor* proc, Viewport *p, FPGAcanvas*c);
     ~FPGAchannelList();
-    void setNewName(int stream, int channelIndex, channelType t, String newName);
-    void setNewGain(int stream, int channel,channelType t, float gain);
+    void setNewName(int stream, int channelIndex, ChannelType t, String newName);
+    void setNewGain(int stream, int channel, ChannelType t, float gain);
     void disableAll();
     void enableAll();
     void paint(Graphics& g);
@@ -74,7 +74,7 @@ public:
     
 private:
     Array<float> gains;
-    Array<channelType> types;
+    Array<ChannelType> types;
     Array<int> stream;
     Array<int> orig_number;
 
@@ -94,7 +94,7 @@ private:
 class FPGAchannelComponent : public Component, public AccessClass, Button::Listener, public ComboBox::Listener, public Label::Listener
 {
 public:
-    FPGAchannelComponent(FPGAchannelList* cl,int stream, int ch, channelType t,  int gainIndex_, String name_, Array<float> gains_);
+    FPGAchannelComponent(FPGAchannelList* cl,int stream, int ch, ChannelType t,  int gainIndex_, String name_, Array<float> gains_);
     ~FPGAchannelComponent();
     Colour getDefaultColor(int ID);
     void setImpedanceValues(float mag, float phase);
@@ -122,7 +122,7 @@ private:
     int channel;
     String name;
     int stream;
-    channelType type;
+    ChannelType type;
     int gainIndex;
     int userDefinedData;
     Font font;
@@ -146,8 +146,10 @@ public:
 
     void refreshState();
     void update();
-    void setParameter(int, float) ;
-    void setParameter(int, int, int, float) ;
+
+    void setParameter(int, float);
+    void setParameter(int, int, int, float);
+
     void updateImpedance(Array<int> streams, Array<int> channels, Array<float> magnitude, Array<float> phase);
 
     void resized();
@@ -196,10 +198,10 @@ private:
     ScopedPointer<AudioInterface> audioInterface;
 
     ScopedPointer<UtilityButton> rescanButton,dacTTLButton;
-    ScopedPointer<UtilityButton> adcButton;
+    ScopedPointer<UtilityButton> adcButton;
     
-    ScopedPointer<UtilityButton> dspoffsetButton;
-    ScopedPointer<ComboBox> ttlSettleCombo,dacHPFcombo;
+    ScopedPointer<UtilityButton> dspoffsetButton;
+    ScopedPointer<ComboBox> ttlSettleCombo,dacHPFcombo;
 
 
     ScopedPointer<Label> audioLabel,ttlSettleLabel,dacHPFlabel ;
diff --git a/Source/Processors/DataThreads/RHD2000Thread.cpp b/Source/Processors/DataThreads/RHD2000Thread.cpp
index 8d13a9299380914d8e9fe89c5024b60ab37d7bfb..6a6fb639228eaafb1caa84b3fab3518a3db8ca45 100644
--- a/Source/Processors/DataThreads/RHD2000Thread.cpp
+++ b/Source/Processors/DataThreads/RHD2000Thread.cpp
@@ -138,7 +138,9 @@ RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn),
         }
 
         evalBoard->getDacInformation(dacChannels,dacThresholds);
-		sn->setDefaultNamingScheme(numberingScheme);
+
+		//sn->setDefaultNamingScheme(numberingScheme);
+        //setDefaultChannelNamesAndType();
     }
 }
 
@@ -671,24 +673,16 @@ void RHD2000Thread::setNumChannels(int hsNum, int numChannels)
 }
 
 
-int RHD2000Thread::getNumADCchannels()
-{
-    if (acquireAdcChannels)
-        return 8;
-    else
-        return 0;
-}
-
 void RHD2000Thread::getEventChannelNames(StringArray& Names)
 {
     Names.clear();
-    for (int k=0; k<8; k++)
+    for (int k = 0; k < 8; k++)
     {
         Names.add("TTL"+String(k+1));
     }
 }
 
-void RHD2000Thread::getChannelsInfo(StringArray& Names_, Array<channelType>& type_, Array<int>& stream_, Array<int>& originalChannelNumber_,Array<float>& gains_)
+void RHD2000Thread::getChannelsInfo(StringArray& Names_, Array<ChannelType>& type_, Array<int>& stream_, Array<int>& originalChannelNumber_,Array<float>& gains_)
 {
     Names_ = Names;
     type_ = type;
@@ -704,14 +698,14 @@ void RHD2000Thread::updateChannelNames()
 	for (int i = 0; i < sn->channels.size(); i++)
 	{
 		sn->channels[i]->setName(Names[i]);
-		sn->channels[i]->setGain(gains[i]);
+		sn->channels[i]->bitVolts = gains[i];
 		sn->channels[i]->setType(type[i]);
 	}
 }
 
 /* go over the old names and tests whether this particular channel name was changed.
 if so, return the old name */
-bool RHD2000Thread::channelModified(channelType t, int str, int ch, String& oldName, float& oldGain, int& index)
+bool RHD2000Thread::channelModified(ChannelType t, int str, int ch, String& oldName, float& oldGain, int& index)
 {
     for (int k = 0; k < oldNames.size(); k++)
     {
@@ -727,7 +721,7 @@ bool RHD2000Thread::channelModified(channelType t, int str, int ch, String& oldN
 }
 
 
-int RHD2000Thread::modifyChannelName(channelType t, int str, int ch, String newName)
+int RHD2000Thread::modifyChannelName(ChannelType t, int str, int ch, String newName)
 {
     String dummy;
     float dummyFloat = 0;
@@ -738,17 +732,17 @@ int RHD2000Thread::modifyChannelName(channelType t, int str, int ch, String newN
     }
     else
     {
-        oldNames.add(newName);
-        oldType.add(t);
-        oldStream.add(str);
-        oldChannelNumber.add(ch);
-		if (t == ADC_CHANNEL)
-			oldGains.add(gains[getNumChannels()-getNumADCchannels()+ch]);
-		else
-			oldGains.add(gains[ch]);
+  //       oldNames.add(newName);
+  //       oldType.add(t);
+  //       oldStream.add(str);
+  //       oldChannelNumber.add(ch);
+		// if (t == ADC_CHANNEL)
+		// 	oldGains.add(gains[getNumChannels()-getNumADCchannels()+ch]);
+		// else
+		// 	oldGains.add(gains[ch]);
     }
 
-    for (int k=0; k<Names.size(); k++)
+    for (int k = 0; k < Names.size(); k++)
     {
         if (type[k] == t && stream[k] == str && originalChannelNumber[k] == ch)
         {
@@ -759,7 +753,7 @@ int RHD2000Thread::modifyChannelName(channelType t, int str, int ch, String newN
     return -1;
 }
 
-String RHD2000Thread::getChannelName(channelType t, int str, int ch)
+String RHD2000Thread::getChannelName(ChannelType t, int str, int ch)
 {
 	for (int k=0; k<Names.size(); k++)
     {
@@ -770,10 +764,10 @@ String RHD2000Thread::getChannelName(channelType t, int str, int ch)
     }
 }
 
-int RHD2000Thread::modifyChannelGain(channelType t, int str, int ch, float gain)
+int RHD2000Thread::modifyChannelGain(ChannelType t, int str, int ch, float gain)
 {
     String dummy;
-    float dummyFloat=0;
+    float dummyFloat = 0;
     int index;
     if (channelModified(t, str, ch, dummy, dummyFloat, index))
     {
@@ -781,6 +775,7 @@ int RHD2000Thread::modifyChannelGain(channelType t, int str, int ch, float gain)
     }
     else
     {
+
 		if (t == ADC_CHANNEL)
 			oldNames.add(Names[getNumChannels()-getNumADCchannels()+ch]);
 		else
@@ -789,6 +784,7 @@ int RHD2000Thread::modifyChannelGain(channelType t, int str, int ch, float gain)
         oldStream.add(str);
         oldChannelNumber.add(ch);
         oldGains.add(gain);
+
     }
 
     for (int k=0; k<Names.size(); k++)
@@ -843,9 +839,9 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
         {
             for (int k = 0; k < numChannelsPerDataStream[i]; k++)
             {
-                type.add(DATA_CHANNEL);
+                type.add(HEADSTAGE_CHANNEL);
 
-                if (channelModified(DATA_CHANNEL,i,k, oldName,oldGain,dummy))
+                if (channelModified(HEADSTAGE_CHANNEL,i,k, oldName,oldGain,dummy))
                 {
                     Names.add(oldName);
                     gains.add(oldGain);
@@ -858,7 +854,7 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
                     else
                         Names.add("CH_"+stream_prefix[i]+"_"+String(1+k));
 
-                    gains.add(getBitVolts(channelNumber));
+                   // gains.add(getBitVolts(channelNumber));
                 }
                 
                 stream.add(i);
@@ -917,7 +913,7 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
             else
             {
                 Names.add("ADC" + String(k+1));
-                gains.add(getADCBitVolts(k));
+                gains.add(getAdcBitVolts(k));
             }
             
             stream.add(MAX_NUM_DATA_STREAMS);
@@ -929,6 +925,11 @@ void RHD2000Thread::setDefaultChannelNamesAndType()
 }
 
 int RHD2000Thread::getNumChannels()
+{
+    return getNumHeadstageOutputs() + getNumAdcOutputs() + getNumAuxOutputs();
+}
+
+int RHD2000Thread::getNumHeadstageOutputs()
 {
     numChannels = 0;
     for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
@@ -937,13 +938,8 @@ int RHD2000Thread::getNumChannels()
         if (numChannelsPerDataStream[i] > 0)
         {
             numChannels += numChannelsPerDataStream[i];
-            numChannels += 3; // to account for aux inputs
         }
     }
-    if (acquireAdcChannels)
-    {
-        numChannels += 8; // add 8 channels for the ADCs
-    }
 
     if (numChannels > 0)
         return numChannels;
@@ -951,7 +947,31 @@ int RHD2000Thread::getNumChannels()
         return 1; // to prevent crashing with 0 channels
 }
 
+int RHD2000Thread::getNumAuxOutputs()
+{
+    int numAuxOutputs = 0;
+
+    for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++)
+    {
+        if (numChannelsPerDataStream[i] > 0)
+        {
+            numAuxOutputs += 3;
+        }
+    }
+
+    return numAuxOutputs;
+
+}
 
+int RHD2000Thread::getNumAdcOutputs()
+{
+    if (acquireAdcChannels)
+    {
+        return 8;
+    } else {
+        return 0;
+    }
+}
 
 int RHD2000Thread::getNumEventChannels()
 {
@@ -963,18 +983,22 @@ float RHD2000Thread::getSampleRate()
     return evalBoard->getSampleRate();
 }
 
-float RHD2000Thread::getBitVolts(int chan)
+float RHD2000Thread::getBitVolts(Channel* ch)
 {
-    if (type[chan] == ADC_CHANNEL)
-	   return 0.00015258789;
+    if (ch->type == ADC_CHANNEL)
+	   return getAdcBitVolts(ch->index);
+    else if (ch->type == AUX_CHANNEL)
+        return 0.0000374;
     else
         return 0.195f;
 }
 
-float RHD2000Thread::getADCBitVolts(int chan)
+float RHD2000Thread::getAdcBitVolts(int chan)
 {
-    return 0.00015258789;
-
+    if (chan < adcBitVolts.size())
+        return adcBitVolts[chan];
+    else
+        return 0.00015258789;
 }
 
 double RHD2000Thread::setUpperBandwidth(double upper)
@@ -1131,7 +1155,7 @@ void RHD2000Thread::enableAdcs(bool t)
     acquireAdcChannels = t;
 
     dataBuffer->resize(getNumChannels(), 10000);
-    //updateChannelNames();
+
 }
 
 
diff --git a/Source/Processors/DataThreads/RHD2000Thread.h b/Source/Processors/DataThreads/RHD2000Thread.h
index 3bc7baca14fa8273ed4b4de9e49d5488f560e5e4..6eb6c031de3f59ef9346261b51a5ad3efed7e173 100644
--- a/Source/Processors/DataThreads/RHD2000Thread.h
+++ b/Source/Processors/DataThreads/RHD2000Thread.h
@@ -58,12 +58,17 @@ public:
     RHD2000Thread(SourceNode* sn);
     ~RHD2000Thread();
 
+    // for communication with SourceNode processors:
     bool foundInputSource();
     int getNumChannels();
+    int getNumHeadstageOutputs();
+    int getNumAuxOutputs();
+    int getNumAdcOutputs();
     float getSampleRate();
-    float getBitVolts(int chan);
-    float getADCBitVolts(int chan);
+    float getBitVolts(Channel* chan);
+    float getAdcBitVolts(int channelNum);
 
+    // for internal use:
     bool isHeadstageEnabled(int hsNum);
 
     bool enableHeadstage(int hsNum, bool enabled);
@@ -98,16 +103,15 @@ public:
                                                const std::vector<double> &data, int startIndex,
                                                int endIndex, double sampleRate, double frequency);
     int getNumEventChannels();
-    int getNumADCchannels();
 
     void assignAudioOut(int dacChannel, int dataChannel);
     void enableAdcs(bool);
 
     bool isAcquisitionActive();
     
-    virtual int modifyChannelGain(channelType t, int str, int ch, float gain);
-    virtual int modifyChannelName(channelType t, int str, int k, String newName);
-    virtual void getChannelsInfo(StringArray &Names, Array<channelType> &type, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains);
+    virtual int modifyChannelGain(ChannelType t, int str, int ch, float gain);
+    virtual int modifyChannelName(ChannelType t, int str, int k, String newName);
+    virtual void getChannelsInfo(StringArray &Names, Array<ChannelType> &type, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains);
     virtual void getEventChannelNames(StringArray &Names);
     void updateChannelNames();
     Array<int> getDACchannels();
@@ -115,11 +119,11 @@ public:
     void setDACthreshold(int dacOutput, float threshold);
     void setDefaultNamingScheme(int scheme);
 
-	String getChannelName(channelType t, int str, int ch);
+	String getChannelName(ChannelType t, int str, int ch);
 
 private:
     void setDefaultChannelNamesAndType();
-    bool channelModified(channelType t, int str, int k, String &oldName, float &oldGain, int &index);
+    bool channelModified(ChannelType t, int str, int k, String &oldName, float &oldGain, int &index);
 
     ScopedPointer<Rhd2000EvalBoard> evalBoard;
     Rhd2000Registers chipRegisters;
@@ -188,8 +192,9 @@ private:
     // used for data stream names...
     int numberingScheme ;
     StringArray Names, oldNames;
-    Array<channelType> type, oldType;
+    Array<ChannelType> type, oldType;
     Array<float> gains, oldGains;
+    Array<float> adcBitVolts;
     Array<int> stream, oldStream;
     Array<bool> modifiedName, oldModifiedName;
     Array<int> originalChannelNumber, oldChannelNumber;
diff --git a/Source/Processors/Editors/ChannelSelector.cpp b/Source/Processors/Editors/ChannelSelector.cpp
index aa17fde9099cc32d0c4fe132b50b5121a809f795..0c5b243d728800ee8af867a01e0e511c10a3b0df 100755
--- a/Source/Processors/Editors/ChannelSelector.cpp
+++ b/Source/Processors/Editors/ChannelSelector.cpp
@@ -132,12 +132,12 @@ void ChannelSelector::setNumChannels(int numChans)
     //Reassign numbers according to the actual channels (useful for channel mapper)
     for (int n = 0; n < parameterButtons.size(); n++)
     {
-        int num = ((GenericEditor*)getParentComponent())->getChannel(n)->num + 1;
-        parameterButtons[n]->setChannel(num);
+        int num = ((GenericEditor*)getParentComponent())->getChannel(n)->nodeIndex;
+        parameterButtons[n]->setChannel(n+1, num+1);
         if (isNotSink)
         {
-            recordButtons[n]->setChannel(num);
-            audioButtons[n]->setChannel(num);
+            recordButtons[n]->setChannel(n+1, num+1);
+            audioButtons[n]->setChannel(n+1, num+1);
         }
     }
 
@@ -596,7 +596,7 @@ void ChannelSelector::buttonClicked(Button* button)
             //int channelNum = editor->getStartChannel() + b->getChannel() - 1;
             bool status = b->getToggleState();
 
-            std::cout << "Requesting audio monitor for channel " << ch->num << std::endl;
+            std::cout << "Requesting audio monitor for channel " << ch->nodeIndex+1 << std::endl;
 
             if (acquisitionIsActive) // use setParameter to change parameter safely
             {
@@ -820,6 +820,7 @@ ChannelSelectorButton::ChannelSelectorButton(int num_, int type_, Font& f) : But
 {
     isActive = true;
     num = num_;
+	displayNum = num_;
     type = type_;
 
     setClickingTogglesState(true);
@@ -855,7 +856,7 @@ void ChannelSelectorButton::paintButton(Graphics& g, bool isMouseOver, bool isBu
 
     // g.drawRect(0,0,getWidth(),getHeight(),1.0);
 
-    g.drawText(String(num),0,0,getWidth(),getHeight(),Justification::centred,true);
+	g.drawText(String(displayNum),0,0,getWidth(),getHeight(),Justification::centred,true);
 }
 
 void ChannelSelectorButton::setActive(bool t)
diff --git a/Source/Processors/Editors/ChannelSelector.h b/Source/Processors/Editors/ChannelSelector.h
index 3eff6ca7b6f410af7883f27c4374844204472f2d..a8cad65f21c90c8e63d80319d81327c9b12d607f 100755
--- a/Source/Processors/Editors/ChannelSelector.h
+++ b/Source/Processors/Editors/ChannelSelector.h
@@ -306,6 +306,12 @@ public:
 	void setChannel(int n)
 	{
 		num = n;
+		displayNum = n;
+	}
+	void setChannel(int n, int d)
+	{
+		num = n;
+		displayNum = d;
 	}
 
 private:
@@ -315,6 +321,7 @@ private:
 
     int type;
     int num;
+	int displayNum;
     Font buttonFont;
     bool isActive;
 };
diff --git a/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.cpp b/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.cpp
index 2de456adcc5fb0ba548270e70c268481955384ad..d79d3edcec8f705414808b060f0b5cfa08644c9c 100644
--- a/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.cpp
+++ b/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.cpp
@@ -154,9 +154,12 @@ void PeriStimulusTimeHistogramEditor::loadVisualizerParameters(XmlElement* xml)
 
 void PeriStimulusTimeHistogramEditor::comboBoxChanged(ComboBox* comboBox)
 {
+
 	if (comboBox == hardwareTrialAlignment)
 	{
-		// TODO
+		std::cout << "Setting hardware trigger alignment channel to " << comboBox->getSelectedId()-2 << std::endl;
+		PeriStimulusTimeHistogramNode* processor = (PeriStimulusTimeHistogramNode*) getProcessor();
+		processor->setHardwareTriggerAlignmentChannel(comboBox->getSelectedId()-2);
 	}
 }
 
@@ -363,8 +366,8 @@ Visualizer* PeriStimulusTimeHistogramEditor::createNewCanvas()
 {
 	PeriStimulusTimeHistogramNode* processor = (PeriStimulusTimeHistogramNode*) getProcessor();
 	periStimulusTimeHistogramCanvas = new PeriStimulusTimeHistogramCanvas(processor);
-//	ActionListener* listener = (ActionListener*) periStimulusTimeHistogramCanvas;
-//    getUIComponent()->registerAnimatedComponent(listener);
+	//ActionListener* listener = (ActionListener*) periStimulusTimeHistogramCanvas;
+    //getUIComponent()->registerAnimatedComponent(listener);
 	return periStimulusTimeHistogramCanvas;
 }
 
@@ -462,7 +465,9 @@ PeriStimulusTimeHistogramCanvas::~PeriStimulusTimeHistogramCanvas()
 
 void PeriStimulusTimeHistogramCanvas::beginAnimation()
 {
-	//startCallbacks();
+
+	std::cout << "PeriStimulusTimeHistogramCanvas starting animation." << std::endl;
+	startCallbacks();
 	
 }
 
@@ -502,9 +507,9 @@ void PeriStimulusTimeHistogramCanvas::buttonClicked(Button* button)
 
 void PeriStimulusTimeHistogramCanvas::endAnimation()
 {
-	std::cout << "SpikeDisplayCanvas ending animation." << std::endl;
+	std::cout << "PeriStimulusTimeHistogramCanvas ending animation." << std::endl;
 
-	//stopCallbacks();
+	stopCallbacks();
 }
 
 void PeriStimulusTimeHistogramCanvas::setRasterMode(bool rasterModeActive)
@@ -617,7 +622,7 @@ void PeriStimulusTimeHistogramCanvas::update()
 	widthPerUnit = 300;
 	int maxUnitsPerRow = (screenWidth-conditionWidth)/ widthPerUnit;
 	updateNeeded = false;
-	for (int k=0; k < psthDisplay->psthPlots.size();k++)
+	for (int k = 0; k < psthDisplay->psthPlots.size(); k++)
 	{
 		delete psthDisplay->psthPlots[k];
 	}
@@ -635,7 +640,7 @@ void PeriStimulusTimeHistogramCanvas::update()
 	numCols = 0;
 	numRows = 0;
 	int plotID = 0;
-	for (int e=0;e<numElectrodes;e++) 
+	for (int e = 0; e < numElectrodes; e++) 
 	{
 		int offset = 0;
 		bool plottedSomething = false;
@@ -782,12 +787,10 @@ void PeriStimulusTimeHistogramCanvas::resized()
 	visualizationButton->setBounds(20,5,150,20);
 	clearAllButton->setBounds(200,5,150,20);
 
-
 	zoomButton->setBounds(360,5,60,20);
 	panButton->setBounds(440,5,60,20);
 	resetAxesButton->setBounds(510,5,150,20);
 
-
 }
 
 void PeriStimulusTimeHistogramCanvas::paint(Graphics& g)
@@ -831,7 +834,6 @@ void PeriStimulusTimeHistogramDisplay::refresh()
 
 }
 
-
 void PeriStimulusTimeHistogramDisplay::paint(Graphics &g)
 {
 	g.setColour(Colours::white);
@@ -845,7 +847,6 @@ void PeriStimulusTimeHistogramDisplay::paint(Graphics &g)
 	*/
 }  
 
-
 void PeriStimulusTimeHistogramDisplay::setAutoRescale(bool state)
 {
 	// draw n by m grid
@@ -881,7 +882,6 @@ void PeriStimulusTimeHistogramDisplay::resized()
 	}
 }
 
-
 void PeriStimulusTimeHistogramDisplay::focusOnPlot(int plotID)
 {
 	int plotIndex = -1;
diff --git a/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.h b/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.h
index add3a2128865eabf435dcbd963f390c046eb53d2..b184a5e32b6627462dcfd3d56e7b411805effdbc 100644
--- a/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.h
+++ b/Source/Processors/Editors/PeriStimulusTimeHistogramEditor.h
@@ -65,7 +65,6 @@ class PeriStimulusTimeHistogramDisplay : public Component
 public:
 	PeriStimulusTimeHistogramDisplay(PeriStimulusTimeHistogramNode* n, Viewport *p, PeriStimulusTimeHistogramCanvas*c);
 	~PeriStimulusTimeHistogramDisplay();
-	
 
 	void setAutoRescale(bool state);
 	void resized();
@@ -81,21 +80,14 @@ public:
 
 	juce::Font font;
 
-	
-	  JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PeriStimulusTimeHistogramDisplay);
+	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PeriStimulusTimeHistogramDisplay);
 
 };
 
 
-
-
-
-
-
 class ProcessorListItem;
 class UIComponent;
 
-
 class ConditionList : public Component,
 	public AccessClass, Button::Listener
 
@@ -129,9 +121,6 @@ private:
 };
 
 
-
-
-
 class PeriStimulusTimeHistogramCanvas: public Visualizer, public Button::Listener
 {
 public:
@@ -173,7 +162,7 @@ public:
 	int heightPerElectrodePix;
 	int widthPerUnit;
 	bool updateNeeded;
-		int screenHeight, screenWidth;
+	int screenHeight, screenWidth;
 
    private:
 	int conditionWidth;
@@ -187,13 +176,11 @@ public:
 	float gaussianStandardDeviationMS;
 	int numRows,numCols;
 
-
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PeriStimulusTimeHistogramCanvas);
 
 };
 
 
-
 class PeriStimulusTimeHistogramEditor : public VisualizerEditor,
 	 public ComboBox::Listener
 {
@@ -251,7 +238,6 @@ private:
 	void paintLFPraster(Graphics &g);
 	void paintLFP(Graphics &g);
 
-
 	ScopedPointer<MatlabLikePlot> mlp;
 	PeriStimulusTimeHistogramDisplay* display;
 	TrialCircularBuffer *tcb;
diff --git a/Source/Processors/EventDetector/EventDetector.cpp b/Source/Processors/EventDetector/EventDetector.cpp
index 4afe33258a5e9c1c87e3c02bf39ea6cfa9532850..89198cd9e65d272e93aa936d22abedc06e1102fa 100755
--- a/Source/Processors/EventDetector/EventDetector.cpp
+++ b/Source/Processors/EventDetector/EventDetector.cpp
@@ -57,14 +57,13 @@ void EventDetector::setParameter(int parameterIndex, float newValue)
 }
 
 void EventDetector::process(AudioSampleBuffer& buffer,
-                            MidiBuffer& events,
-                            int& nSamples)
+                            MidiBuffer& events)
 {
 
     //std::cout << *buffer.getReadPointer(0, 0) << std::endl;
 
 
-    for (int i = 0; i < nSamples; i++)
+    for (int i = 0; i < getNumSamples(channels[0]->sourceNodeId); i++)
     {
 
         if ((*buffer.getReadPointer(0, i) < -threshold) && !state)
diff --git a/Source/Processors/EventDetector/EventDetector.h b/Source/Processors/EventDetector/EventDetector.h
index d99efdc26e54da857e02bda0ccdc926bab96c8d2..2d8e44bfe93ecaf34926f6382878c0cedd90e5e4 100755
--- a/Source/Processors/EventDetector/EventDetector.h
+++ b/Source/Processors/EventDetector/EventDetector.h
@@ -43,7 +43,7 @@ public:
     EventDetector();
     ~EventDetector();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     void setParameter(int parameterIndex, float newValue);
 
 private:
diff --git a/Source/Processors/EventNode/EventNode.cpp b/Source/Processors/EventNode/EventNode.cpp
index 4c96d18b78fa3e046efce1d9f889e78815ee94e9..4420a1baa0e8bd3087aab9eda9a11067551936e7 100755
--- a/Source/Processors/EventNode/EventNode.cpp
+++ b/Source/Processors/EventNode/EventNode.cpp
@@ -55,8 +55,8 @@ void EventNode::updateSettings()
 {
     // add event channels
 
-    Channel* ch = new Channel(this, 1);
-    ch->name = "Trigger";
+    Channel* ch = new Channel(this, 1, EVENT_CHANNEL);
+    ch->setName("Trigger");
 
     eventChannels.add(ch);
 
@@ -71,8 +71,7 @@ void EventNode::updateSettings()
 
 
 void EventNode::process(AudioSampleBuffer& buffer,
-                        MidiBuffer& events,
-                        int& nSamples)
+                        MidiBuffer& events)
 {
     events.clear();
 
diff --git a/Source/Processors/EventNode/EventNode.h b/Source/Processors/EventNode/EventNode.h
index 8f5e03f5fa582097972eb7afbe7960bcc9112162..b0e2a6e82d3915b998cf8b09dcf014c45654c6e2 100755
--- a/Source/Processors/EventNode/EventNode.h
+++ b/Source/Processors/EventNode/EventNode.h
@@ -44,7 +44,7 @@ public:
     EventNode();
     ~EventNode();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     //void setParameter (int parameterIndex, float newValue);
 
     bool isSource()
@@ -52,7 +52,7 @@ public:
         return true;
     }
 
-    int getDefaultNumOutputs()
+    int getNumHeadstageOutputs()
     {
         return 0;
     }
diff --git a/Source/Processors/ExampleProcessor/ExampleProcessor.cpp b/Source/Processors/ExampleProcessor/ExampleProcessor.cpp
index 2ebc64073b709fe6e2ef9a954e1bcd82139e285c..fa26ecd40ddf3028db62b58bc1948656c474c66b 100644
--- a/Source/Processors/ExampleProcessor/ExampleProcessor.cpp
+++ b/Source/Processors/ExampleProcessor/ExampleProcessor.cpp
@@ -56,11 +56,10 @@ void ExampleProcessor::setParameter(int parameterIndex, float newValue)
 }
 
 void ExampleProcessor::process(AudioSampleBuffer& buffer,
-                               MidiBuffer& events,
-                               int& nSamples)
+                               MidiBuffer& events)
 {
 
-    // for (int i = 0; i < nSamples; i++)
+    // for (int i = 0; i < getNumSamples(channels[0]->sourceNodeId); i++)
     // {
     //
     //     if ((*buffer.getReadPointer(0, i) < -threshold) && !state)
diff --git a/Source/Processors/ExampleProcessor/ExampleProcessor.h b/Source/Processors/ExampleProcessor/ExampleProcessor.h
index 7bf796cef1dd14f9eca571bacadad22ef1b11d1d..9307bbe029e0777951a6f7c556e84e9cd5bf0fdb 100644
--- a/Source/Processors/ExampleProcessor/ExampleProcessor.h
+++ b/Source/Processors/ExampleProcessor/ExampleProcessor.h
@@ -77,7 +77,7 @@ public:
         number of continous samples in the current buffer (which may differ from the
         size of the buffer).
          */
-    void process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& events);
 
     /** Any variables used by the "process" function _must_ be modified only through
         this method while data acquisition is active. If they are modified in any
diff --git a/Source/Processors/FPGAOutput/FPGAOutput.cpp b/Source/Processors/FPGAOutput/FPGAOutput.cpp
index 6e313cea80263e8b1158d592cb47fa93a3582125..089eeb02c5b865dae8d775dc5b69c9dc187ee83a 100755
--- a/Source/Processors/FPGAOutput/FPGAOutput.cpp
+++ b/Source/Processors/FPGAOutput/FPGAOutput.cpp
@@ -157,14 +157,10 @@ void FPGAOutput::setParameter(int parameterIndex, float newValue)
 }
 
 void FPGAOutput::process(AudioSampleBuffer& buffer,
-                         MidiBuffer& events,
-                         int& nSamples)
+                         MidiBuffer& events)
 {
 
-
     checkForEvents(events);
-
-
 }
 
 void FPGAOutput::timerCallback()
diff --git a/Source/Processors/FPGAOutput/FPGAOutput.h b/Source/Processors/FPGAOutput/FPGAOutput.h
index 8c1b3d5ae7f235f36acbf869b42da0866f8aabdd..b81479a028b731881247d2f929c277deef392226 100755
--- a/Source/Processors/FPGAOutput/FPGAOutput.h
+++ b/Source/Processors/FPGAOutput/FPGAOutput.h
@@ -49,7 +49,7 @@ public:
     FPGAOutput();
     ~FPGAOutput();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     void setParameter(int parameterIndex, float newValue);
 
     void handleEvent(int eventType, MidiMessage& event, int sampleNum);
diff --git a/Source/Processors/FileReader/FileReader.cpp b/Source/Processors/FileReader/FileReader.cpp
index edb0d18c6c4df5a4789fcf91b1972e64236dcd12..bdeb3f014c73d893052b4cfa9d0e69b8421ff432 100644
--- a/Source/Processors/FileReader/FileReader.cpp
+++ b/Source/Processors/FileReader/FileReader.cpp
@@ -35,6 +35,7 @@ FileReader::FileReader()
 
     enabledState(false);
 
+    counter = 0;
 
 }
 
@@ -72,7 +73,7 @@ float FileReader::getDefaultSampleRate()
         return 44100.0;
 }
 
-int FileReader::getDefaultNumOutputs()
+int FileReader::getNumHeadstageOutputs()
 {
     if (input)
         return currentNumChannels;
@@ -80,10 +81,15 @@ int FileReader::getDefaultNumOutputs()
         return 16;
 }
 
-float FileReader::getBitVolts(int chan)
+int FileReader::getNumEventChannels()
+{
+    return 8;
+}
+
+float FileReader::getBitVolts(Channel* chan)
 {
     if (input)
-        return channelInfo[chan].bitVolts;
+        return chan->bitVolts;
     else
         return 0.05f;
 }
@@ -158,74 +164,45 @@ String FileReader::getFile()
 
 void FileReader::updateSettings()
 {
-    if (!input) return;
+    // if (!input) return;
 
-    for (int i=0; i < currentNumChannels; i++)
-    {
-        channels[i]->bitVolts = channelInfo[i].bitVolts;
-        channels[i]->name = channelInfo[i].name;
-    }
+    // for (int i=0; i < currentNumChannels; i++)
+    // {
+    //     channels[i]->bitVolts = channelInfo[i].bitVolts;
+    //     channels[i]->name = channelInfo[i].name;
+    // }
 }
 
 
 
-void FileReader::process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSamples)
+void FileReader::process(AudioSampleBuffer& buffer, MidiBuffer& events)
 {
 
-    uint8 data[8];
-    memcpy(data, &timestamp, 8);
-
-    // generate timestamp
-    addEvent(events,    // MidiBuffer
-             TIMESTAMP, // eventType
-             0,         // sampleNum
-             nodeId,    // eventID
-             0,		 // eventChannel
-             8,         // numBytes
-             data   // data
-            );
+    setTimestamp(events, timestamp);
 
+    int samplesNeeded = (int) float(buffer.getNumSamples()) * (getDefaultSampleRate()/44100.0f);
     // FIXME: needs to account for the fact that the ratio might not be an exact
     //        integer value
 
-    // code for testing events:
-    // if (counter > 100)
-    // {
-    //     addEvent(events,    // MidiBuffer
-    //          TTL, // eventType
-    //          0,         // sampleNum
-    //          1,    // eventID
-    //          0      // eventChannel
-    //         );
-    //     counter = 0;
-    // } else {
-    //     counter++;
-
-    // }
-
-
-
-    int samplesNeeded = (int) float(buffer.getNumSamples()) * (getDefaultSampleRate()/44100.0f);
-
-    int samplesReaded = 0;
+    int samplesRead = 0;
 
-    while (samplesReaded < samplesNeeded)
+    while (samplesRead < samplesNeeded)
     {
-        int samplesToRead = samplesNeeded - samplesReaded;
+        int samplesToRead = samplesNeeded - samplesRead;
         if ((currentSample + samplesToRead) > stopSample)
         {
             samplesToRead = stopSample - currentSample;
             if (samplesToRead > 0)
-                input->readData(readBuffer+samplesReaded,samplesToRead);
+                input->readData(readBuffer+samplesRead,samplesToRead);
             input->seekTo(startSample);
             currentSample = startSample;
         }
         else
         {
-            input->readData(readBuffer+samplesReaded,samplesToRead);
+            input->readData(readBuffer+samplesRead,samplesToRead);
             currentSample += samplesToRead;
         }
-        samplesReaded += samplesToRead;
+        samplesRead += samplesToRead;
     }
     for (int i=0; i < currentNumChannels; i++)
     {
@@ -233,8 +210,34 @@ void FileReader::process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSa
     }
 
     timestamp += samplesNeeded;
-    static_cast<FileReaderEditor*>(getEditor())->setCurrentTime(samplesToMilliseconds(currentSample));
-    nSamples = samplesNeeded;
+    setNumSamples(events, samplesNeeded);
+
+    // code for testing events:
+    if (counter == 100)
+    {
+        std::cout << "Adding on event for node id: " << nodeId << std::endl;
+        addEvent(events,    // MidiBuffer
+             TTL, // eventType
+             0,         // sampleNum
+             1,    // eventID
+             1      // eventChannel
+            );
+
+        counter++;
+    } else if (counter > 120) 
+    {
+        std::cout << "Adding off event!" << std::endl;
+        addEvent(events,    // MidiBuffer
+             TTL, // eventType
+             0,         // sampleNum
+             0,    // eventID
+             1      // eventChannel
+            );
+
+        counter = 0;
+    } else {
+        counter++;
+    }
 
 }
 
diff --git a/Source/Processors/FileReader/FileReader.h b/Source/Processors/FileReader/FileReader.h
index ffd54c21206bd499009ad97ba9a7db668b5fc652..369a92ab46c02749fd556db03fcb0b35c400ff0c 100644
--- a/Source/Processors/FileReader/FileReader.h
+++ b/Source/Processors/FileReader/FileReader.h
@@ -49,7 +49,7 @@ public:
     FileReader();
     ~FileReader();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     void setParameter(int parameterIndex, float newValue);
 
     AudioProcessorEditor* createEditor();
@@ -71,8 +71,9 @@ public:
     void enabledState(bool t);
 
     float getDefaultSampleRate();
-    int getDefaultNumOutputs();
-    float getBitVolts(int chan);
+    int getNumHeadstageOutputs();
+    int getNumEventChannels();
+    float getBitVolts(Channel* chan);
 
     bool setFile(String fullpath);
     String getFile();
@@ -90,6 +91,8 @@ private:
 
     int64 currentSample;
 
+    int counter; // for testing purposes only
+
     ScopedPointer<FileSource> input;
 
     HeapBlock<int16> readBuffer;
diff --git a/Source/Processors/FilterNode/FilterNode.cpp b/Source/Processors/FilterNode/FilterNode.cpp
index 04b92d3c607a4e16961349d47ff37e46424f0734..9d2716b701c0453d6f6c786778635789625eb2a5 100755
--- a/Source/Processors/FilterNode/FilterNode.cpp
+++ b/Source/Processors/FilterNode/FilterNode.cpp
@@ -207,7 +207,7 @@ void FilterNode::setFilterParameters(double lowCut, double highCut, int chan)
 {
 
     Dsp::Params params;
-    params[0] = getSampleRate(); // sample rate
+    params[0] = channels[chan]->sampleRate; // sample rate
     params[1] = 2; // order
     params[2] = (highCut + lowCut)/2; // center frequency
     params[3] = highCut - lowCut; // bandwidth
@@ -261,8 +261,7 @@ void FilterNode::setParameter(int parameterIndex, float newValue)
 }
 
 void FilterNode::process(AudioSampleBuffer& buffer,
-                         MidiBuffer& midiMessages,
-                         int& nSamples)
+                         MidiBuffer& midiMessages)
 {
 
     for (int n = 0; n < getNumOutputs(); n++)
@@ -270,7 +269,7 @@ void FilterNode::process(AudioSampleBuffer& buffer,
         if (shouldFilterChannel[n])
         {
             float* ptr = buffer.getWritePointer(n);
-            filters[n]->process(nSamples, &ptr);
+            filters[n]->process(getNumSamples(n), &ptr);
         }
     }
 
diff --git a/Source/Processors/FilterNode/FilterNode.h b/Source/Processors/FilterNode/FilterNode.h
index 4a0b9886f5ccbd55caae574b493aa6ca59defff2..c026537acc60c8286b38173380e0cd4d5125754e 100755
--- a/Source/Processors/FilterNode/FilterNode.h
+++ b/Source/Processors/FilterNode/FilterNode.h
@@ -46,7 +46,7 @@ public:
     FilterNode();
     ~FilterNode();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     void setParameter(int parameterIndex, float newValue);
 
     AudioProcessorEditor* createEditor();
diff --git a/Source/Processors/GenericProcessor/GenericProcessor.cpp b/Source/Processors/GenericProcessor/GenericProcessor.cpp
index 8cd369d65f30890b92a7edae0600f331e641ea1c..dd148c568c03065f7fff7224e4b8a81cf0671c61 100755
--- a/Source/Processors/GenericProcessor/GenericProcessor.cpp
+++ b/Source/Processors/GenericProcessor/GenericProcessor.cpp
@@ -24,10 +24,12 @@
 #include "GenericProcessor.h"
 #include "../../UI/UIComponent.h"
 
+#include <exception>
+
 GenericProcessor::GenericProcessor(const String& name_) : AccessClass(),
     sourceNode(0), destNode(0), isEnabled(true), wasConnected(false),
     nextAvailableChannel(0), saveOrder(-1), loadOrder(-1), currentChannel(-1),
-     editor(0), parametersAsXml(nullptr), sendSampleCount(true), name(name_), paramsWereLoaded(false)
+    editor(0), parametersAsXml(nullptr), sendSampleCount(true), name(name_), paramsWereLoaded(false)
 {
     settings.numInputs = settings.numOutputs = settings.sampleRate = 0;
 
@@ -303,16 +305,21 @@ void GenericProcessor::update()
     std::cout << getName() << " updating settings." << std::endl;
     // SO patched here to keep original channel names
 
+    // save original channel names
     int oldNumChannels = channels.size();
+
     StringArray oldNames;
+
     for (int k = 0; k < oldNumChannels; k++)
     {
         oldNames.add(channels[k]->getName());
     }
 
+    // ---- RESET EVERYTHING ---- ///
     clearSettings();
 
-    if (sourceNode != 0)
+
+    if (sourceNode != 0) // copy settings from source node
     {
         // everything is inherited except numOutputs
         settings = sourceNode->settings;
@@ -324,8 +331,7 @@ void GenericProcessor::update()
             Channel* sourceChan = sourceNode->channels[i];
             Channel* ch = new Channel(*sourceChan);
             ch->setProcessor(this);
-            ch->bitVolts = ch->bitVolts*getBitVolts(i);
-			ch->num = i;
+            ch->nodeIndex = i;
 
             if (i < recordStatus.size())
             {
@@ -340,63 +346,96 @@ void GenericProcessor::update()
         {
             Channel* sourceChan = sourceNode->eventChannels[i];
             Channel* ch = new Channel(*sourceChan);
-            ch->sampleRate = getDefaultSampleRate();
-            ch->bitVolts = getDefaultBitVolts();
+            ch->setProcessor(this);
             eventChannels.add(ch);
         }
 
     }
-    else
+    else // generate new settings
     {
-        settings.numOutputs = getDefaultNumOutputs();
         settings.sampleRate = getDefaultSampleRate();
+        settings.numOutputs = getNumHeadstageOutputs() + getNumAdcOutputs() + getNumAuxOutputs();
 
-        int numChan = getNumOutputs();
-        int numADC_Chan = getDefaultADCoutputs();
-
-		Array<channelType> types;
-		Array<int> stream, orig;
-		Array<float> gains;
-		StringArray names;
-		getChannelsInfo(names, types, stream, orig, gains);
+        std::cout << getName() << " setting num outputs to " << settings.numOutputs << std::endl;
+        int nidx = 0;
 
-        for (int i = 0; i < numChan; i++)
+        for (int i = 0; i < getNumHeadstageOutputs(); i++)
         {
-            Channel* ch = new Channel(this, i);
+            Channel* ch = new Channel(this, i+1, HEADSTAGE_CHANNEL);
+            ch->setProcessor(this);
+            ch->sampleRate = getDefaultSampleRate();
+            ch->bitVolts = getBitVolts(ch);
+            ch->sourceNodeId = nodeId;
+            ch->nodeIndex = nidx;
 
-            // if (i < oldNumChannels)
-            // 	ch->setName(oldNames[i]);
-            //else if (i >= numChan-numADC_Chan)
-            //	ch->setName("ADC"+String(1+i-(numChan-numADC_Chan)));
+            if (i < recordStatus.size())
+            {
+                ch->setRecordState(recordStatus[i]);
+            }
+            else
+            {
+                if (isSource())
+                    ch->setRecordState(true);
+            }
 
-            if (i >= numChan-numADC_Chan)
-                ch->setName("ADC" + String(1+i-(numChan-numADC_Chan)));
+            channels.add(ch);
+            nidx++;
+        }
 
-            if (i >= numChan-numADC_Chan)
-				ch->setType(ADC_CHANNEL);
+        for (int j = 0; j < getNumAuxOutputs(); j++)
+        {
+            Channel* ch = new Channel(this, j+1, AUX_CHANNEL);
+            ch->setProcessor(this);
+            ch->sampleRate = getDefaultSampleRate();
+            ch->bitVolts = getBitVolts(ch);
+            ch->sourceNodeId = nodeId;
+            ch->nodeIndex = nidx;
+
+            if (j < recordStatus.size())
+            {
+                ch->setRecordState(recordStatus[j]);
+            }
+            else
+            {
+                if (isSource())
+                    ch->setRecordState(true);
+            }
 
-			if (i < stream.size())
-			{
-			  ch->originalStream = stream[i];
-			  ch->originalChannel = orig[i];
-			}
+            channels.add(ch);
+            nidx++;
+        }
+
+        for (int k = 0; k < getNumAdcOutputs(); k++)
+        {
+            Channel* ch = new Channel(this, k+1, ADC_CHANNEL);
+            ch->setProcessor(this);
             ch->sampleRate = getDefaultSampleRate();
+            ch->bitVolts = getBitVolts(ch);
+            ch->sourceNodeId = nodeId;
+            ch->nodeIndex = nidx;
 
-            //  if (ch->isADCchannel)
-            ch->bitVolts = getDefaultBitVolts();
-            //  else
-            //      ch->bitVolts = getDefaultAdcBitVolts(); // should implement this
+            if (k < recordStatus.size())
+            {
 
-            if (i < recordStatus.size())
+                ch->setRecordState(recordStatus[k]);
+            }
+            else
             {
-                ch->setRecordState(recordStatus[i]);
-				ch->isMonitored = monitorStatus[i];
-            } else {
-                if (this->isSource())
+                if (isSource())
                     ch->setRecordState(true);
             }
 
             channels.add(ch);
+            nidx++;
+        }
+
+        for (int m = 0; m < getNumEventChannels(); m++)
+        {
+            Channel* ch = new Channel(this, m+1, EVENT_CHANNEL);
+            ch->sourceNodeId = nodeId;
+            ch->nodeIndex = nidx;
+            eventChannels.add(ch);
+            ch->sampleRate = getDefaultSampleRate();
         }
 
     }
@@ -406,7 +445,7 @@ void GenericProcessor::update()
         settings.numOutputs = 0;
     }
 
-    updateSettings(); // custom settings code
+    updateSettings(); // allow processors to change custom settings
 
     // required for the ProcessorGraph to know the
     // details of this processor:
@@ -415,16 +454,16 @@ void GenericProcessor::update()
                          44100.0,         // sampleRate
                          128);            // blockSize
 
-    editor->update(); // update editor settings
+    editor->update(); // allow the editor to update its settings
 
 }
 
 void GenericProcessor::setAllChannelsToRecord()
 {
 
-    recordStatus.resize(getDefaultNumOutputs());
+    recordStatus.resize(channels.size());
 
-    for (int i = 0; i < getDefaultNumOutputs(); i++)
+    for (int i = 0; i < channels.size(); i++)
     {
         recordStatus.set(i,true);
     }
@@ -435,19 +474,19 @@ void GenericProcessor::setAllChannelsToRecord()
 
 void GenericProcessor::setRecording(bool state)
 {
-	GenericEditor* ed = getEditor();
-	if (state)
-	{
-		if (ed != 0)
-			ed->startRecording();
-		startRecording();
-	}
-	else
-	{
-		if (ed != 0)
-			ed->stopRecording();
-		stopRecording();
-	}
+    GenericEditor* ed = getEditor();
+    if (state)
+    {
+        if (ed != 0)
+            ed->startRecording();
+        startRecording();
+    }
+    else
+    {
+        if (ed != 0)
+            ed->stopRecording();
+        stopRecording();
+    }
 }
 
 void GenericProcessor::enableEditor()
@@ -469,7 +508,105 @@ void GenericProcessor::disableEditor()
         ed->stopAcquisition();
 }
 
-int GenericProcessor::getNumSamples(MidiBuffer& events)
+/** Used to get the number of samples in a given buffer, for a given channel. */
+int GenericProcessor::getNumSamples(int channelNum)
+{
+    int sourceNodeId, nSamples;
+
+    if (channelNum >= 0 && channelNum < channels.size())
+        sourceNodeId = channels[channelNum]->sourceNodeId;
+    else
+        return 0;
+
+    // std::cout << "Requesting samples for channel " << channelNum << " with source node " << sourceNodeId << std::endl;
+
+    try
+    {
+        nSamples = numSamples.at(sourceNodeId);
+    }
+    catch (std::exception& e)
+    {
+        return 0;
+    }
+
+    //std::cout << nSamples << " were found." << std::endl;
+
+    return nSamples;
+}
+
+
+/** Used to get the number of samples in a given buffer, for a given source node. */
+void GenericProcessor::setNumSamples(MidiBuffer& events, int sampleIndex)
+{
+
+    // This amounts to adding a "buffer size" flag at a particular sample number,
+    // and a new flag is added each time "setNumSamples" is called.
+    // Thus, if the number of samples changes somewhere in the processing pipeline,
+    // the old sample number will remain. This is a problem if the number of
+    // samples gets smaller.
+    // If we allow the sample rate to change (e.g., with a resampling node),
+    // this code will have to be updated. The easiest approach will be for each
+    // processor to ignore any buffer size events that don't come from its
+    // immediate source.
+    //
+
+    uint8 data[4];
+
+    int16 si = (int16) sampleIndex;
+
+    data[0] = BUFFER_SIZE;  // most-significant byte
+    data[1] = nodeId;       // least-significant byte
+    memcpy(data+2, &si, 2);
+
+    events.addEvent(data,       // spike data
+                    4,          // total bytes
+                    0); // sample index
+}
+
+/** Used to get the timestamp for a given buffer, for a given source node. */
+int64 GenericProcessor::getTimestamp(int channelNum)
+{
+    int sourceNodeId;
+    int64 ts;
+
+    if (channelNum >= 0 && channelNum < channels.size())
+        sourceNodeId = channels[channelNum]->sourceNodeId;
+    else
+        return 0;
+
+    try
+    {
+        ts = timestamps.at(sourceNodeId);
+    }
+    catch (std::exception& e)
+    {
+        return 0;
+    }
+
+    return ts;
+}
+
+/** Used to set the timestamp for a given buffer, for a given channel. */
+void GenericProcessor::setTimestamp(MidiBuffer& events, int64 timestamp)
+{
+
+    //std::cout << "Setting timestamp to " << timestamp << std:;endl;
+
+    uint8 data[8];
+    memcpy(data, &timestamp, 8);
+
+    // generate timestamp
+    addEvent(events,    // MidiBuffer
+             TIMESTAMP, // eventType
+             0,         // sampleNum
+             nodeId,    // eventID
+             0,      // eventChannel
+             8,         // numBytes
+             data   // data
+            );
+}
+
+int GenericProcessor::processEventBuffer(MidiBuffer& events)
 {
     //
     // This loops through all events in the buffer, and uses the BUFFER_SIZE
@@ -508,54 +645,49 @@ int GenericProcessor::getNumSamples(MidiBuffer& events)
 
                 numRead = nr;
 
+                uint8 sourceNodeId;
+                memcpy(&sourceNodeId, dataptr + 1, 1);
+
+                numSamples[sourceNodeId] = numRead;
+
+                //if (nodeId < 900)
+                //    std::cout << nodeId << " got " << numRead << " samples for " << (int) sourceNodeId << std::endl;
+
+
+            }
+            else if (*dataptr == TIMESTAMP)
+            {
+                int64 ts;
+                memcpy(&ts, dataptr+4, 8);
+
+                uint8 sourceNodeId;
+                memcpy(&sourceNodeId, dataptr + 1, 1);
+
+                timestamps[sourceNodeId] = ts;
+
+                //if (nodeId < 900)
+                //    std::cout << nodeId << " got " << ts << " timestamp for " << (int) sourceNodeId << std::endl;
+
             }
             else
+            {
 
                 if (*dataptr == TTL &&    // a TTL event
                     getNodeId() < 900 && // not handled by a specialized processor (e.g. AudioNode))
-                    *(dataptr+1) > 0)    // that's flagged for saving
+                    *(dataptr+4) > 0)    // that's flagged for saving
                 {
                     // changing the const cast is dangerous, but probably necessary:
                     uint8* ptr = const_cast<uint8*>(dataptr);
-                    *(ptr + 1) = 0; // set second byte of raw data to 0, so the event
-                    // won't be saved twice
+                    *(ptr + 4) = 0; // set fifth byte of raw data to 0, so the event
+                                    // won't be saved twice
                 }
+            }
         }
     }
 
     return numRead;
 }
 
-void GenericProcessor::setNumSamples(MidiBuffer& events, int sampleIndex)
-{
-    //
-    // This amounts to adding a "buffer size" flag at a particular sample number,
-    // and a new flag is added each time "setNumSamples" is called.
-    // Thus, if the number of samples changes somewhere in the processing pipeline,
-    // the old sample number will remain. This is a problem if the number of
-    // samples gets smaller.
-    // If we allow the sample rate to change (e.g., with a resampling node),
-    // this code will have to be updated. The easiest approach will be for each
-    // processor to ignore any buffer size events that don't come from its
-    // immediate source.
-    //
-
-    uint8 data[4];
-
-    int16 si = (int16) sampleIndex;
-
-    data[0] = BUFFER_SIZE;  // most-significant byte
-    data[1] = nodeId;       // least-significant byte
-    memcpy(data+2, &si, 2);
-
-    events.addEvent(data,       // spike data
-                    4,          // total bytes
-                    0); // sample index
-
-    // std::cout << "Processor " << getNodeId() << " adding a new sample count of " << sampleIndex << std::endl;
-
-}
-
 
 int GenericProcessor::checkForEvents(MidiBuffer& midiMessages)
 {
@@ -595,16 +727,19 @@ void GenericProcessor::addEvent(MidiBuffer& eventBuffer,
                                 uint8 numBytes,
                                 uint8* eventData)
 {
-    uint8* data = new uint8[4+numBytes];
+    uint8* data = new uint8[5+numBytes];
 
     data[0] = type;    // event type
     data[1] = nodeId;  // processor ID automatically added
-    data[2] = eventId; // event ID
+    data[2] = eventId; // event ID (1 = on, 0 = off, usually)
     data[3] = eventChannel; // event channel
-    memcpy(data + 4, eventData, numBytes);
+    data[4] = 1; // saving flag
+    memcpy(data + 5, eventData, numBytes);
+
+    //std::cout << "Node id: " << data[1] << std::endl;
 
     eventBuffer.addEvent(data, 		// raw data
-                         4 + numBytes, // total bytes
+                         5 + numBytes, // total bytes
                          sampleNum);     // sample index
 
     //if (type == TTL)
@@ -622,14 +757,10 @@ void GenericProcessor::addEvent(MidiBuffer& eventBuffer,
 void GenericProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& eventBuffer)
 {
 
-    int nSamples = getNumSamples(eventBuffer); // finds buffer size and sets save
-    // flag on all TTL events to zero
-
-    process(buffer, eventBuffer, nSamples);
+    processEventBuffer(eventBuffer); // extract buffer sizes and timestamps,
+    // set flag on all TTL events to zero
 
-    if (sendSampleCount)
-        setNumSamples(eventBuffer, nSamples); // adds it back,
-    // even if it's unchanged
+    process(buffer, eventBuffer);
 
 }
 
diff --git a/Source/Processors/GenericProcessor/GenericProcessor.h b/Source/Processors/GenericProcessor/GenericProcessor.h
index 8c3f2719fbd03a5e2f6852dd64a8ec86e542839e..ce62e607d0a5d2bc61302b92b4dc26397994ba5d 100755
--- a/Source/Processors/GenericProcessor/GenericProcessor.h
+++ b/Source/Processors/GenericProcessor/GenericProcessor.h
@@ -24,8 +24,9 @@
 #ifndef __GENERICPROCESSOR_H_1F469DAF__
 #define __GENERICPROCESSOR_H_1F469DAF__
 
-enum channelType {DATA_CHANNEL = 0, AUX_CHANNEL = 1, ADC_CHANNEL = 2, EVENT_CHANNEL = 3};
-
+enum ChannelType {HEADSTAGE_CHANNEL = 0, AUX_CHANNEL = 1, ADC_CHANNEL = 2, EVENT_CHANNEL = 3,
+                  SINGLE_ELECTRODE = 4, STEREOTRODE = 5, TETRODE = 6
+                 };
 
 #include "../../../JuceLibraryCode/JuceHeader.h"
 #include "../Editors/GenericEditor.h"
@@ -35,6 +36,7 @@ enum channelType {DATA_CHANNEL = 0, AUX_CHANNEL = 1, ADC_CHANNEL = 2, EVENT_CHAN
 
 #include <time.h>
 #include <stdio.h>
+#include <map>
 
 class EditorViewport;
 class DataViewport;
@@ -60,7 +62,6 @@ class Channel;
 
 */
 
-
 class GenericProcessor : public AudioProcessor,
     public AccessClass
 
@@ -137,23 +138,23 @@ public:
     {
         return GenericProcessor::unusedNameString;
     }
-    
+
     /** returns the names and types of all data, aux and adc channels */
-    virtual void getChannelsInfo(StringArray &Names, Array<channelType> &type, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains)
+    virtual void getChannelsInfo(StringArray& Names, Array<ChannelType>& type, Array<int>& stream, Array<int>& originalChannelNumber, Array<float>& gains)
     {
 
     }
 
-    virtual int modifyChannelName(channelType t, int stream, int ch, String newName, bool updateSignalChain)
+    virtual int modifyChannelName(ChannelType t, int stream, int ch, String newName, bool updateSignalChain)
     {
         return -1;
     }
 
-    virtual int modifyChannelGain(channelType t, int stream, int ch, float newGain, bool updateSignalChain)
+    virtual int modifyChannelGain(ChannelType t, int stream, int ch, float newGain, bool updateSignalChain)
     {
         return -1;
     }
-    virtual void getEventChannelNames(StringArray &Names)
+    virtual void getEventChannelNames(StringArray& Names)
     {
     }
 
@@ -260,8 +261,7 @@ public:
     the number of samples in the current buffer.
     */
     virtual void process(AudioSampleBuffer& continuousBuffer,
-                         MidiBuffer& eventBuffer,
-                         int& nSamples) = 0;
+                         MidiBuffer& eventBuffer) = 0;
 
     /** Pointer to a processor's immediate source node.*/
     GenericProcessor* sourceNode;
@@ -293,13 +293,26 @@ public:
         return settings.numOutputs;
     }
 
-    /** Returns the default number of outputs, in case a processor has no source (or is itself a source).*/
-    virtual int getDefaultNumOutputs()
+    /** Returns the default number of headstage (neural data) outputs, in case a processor has no source (or is itself a source).*/
+    virtual int getNumHeadstageOutputs()
     {
         return 2;
     }
 
-      virtual int getDefaultADCoutputs()
+    /** Returns the default number of ADC (typically 0-5V, or -5 to +5V) outputs. */
+    virtual int getNumAdcOutputs()
+    {
+        return 0;
+    }
+
+    /** Returns the default number of auxiliary (e.g. accelerometer) outputs. */
+    virtual int getNumAuxOutputs()
+    {
+        return 0;
+    }
+
+    /** Returns the default number of event channels. */
+    virtual int getNumEventChannels()
     {
         return 0;
     }
@@ -310,11 +323,11 @@ public:
         return 1.0;
     }
 
-	/** Returns the bit volts for a given channel **/
-	virtual float getBitVolts(int chan)
-	{
-		return 1.0; 
-	}
+    /** Returns the bit volts for a given channel **/
+    virtual float getBitVolts(Channel* chan)
+    {
+        return 1.0;
+    }
 
 
     /** Returns the next available channel (and increments the channel if the input is set to 'true'. */
@@ -394,7 +407,7 @@ public:
     {
         return false;
     }
-    
+
     /** Returns true if a processor is a utility (non-merger or splitter), false otherwise.*/
     virtual bool isUtility()
     {
@@ -428,9 +441,9 @@ public:
         return true;
     }
 
-	/** Called when recording starts/stops **/
-	void setRecording(bool state);
-    
+    /** Called when recording starts/stops **/
+    void setRecording(bool state);
+
     /** Called from setRecording whenever recording has started. */
     virtual void startRecording() { }
 
@@ -513,14 +526,6 @@ public:
         MESSAGE = 10
     };
 
-    enum eventChannelTypes
-    {
-        GENERIC_EVENT = 100,
-        SINGLE_ELECTRODE = 1,
-        STEREOTRODE = 2,
-        TETRODE = 4
-    };
-
     /** Variable used to orchestrate saving the ProcessorGraph. */
     int saveOrder;
 
@@ -617,7 +622,10 @@ public:
     virtual void loadCustomChannelParametersFromXml(XmlElement* channelElement, bool isEventChannel=false);
 
     /** handle messages from other processors */
-    virtual String interProcessorCommunication(String command) { return String("OK"); };
+    virtual String interProcessorCommunication(String command)
+    {
+        return String("OK");
+    };
 
     /** Holds loaded parameters */
     XmlElement* parametersAsXml;
@@ -625,6 +633,21 @@ public:
     /** When set to false, this disables the sending of sample counts through the event buffer. */
     bool sendSampleCount;
 
+    /** Used to get the number of samples in a given buffer, for a given channel. */
+    int getNumSamples(int channelNumber);
+
+    /** Used to get the number of samples in a given buffer, for a given source node. */
+    void setNumSamples(MidiBuffer&, int numSamples);
+
+    /** Used to get the timestamp for a given buffer, for a given channel. */
+    int64 getTimestamp(int channelNumber);
+
+    /** Used to set the timestamp for a given buffer, for a given source node. */
+    void setTimestamp(MidiBuffer&, int64 timestamp);
+
+    std::map<uint8, int> numSamples;
+    std::map<uint8, int64> timestamps;
+
 private:
 
     /** Automatically extracts the number of samples in the buffer, then
@@ -638,13 +661,8 @@ private:
     Array<bool> recordStatus;
 	Array<bool> monitorStatus;
 
-    /** Returns the number of samples for the current continuous buffer (assumed to be
-    the same for all channels).*/
-    int getNumSamples(MidiBuffer&);
-
-    /** Updates the number of samples for the current continuous buffer (assumed to be
-    the same for all channels).*/
-    void setNumSamples(MidiBuffer&, int);
+    /** Extracts sample counts and timestamps from the MidiBuffer. */
+    int processEventBuffer(MidiBuffer&);
 
     /** For getInputChannelName() and getOutputChannelName() */
     static const String unusedNameString;
diff --git a/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.cpp b/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.cpp
index 712a71987ba6d891e55f358cded0baeeec0dcb19..d6337a50b611d901f0f1a1a988e94f543fea3c45 100755
--- a/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.cpp
+++ b/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.cpp
@@ -26,13 +26,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <math.h>
 
 LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) :
-    screenBufferIndex(0), timebase(1.0f), displayGain(1.0f),   timeOffset(0.0f),
-    processor(processor_), selectedChannelType(DATA_CHANNEL),
-    displayBufferIndex(0)
+     timebase(1.0f), displayGain(1.0f),   timeOffset(0.0f),
+    processor(processor_), selectedChannelType(HEADSTAGE_CHANNEL)
 {
 
     nChans = processor->getNumInputs();
-    sampleRate = processor->getSampleRate();
     std::cout << "Setting num inputs on LfpDisplayCanvas to " << nChans << std::endl;
 
     displayBuffer = processor->getDisplayBufferAddress();
@@ -64,40 +62,39 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) :
 
     //viewport->getVerticalScrollBar()->addListener(this->scrollBarMoved(viewport->getVerticalScrollBar(), 1.0));
 
-
+    UtilityButton* tbut;
 
     addAndMakeVisible(viewport);
     addAndMakeVisible(timescale);
 
-	UtilityButton* tbut;
-
     //Ranges for neural data
-     voltageRanges[DATA_CHANNEL].add("25");
-    voltageRanges[DATA_CHANNEL].add("50");
-    voltageRanges[DATA_CHANNEL].add("100");
-    voltageRanges[DATA_CHANNEL].add("250");
-    voltageRanges[DATA_CHANNEL].add("400");
-    voltageRanges[DATA_CHANNEL].add("500");
-    voltageRanges[DATA_CHANNEL].add("750");
-    voltageRanges[DATA_CHANNEL].add("1000");
-    voltageRanges[DATA_CHANNEL].add("2000");
-    voltageRanges[DATA_CHANNEL].add("5000");
-	voltageRanges[DATA_CHANNEL].add("10000");
-	selectedVoltageRange[DATA_CHANNEL] = 8;
-	rangeGain[DATA_CHANNEL] = 1; //uV
-	rangeSteps[DATA_CHANNEL] = 10;
-	rangeUnits.add("uV");
-	typeNames.add("DATA");
-	tbut  = new UtilityButton("DATA",Font("Small Text", 9, Font::plain));
-	tbut->setEnabledState(true);
-	tbut->setCorners(false,false,false,false);
-	tbut->addListener(this);
-	tbut->setClickingTogglesState(true);
-	tbut->setRadioGroupId(100,dontSendNotification);
-	tbut->setToggleState(true,dontSendNotification);
-	addAndMakeVisible(tbut);
-	typeButtons.add(tbut);
-	
+     voltageRanges[HEADSTAGE_CHANNEL].add("25");
+    voltageRanges[HEADSTAGE_CHANNEL].add("50");
+    voltageRanges[HEADSTAGE_CHANNEL].add("100");
+    voltageRanges[HEADSTAGE_CHANNEL].add("250");
+    voltageRanges[HEADSTAGE_CHANNEL].add("400");
+    voltageRanges[HEADSTAGE_CHANNEL].add("500");
+    voltageRanges[HEADSTAGE_CHANNEL].add("750");
+    voltageRanges[HEADSTAGE_CHANNEL].add("1000");
+    voltageRanges[HEADSTAGE_CHANNEL].add("2000");
+    voltageRanges[HEADSTAGE_CHANNEL].add("5000");
+    voltageRanges[HEADSTAGE_CHANNEL].add("10000");
+    selectedVoltageRange[HEADSTAGE_CHANNEL] = 8;
+    rangeGain[HEADSTAGE_CHANNEL] = 1; //uV
+    rangeSteps[HEADSTAGE_CHANNEL] = 10;
+    rangeUnits.add("uV");
+    typeNames.add("DATA");
+
+    tbut = new UtilityButton("DATA",Font("Small Text", 9, Font::plain));
+    tbut->setEnabledState(true);
+    tbut->setCorners(false,false,false,false);
+    tbut->addListener(this);
+    tbut->setClickingTogglesState(true);
+    tbut->setRadioGroupId(100,dontSendNotification);
+    tbut->setToggleState(true,dontSendNotification);
+    addAndMakeVisible(tbut);
+    typeButtons.add(tbut);
+    
 
     //Ranges for AUX/accelerometer data
     voltageRanges[AUX_CHANNEL].add("25");
@@ -110,20 +107,21 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) :
     voltageRanges[AUX_CHANNEL].add("1000");
     voltageRanges[AUX_CHANNEL].add("2000");
     voltageRanges[AUX_CHANNEL].add("5000");
-	selectedVoltageRange[AUX_CHANNEL] = 6;
-	rangeGain[AUX_CHANNEL] = 1; //uV
-	rangeSteps[AUX_CHANNEL] = 10;
-	rangeUnits.add("uV");
-	typeNames.add("AUX");
-	tbut  = new UtilityButton("AUX",Font("Small Text", 9, Font::plain));
-	tbut->setEnabledState(true);
-	tbut->setCorners(false,false,false,false);
-	tbut->addListener(this);
-	tbut->setClickingTogglesState(true);
-	tbut->setRadioGroupId(100,dontSendNotification);
-	tbut->setToggleState(false,dontSendNotification);
-	addAndMakeVisible(tbut);
-	typeButtons.add(tbut);
+    selectedVoltageRange[AUX_CHANNEL] = 6;
+    rangeGain[AUX_CHANNEL] = 1; //uV
+    rangeSteps[AUX_CHANNEL] = 10;
+    rangeUnits.add("uV");
+    typeNames.add("AUX");
+
+    tbut = new UtilityButton("AUX",Font("Small Text", 9, Font::plain));
+    tbut->setEnabledState(true);
+    tbut->setCorners(false,false,false,false);
+    tbut->addListener(this);
+    tbut->setClickingTogglesState(true);
+    tbut->setRadioGroupId(100,dontSendNotification);
+    tbut->setToggleState(false,dontSendNotification);
+    addAndMakeVisible(tbut);
+    typeButtons.add(tbut);
 
     //Ranges for ADC data
      voltageRanges[ADC_CHANNEL].add("0.01");
@@ -132,28 +130,29 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) :
     voltageRanges[ADC_CHANNEL].add("0.5");
     voltageRanges[ADC_CHANNEL].add("1.0");
     voltageRanges[ADC_CHANNEL].add("2.0");
-	voltageRanges[ADC_CHANNEL].add("5.0");
-	voltageRanges[ADC_CHANNEL].add("10.0");
-	selectedVoltageRange[ADC_CHANNEL] = 8;
-	rangeGain[ADC_CHANNEL] = 1; //V
-	rangeSteps[ADC_CHANNEL] = 0.1; //in V
-	rangeUnits.add("V");
-	typeNames.add("ADC");
-	tbut  = new UtilityButton("ADC",Font("Small Text", 9, Font::plain));
-	tbut->setEnabledState(true);
-	tbut->setCorners(false,false,false,false);
-	tbut->addListener(this);
-	tbut->setClickingTogglesState(true);
-	tbut->setRadioGroupId(100,dontSendNotification);
-	tbut->setToggleState(false,dontSendNotification);
-	addAndMakeVisible(tbut);
-	typeButtons.add(tbut);
-
-	selectedVoltageRangeValues[DATA_CHANNEL] = voltageRanges[DATA_CHANNEL][selectedVoltageRange[DATA_CHANNEL]-1];
-	selectedVoltageRangeValues[AUX_CHANNEL] = voltageRanges[AUX_CHANNEL][selectedVoltageRange[AUX_CHANNEL]-1];
-	selectedVoltageRangeValues[ADC_CHANNEL] = voltageRanges[ADC_CHANNEL][selectedVoltageRange[ADC_CHANNEL]-1];
-
-	timebases.add("0.25");
+    voltageRanges[ADC_CHANNEL].add("5.0");
+    voltageRanges[ADC_CHANNEL].add("10.0");
+    selectedVoltageRange[ADC_CHANNEL] = 8;
+    rangeGain[ADC_CHANNEL] = 1; //V
+    rangeSteps[ADC_CHANNEL] = 0.1; //in V
+    rangeUnits.add("V");
+    typeNames.add("ADC");
+
+    tbut = new UtilityButton("ADC",Font("Small Text", 9, Font::plain));
+    tbut->setEnabledState(true);
+    tbut->setCorners(false,false,false,false);
+    tbut->addListener(this);
+    tbut->setClickingTogglesState(true);
+    tbut->setRadioGroupId(100,dontSendNotification);
+    tbut->setToggleState(false,dontSendNotification);
+    addAndMakeVisible(tbut);
+    typeButtons.add(tbut);
+
+    selectedVoltageRangeValues[HEADSTAGE_CHANNEL] = voltageRanges[HEADSTAGE_CHANNEL][selectedVoltageRange[HEADSTAGE_CHANNEL]-1];
+    selectedVoltageRangeValues[AUX_CHANNEL] = voltageRanges[AUX_CHANNEL][selectedVoltageRange[AUX_CHANNEL]-1];
+    selectedVoltageRangeValues[ADC_CHANNEL] = voltageRanges[ADC_CHANNEL][selectedVoltageRange[ADC_CHANNEL]-1];
+
+    timebases.add("0.25");
     timebases.add("0.5");
     timebases.add("1.0");
     timebases.add("2.0");
@@ -162,8 +161,8 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) :
     timebases.add("5.0");
     timebases.add("10.0");
     timebases.add("20.0");
-	selectedTimebase = 4;
-	selectedTimebaseValue = timebases[selectedTimebase-1];
+    selectedTimebase = 4;
+    selectedTimebaseValue = timebases[selectedTimebase-1];
 
     spreads.add("10");
     spreads.add("20");
@@ -175,8 +174,8 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) :
     spreads.add("80");
     spreads.add("90");
     spreads.add("100");
-	selectedSpread = 5;
-	selectedSpreadValue = spreads[selectedSpread-1];
+    selectedSpread = 5;
+    selectedSpreadValue = spreads[selectedSpread-1];
 
     colorGroupings.add("1");
     colorGroupings.add("2");
@@ -186,26 +185,26 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) :
 
 
     rangeSelection = new ComboBox("Voltage range");
-    rangeSelection->addItemList(voltageRanges[DATA_CHANNEL], 1);
-	rangeSelection->setSelectedId(selectedVoltageRange[DATA_CHANNEL], sendNotification);
-	rangeSelection->setEditableText(true);
+    rangeSelection->addItemList(voltageRanges[HEADSTAGE_CHANNEL], 1);
+    rangeSelection->setSelectedId(selectedVoltageRange[HEADSTAGE_CHANNEL], sendNotification);
+    rangeSelection->setEditableText(true);
     rangeSelection->addListener(this);
     addAndMakeVisible(rangeSelection);
 
 
     timebaseSelection = new ComboBox("Timebase");
     timebaseSelection->addItemList(timebases, 1);
-	timebaseSelection->setSelectedId(selectedTimebase, sendNotification);
-	timebaseSelection->setEditableText(true);
+    timebaseSelection->setSelectedId(selectedTimebase, sendNotification);
+    timebaseSelection->setEditableText(true);
     timebaseSelection->addListener(this);
     addAndMakeVisible(timebaseSelection);
 
 
     spreadSelection = new ComboBox("Spread");
     spreadSelection->addItemList(spreads, 1);
-	spreadSelection->setSelectedId(selectedSpread,sendNotification);
+    spreadSelection->setSelectedId(selectedSpread,sendNotification);
     spreadSelection->addListener(this);
-	spreadSelection->setEditableText(true);
+    spreadSelection->setEditableText(true);
     addAndMakeVisible(spreadSelection);
 
     colorGroupingSelection = new ComboBox("Color Grouping");
@@ -245,8 +244,8 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) :
 
 
     lfpDisplay->setNumChannels(nChans);
-	lfpDisplay->setRange(voltageRanges[DATA_CHANNEL][selectedVoltageRange[DATA_CHANNEL]-1].getFloatValue()*rangeGain[DATA_CHANNEL]
-		,DATA_CHANNEL);
+    lfpDisplay->setRange(voltageRanges[HEADSTAGE_CHANNEL][selectedVoltageRange[HEADSTAGE_CHANNEL]-1].getFloatValue()*rangeGain[HEADSTAGE_CHANNEL]
+        ,HEADSTAGE_CHANNEL);
 
     // add event display-specific controls (currently just an enable/disable button)
     for (int i = 0; i < 8; i++)
@@ -302,12 +301,11 @@ void LfpDisplayCanvas::resized()
         eventDisplayInterfaces[i]->repaint();
     }
 
-	int bh = 25/typeButtons.size();
-	for (int i = 0; i < typeButtons.size(); i++)
-	{
-		typeButtons[i]->setBounds(110,getHeight()-30+i*bh,50,bh);
-	}
-
+    int bh = 25/typeButtons.size();
+    for (int i = 0; i < typeButtons.size(); i++)
+    {
+        typeButtons[i]->setBounds(110,getHeight()-30+i*bh,50,bh);
+    }
     // std::cout << "Canvas thinks LfpDisplay should be this high: "
     //  << lfpDisplay->getTotalHeight() << std::endl;
 
@@ -319,7 +317,10 @@ void LfpDisplayCanvas::beginAnimation()
 
     displayBufferSize = displayBuffer->getNumSamples();
 
-    screenBufferIndex = 0;
+    for (int i = 0; i < screenBufferIndex.size(); i++)
+    {
+        screenBufferIndex.set(i,0);
+    }
 
     startCallbacks();
 }
@@ -334,18 +335,33 @@ void LfpDisplayCanvas::endAnimation()
 void LfpDisplayCanvas::update()
 {
     nChans = jmax(processor->getNumInputs(),1);
-    sampleRate = processor->getSampleRate();
 
-    std::cout << "Setting sample rate of LfpDisplayCanvas to " << sampleRate << std::endl;
+    sampleRate.clear();
+    screenBufferIndex.clear();
+    lastScreenBufferIndex.clear();
+    displayBufferIndex.clear();
 
-    if (nChans != lfpDisplay->getNumChannels())
+    for (int i = 0; i <= nChans; i++) // extra channel for events
     {
-        std::cout << "Setting num inputs on LfpDisplayCanvas to " << nChans << std::endl;
+        if (i < nChans)
+            sampleRate.add(processor->channels[i]->sampleRate);
+        else
+            sampleRate.add(processor->channels[i-1]->sampleRate); // for event channel (IT'S A HACK -- BE CAREFUL!)
+        
+       // std::cout << "Sample rate for ch " << i << " = " << sampleRate[i] << std::endl; 
+        displayBufferIndex.add(0);
+        screenBufferIndex.add(0);
+        lastScreenBufferIndex.add(0);
+    }
 
-        lfpDisplay->setNumChannels(nChans);
+    if (nChans != lfpDisplay->getNumChannels())
+    {
+        //std::cout << "Setting num inputs on LfpDisplayCanvas to " << nChans << std::endl;
 
         refreshScreenBuffer();
 
+        lfpDisplay->setNumChannels(nChans); // add an extra channel for events
+
         // update channel names
         for (int i = 0; i < processor->getNumInputs(); i++)
         {
@@ -363,15 +379,15 @@ void LfpDisplayCanvas::update()
 
         resized();
     }
-	else
-	{
-		for (int i = 0; i < processor->getNumInputs(); i++)
+    else
+    {
+        for (int i = 0; i < processor->getNumInputs(); i++)
         {
-			lfpDisplay->channels[i]->updateType();
-			lfpDisplay->channelInfo[i]->updateType();
-		}
-		
-	}
+            lfpDisplay->channels[i]->updateType();
+            lfpDisplay->channelInfo[i]->updateType();
+        }
+        
+    }
 
 }
 
@@ -380,31 +396,32 @@ void LfpDisplayCanvas::buttonClicked(Button* b)
     if (b == invertInputButton)
     {
         lfpDisplay->setInputInverted(b->getToggleState());
-		return;
+        return;
     }
     if (b == drawMethodButton)
     {
         lfpDisplay->setDrawMethod(b->getToggleState());
-		return;
+        return;
     }
     if (b == pauseButton)
     {
         lfpDisplay->isPaused = b->getToggleState();
-		return;
+        return;
+    }
+
+    int idx = typeButtons.indexOf((UtilityButton*)b);
+    if ((idx >= 0) && (b->getToggleState()))
+    {
+        for (int i = 0; i < processor->getNumInputs(); i++)
+        {
+            if (lfpDisplay->channels[i]->getSelected())
+            {
+                lfpDisplay->channels[i]->deselect();
+                lfpDisplay->channels[i]->repaint();
+            }
+        }  
+        setSelectedType((ChannelType) idx, false);
     }
-	int idx = typeButtons.indexOf((UtilityButton*)b);
-	if ((idx >= 0) && (b->getToggleState()))
-	{
-		for (int i = 0; i < processor->getNumInputs(); i++)
-		{
-			if (lfpDisplay->channels[i]->getSelected())
-			{
-				lfpDisplay->channels[i]->deselect();
-				lfpDisplay->channels[i]->repaint();
-			}
-		}
-		setSelectedType((channelType)idx,false);
-	}
 
 }
 
@@ -414,126 +431,126 @@ void LfpDisplayCanvas::comboBoxChanged(ComboBox* cb)
 
     if (cb == timebaseSelection)
     {
-		if (cb->getSelectedId())
-		{
-			timebase = timebases[cb->getSelectedId()-1].getFloatValue();
-		}
-		else
-		{
-			timebase = cb->getText().getFloatValue();
-			if (timebase)
-			{
-				if (timebase < timebases[0].getFloatValue())
-				{
-					cb->setSelectedId(1,dontSendNotification);
-					timebase = timebases[0].getFloatValue();
-				}
-				else if (timebase > timebases[timebases.size()-1].getFloatValue())
-				{
-					cb->setSelectedId(timebases.size(),dontSendNotification);
-					timebase = timebases[timebases.size()-1].getFloatValue();
-				}
-				else
-					cb->setText(String(timebase,1),dontSendNotification);
-			}
-			else
-			{
-				if (selectedSpread == 0)
-				{
-					cb->setText(selectedTimebaseValue,dontSendNotification);
-					timebase = selectedTimebaseValue.getFloatValue();
-				}
-				else
-				{
-					cb->setSelectedId(selectedTimebase,dontSendNotification);
-					timebase = timebases[selectedTimebase-1].getFloatValue();
-				}
-
-			}
-		}
+        if (cb->getSelectedId())
+        {
+            timebase = timebases[cb->getSelectedId()-1].getFloatValue();
+        }
+        else
+        {
+            timebase = cb->getText().getFloatValue();
+            if (timebase)
+            {
+                if (timebase < timebases[0].getFloatValue())
+                {
+                    cb->setSelectedId(1,dontSendNotification);
+                    timebase = timebases[0].getFloatValue();
+                }
+                else if (timebase > timebases[timebases.size()-1].getFloatValue())
+                {
+                    cb->setSelectedId(timebases.size(),dontSendNotification);
+                    timebase = timebases[timebases.size()-1].getFloatValue();
+                }
+                else
+                    cb->setText(String(timebase,1),dontSendNotification);
+            }
+            else
+            {
+                if (selectedSpread == 0)
+                {
+                    cb->setText(selectedTimebaseValue,dontSendNotification);
+                    timebase = selectedTimebaseValue.getFloatValue();
+                }
+                else
+                {
+                    cb->setSelectedId(selectedTimebase,dontSendNotification);
+                    timebase = timebases[selectedTimebase-1].getFloatValue();
+                }
+
+            }
+        }
     }
     else if (cb == rangeSelection)
     {
-		if (cb->getSelectedId())
-		{
-		lfpDisplay->setRange(voltageRanges[selectedChannelType][cb->getSelectedId()-1].getFloatValue()*rangeGain[selectedChannelType]
-			,selectedChannelType);
-		}
-		else
-		{
-		    float vRange = cb->getText().getFloatValue();
-		    if (vRange)
-		    {
-		        if (vRange < voltageRanges[selectedChannelType][0].getFloatValue())
-		        {
-					cb->setSelectedId(1,dontSendNotification);
-					vRange = voltageRanges[selectedChannelType][0].getFloatValue();
-		        }
-		        else if (vRange > voltageRanges[selectedChannelType][voltageRanges[selectedChannelType].size()-1].getFloatValue())
-		        {
-					cb->setSelectedId(voltageRanges[selectedChannelType].size(),dontSendNotification);
-					vRange = voltageRanges[selectedChannelType][voltageRanges[selectedChannelType].size()-1].getFloatValue();
-		        }
-		        else
-		        {
-		            if (rangeGain[selectedChannelType] > 1)
-		                cb->setText(String(vRange,1),dontSendNotification);
-		            else
-		                cb->setText(String(vRange),dontSendNotification);
-		        }
-				lfpDisplay->setRange(vRange*rangeGain[selectedChannelType],selectedChannelType);
-		    }
-		    else
-			{
-				if (selectedVoltageRange[selectedChannelType])
-					cb->setText(selectedVoltageRangeValues[selectedChannelType],dontSendNotification);
-				else
-					cb->setSelectedId(selectedVoltageRange[selectedChannelType],dontSendNotification);
-			}
-		}
-		selectedVoltageRange[selectedChannelType] = cb->getSelectedId();
-		selectedVoltageRangeValues[selectedChannelType] = cb->getText();
+        if (cb->getSelectedId())
+        {
+        lfpDisplay->setRange(voltageRanges[selectedChannelType][cb->getSelectedId()-1].getFloatValue()*rangeGain[selectedChannelType]
+            ,selectedChannelType);
+        }
+        else
+        {
+            float vRange = cb->getText().getFloatValue();
+            if (vRange)
+            {
+                if (vRange < voltageRanges[selectedChannelType][0].getFloatValue())
+                {
+                    cb->setSelectedId(1,dontSendNotification);
+                    vRange = voltageRanges[selectedChannelType][0].getFloatValue();
+                }
+                else if (vRange > voltageRanges[selectedChannelType][voltageRanges[selectedChannelType].size()-1].getFloatValue())
+                {
+                    cb->setSelectedId(voltageRanges[selectedChannelType].size(),dontSendNotification);
+                    vRange = voltageRanges[selectedChannelType][voltageRanges[selectedChannelType].size()-1].getFloatValue();
+                }
+                else
+                {
+                    if (rangeGain[selectedChannelType] > 1)
+                        cb->setText(String(vRange,1),dontSendNotification);
+                    else
+                        cb->setText(String(vRange),dontSendNotification);
+                }
+                lfpDisplay->setRange(vRange*rangeGain[selectedChannelType],selectedChannelType);
+            }
+            else
+            {
+                if (selectedVoltageRange[selectedChannelType])
+                    cb->setText(selectedVoltageRangeValues[selectedChannelType],dontSendNotification);
+                else
+                    cb->setSelectedId(selectedVoltageRange[selectedChannelType],dontSendNotification);
+            }
+        }
+        selectedVoltageRange[selectedChannelType] = cb->getSelectedId();
+        selectedVoltageRangeValues[selectedChannelType] = cb->getText();
         //std::cout << "Setting range to " << voltageRanges[cb->getSelectedId()-1].getFloatValue() << std::endl;
     }
     else if (cb == spreadSelection)
     {
-		if (cb->getSelectedId())
-		{
-			lfpDisplay->setChannelHeight(spreads[cb->getSelectedId()-1].getIntValue());
-			resized();
-		}
-		else
-		{
-			int spread = cb->getText().getIntValue();
-			if (spread)
-			{
-				if (spread < spreads[0].getFloatValue())
-				{
-					cb->setSelectedId(1,dontSendNotification);
-					spread = spreads[0].getFloatValue();
-				}
-				else if (spread > spreads[spreads.size()-1].getFloatValue())
-				{
-					cb->setSelectedId(spreads.size(),dontSendNotification);
-					spread = spreads[spreads.size()-1].getFloatValue();
-				}
-				else
-				{
-					cb->setText(String(spread),dontSendNotification);
-				}
-				lfpDisplay->setChannelHeight(spread);
-				resized();
-			}
-			else
-			{
-				if (selectedSpread == 0)
-					cb->setText(selectedSpreadValue,dontSendNotification);
-				else
-					cb->setSelectedId(selectedSpread,dontSendNotification);
-			}
-		}
-		selectedSpread = cb->getSelectedId();
-		selectedSpreadValue = cb->getText();
+        if (cb->getSelectedId())
+        {
+            lfpDisplay->setChannelHeight(spreads[cb->getSelectedId()-1].getIntValue());
+            resized();
+        }
+        else
+        {
+            int spread = cb->getText().getIntValue();
+            if (spread)
+            {
+                if (spread < spreads[0].getFloatValue())
+                {
+                    cb->setSelectedId(1,dontSendNotification);
+                    spread = spreads[0].getFloatValue();
+                }
+                else if (spread > spreads[spreads.size()-1].getFloatValue())
+                {
+                    cb->setSelectedId(spreads.size(),dontSendNotification);
+                    spread = spreads[spreads.size()-1].getFloatValue();
+                }
+                else
+                {
+                    cb->setText(String(spread),dontSendNotification);
+                }
+                lfpDisplay->setChannelHeight(spread);
+                resized();
+            }
+            else
+            {
+                if (selectedSpread == 0)
+                    cb->setText(selectedSpreadValue,dontSendNotification);
+                else
+                    cb->setSelectedId(selectedSpread,dontSendNotification);
+            }
+        }
+        selectedSpread = cb->getSelectedId();
+        selectedSpreadValue = cb->getText();
         //std::cout << "Setting spread to " << spreads[cb->getSelectedId()-1].getFloatValue() << std::endl;
     }
     else if (cb == colorGroupingSelection)
@@ -571,19 +588,19 @@ void LfpDisplayCanvas::setParameter(int param, float val)
 
 void LfpDisplayCanvas:: setRangeSelection(float range, bool canvasMustUpdate)
 {
-	if (canvasMustUpdate)
-	{
-		rangeSelection->setText(String(range/rangeGain[selectedChannelType]), sendNotification); 
-	}
-	else
-	{
-		rangeSelection->setText(String(range/rangeGain[selectedChannelType]),dontSendNotification);
-		selectedVoltageRange[selectedChannelType]=rangeSelection->getSelectedId();
-		selectedVoltageRangeValues[selectedChannelType]=rangeSelection->getText();
+    if (canvasMustUpdate)
+    {
+        rangeSelection->setText(String(range/rangeGain[selectedChannelType]), sendNotification); 
+    }
+    else
+    {
+        rangeSelection->setText(String(range/rangeGain[selectedChannelType]),dontSendNotification);
+        selectedVoltageRange[selectedChannelType]=rangeSelection->getSelectedId();
+        selectedVoltageRangeValues[selectedChannelType]=rangeSelection->getText();
 
-		repaint();
-		refresh();
-	}
+        repaint();
+        refresh();
+    }
 
 }
 
@@ -607,16 +624,21 @@ void LfpDisplayCanvas:: setSpreadSelection(int spread, bool canvasMustUpdate)
 void LfpDisplayCanvas::refreshState()
 {
     // called when the component's tab becomes visible again
-    displayBufferIndex = processor->getDisplayBufferIndex();
-    screenBufferIndex = 0;
+
+    for (int i = 0; i <= displayBufferIndex.size(); i++) // include event channel
+    {
+
+        displayBufferIndex.set(i, processor->getDisplayBufferIndex(i));
+        screenBufferIndex.set(i,0);
+    }
 
 }
 
 void LfpDisplayCanvas::refreshScreenBuffer()
 {
 
-    screenBufferIndex = 0;
-    displayBufferIndex = 0;
+    for (int i = 0; i <= screenBufferIndex.size(); i++)
+        screenBufferIndex.set(i,0);
 
     screenBuffer->clear();
     screenBufferMin->clear();
@@ -643,130 +665,142 @@ void LfpDisplayCanvas::refreshScreenBuffer()
 void LfpDisplayCanvas::updateScreenBuffer()
 {
 
-    // copy new samples from the displayBuffer into the screenBuffer (waves)
+    // copy new samples from the displayBuffer into the screenBuffer
     int maxSamples = lfpDisplay->getWidth() - leftmargin;
 
-    if (screenBufferIndex >= maxSamples) // wrap around if we reached right edge before
-        screenBufferIndex = 0;
-
-    lastScreenBufferIndex = screenBufferIndex;
-
-    int index = processor->getDisplayBufferIndex();
-
-    int nSamples =  index - displayBufferIndex; // N new samples (not pixels) to be added to displayBufferIndex
-
-    if (nSamples < 0) // buffer has reset to 0
+    for (int channel = 0; channel <= nChans; channel++) // pull one extra channel for event display
     {
-        nSamples = (displayBufferSize - displayBufferIndex) + index;
-    }
 
-    float ratio = sampleRate * timebase / float(getWidth() - leftmargin - scrollBarThickness); // samples / pixel
-    // this number is crucial: converting from samples to values (in px) for the screen buffer
-    int valuesNeeded = (int) float(nSamples) / ratio; // N pixels needed for this update
+        if (screenBufferIndex[channel] >= maxSamples) // wrap around if we reached right edge before
+            screenBufferIndex.set(channel, 0);
 
-    if (screenBufferIndex + valuesNeeded > maxSamples)  // crop number of samples to fit cavas width
-    {
-        valuesNeeded = maxSamples - screenBufferIndex;
-    }
+         // hold these values locally for each channel
+        int sbi = screenBufferIndex[channel];
+        int dbi = displayBufferIndex[channel];
 
-    float subSampleOffset = 0.0;
-    
-    //std::cout << screenBufferIndex << " : " << index << " : " << displayBufferIndex << " : " << valuesNeeded << " : " << ratio << std::endl;
+        lastScreenBufferIndex.set(channel,sbi);
 
-    displayBufferIndex = displayBufferIndex % displayBufferSize; // make sure we're not overshooting
-    int nextPos = (displayBufferIndex +1) % displayBufferSize; //  position next to displayBufferIndex in display buffer to copy from
+        int index = processor->getDisplayBufferIndex(channel);
 
-    if (valuesNeeded > 0 && valuesNeeded < 1000)
-    {
-        for (int i = 0; i < valuesNeeded; i++) // also fill one extra sample for line drawing interpolation to match across draws
+        int nSamples =  index - dbi; // N new samples (not pixels) to be added to displayBufferIndex
+
+        if (nSamples < 0) // buffer has reset to 0
         {
-            //If paused don't update screen buffers, but update all indexes as needed
-            if (!lfpDisplay->isPaused)
-            {
-                float gain = 1.0;
-                float alpha = (float) subSampleOffset;
-                float invAlpha = 1.0f - alpha;
+            nSamples = (displayBufferSize - dbi) + index;
+        }
 
-                screenBuffer->clear(screenBufferIndex, 1);
-                screenBufferMin->clear(screenBufferIndex, 1);
-                screenBufferMean->clear(screenBufferIndex, 1);
-                screenBufferMax->clear(screenBufferIndex, 1);
+        //if (channel == 15 || channel == 16)
+        //     std::cout << channel << " " << sbi << " " << dbi << " " << nSamples << std::endl;
 
 
-                displayBufferIndex = displayBufferIndex % displayBufferSize; // just to be sure
+        float ratio = sampleRate[channel] * timebase / float(getWidth() - leftmargin - scrollBarThickness); // samples / pixel
+        // this number is crucial: converting from samples to values (in px) for the screen buffer
+        int valuesNeeded = (int) float(nSamples) / ratio; // N pixels needed for this update
 
-                for (int channel = 0; channel <= nChans; channel++) // pull one extra channel for event display
+        if (sbi + valuesNeeded > maxSamples)  // crop number of samples to fit canvas width
+        {
+            valuesNeeded = maxSamples - sbi;
+        }
+        float subSampleOffset = 0.0;
+
+        dbi %= displayBufferSize; // make sure we're not overshooting
+        int nextPos = (dbi + 1) % displayBufferSize; //  position next to displayBufferIndex in display buffer to copy from
+
+        // if (channel == 0)
+        //     std::cout << "Channel " 
+        //               << channel << " : " 
+        //               << sbi << " : " 
+        //               << index << " : " 
+        //               << dbi << " : " 
+        //               << valuesNeeded << " : " 
+        //               << ratio 
+        //                             << std::endl;
+
+        if (valuesNeeded > 0 && valuesNeeded < 10000)
+        {
+            for (int i = 0; i < valuesNeeded; i++) // also fill one extra sample for line drawing interpolation to match across draws
+            {
+                //If paused don't update screen buffers, but update all indexes as needed
+                if (!lfpDisplay->isPaused)
                 {
-
-                    if (channel < displayBuffer->getNumChannels())
+                    float gain = 1.0;
+                    float alpha = (float) subSampleOffset;
+                    float invAlpha = 1.0f - alpha;
+
+                    screenBuffer->clear(channel, sbi, 1);
+                    screenBufferMin->clear(channel, sbi, 1);
+                    screenBufferMean->clear(channel, sbi, 1);
+                    screenBufferMax->clear(channel, sbi, 1);
+
+                     dbi %= displayBufferSize; // just to be sure
+
+                    // interpolate between two samples with invAlpha and alpha
+                    screenBuffer->addFrom(channel, // destChannel
+                                          sbi, // destStartSample
+                                          displayBuffer->getReadPointer(channel, dbi), // source
+                                          1, // numSamples
+                                          invAlpha*gain); // gain
+
+
+                    screenBuffer->addFrom(channel, // destChannel
+                                          sbi, // destStartSample
+                                          displayBuffer->getReadPointer(channel, nextPos), // source
+                                          1, // numSamples
+                                          alpha*gain); // gain
+
+                    // same thing again, but this time add the min,mean, and max of all samples in current pixel
+                    float sample_min   =  1000000;
+                    float sample_max   = -1000000;
+                    float sample_mean  =  0;
+                    int c = 0;
+                    int nextpix = (dbi +(int)ratio) % displayBufferSize; //  position to next pixels index
+                    
+                    for (int j = dbi; j < nextpix; j++)
                     {
-                        // interpolate between two samples with invAlpha and alpha
-                        screenBuffer->addFrom(channel, // destChannel
-                                              screenBufferIndex, // destStartSample
-                                              displayBuffer->getReadPointer(channel, displayBufferIndex), // source
-                                              1, // numSamples
-                                              invAlpha*gain); // gain
-
-
-                        screenBuffer->addFrom(channel, // destChannel
-                                              screenBufferIndex, // destStartSample
-                                              displayBuffer->getReadPointer(channel, nextPos), // source
-                                              1, // numSamples
-                                              alpha*gain); // gain
-
-                        // same thing again, but this time add the min,mean, and max of all samples in current pixel
-                        float sample_min   =  1000000;
-                        float sample_max   = -1000000;
-                        float sample_mean  =  0;
-                        int c=0;
-                        int nextpix = (displayBufferIndex +(int)ratio) % displayBufferSize; //  position to next pixels index
-                        for (int j = displayBufferIndex; j < nextpix; j++)
-                        {
-                            float sample_current = displayBuffer->getSample(channel, j);
-                            sample_mean = sample_mean + sample_current;
-
-                            if (sample_min>sample_current)
-                            {
-                                sample_min=sample_current;
-                            }
-
-                            if (sample_max<sample_current)
-                            {
-                                sample_max=sample_current;
-                            }
-                            c++;
+                        float sample_current = displayBuffer->getSample(channel, j);
+                        sample_mean = sample_mean + sample_current;
 
+                        if (sample_min>sample_current)
+                        {
+                            sample_min=sample_current;
+                        }
 
+                        if (sample_max<sample_current)
+                        {
+                            sample_max=sample_current;
                         }
-                        sample_mean=sample_mean/c;
-                        screenBufferMean->addSample(channel, screenBufferIndex, sample_mean*gain);
-                        screenBufferMin->addSample(channel, screenBufferIndex, sample_min*gain);
-                        screenBufferMax->addSample(channel, screenBufferIndex, sample_max*gain);
+                        c++;
+
                     }
 
+                    sample_mean = sample_mean/c;
+                    screenBufferMean->addSample(channel, sbi, sample_mean*gain);
+                    screenBufferMin->addSample(channel, sbi, sample_min*gain);
+                    screenBufferMax->addSample(channel, sbi, sample_max*gain);
+                
+                sbi++;
                 }
-                screenBufferIndex++;
-            }
-
+            
             subSampleOffset += ratio;
 
             while (subSampleOffset >= 1.0)
             {
-                if (++displayBufferIndex > displayBufferSize)
-                    displayBufferIndex = 0;
+                if (++dbi > displayBufferSize)
+                    dbi = 0;
 
-                nextPos = (displayBufferIndex + 1) % displayBufferSize;
+                nextPos = (dbi + 1) % displayBufferSize;
                 subSampleOffset -= 1.0;
             }
 
         }
 
+        // update values after we're done
+        screenBufferIndex.set(channel, sbi);
+        displayBufferIndex.set(channel, dbi);
+        }
 
     }
-    else
-    {
-        //std::cout << "Skip." << std::endl;
-    }
+
 }
 
 const float LfpDisplayCanvas::getXCoord(int chan, int samp)
@@ -843,12 +877,12 @@ void LfpDisplayCanvas::paint(Graphics& g)
 
     g.setColour(Colour(100,100,100));
 
-	g.drawText("Voltage range ("+ rangeUnits[selectedChannelType] +")",5,getHeight()-55,300,20,Justification::left, false);
+    g.drawText("Voltage range ("+ rangeUnits[selectedChannelType] +")",5,getHeight()-55,300,20,Justification::left, false);
     g.drawText("Timebase (s)",175,getHeight()-55,300,20,Justification::left, false);
     g.drawText("Spread (px)",345,getHeight()-55,300,20,Justification::left, false);
     g.drawText("Color grouping",620,getHeight()-55,300,20,Justification::left, false);
 
-//	g.drawText(typeNames[selectedChannelType],110,getHeight()-30,50,20,Justification::centredLeft,false);
+    //g.drawText(typeNames[selectedChannelType],110,getHeight()-30,50,20,Justification::centredLeft,false);
 
     g.drawText("Event disp.",500,getHeight()-55,300,20,Justification::left, false);
 
@@ -893,8 +927,8 @@ void LfpDisplayCanvas::saveVisualizerParameters(XmlElement* xml)
     XmlElement* xmlNode = xml->createNewChildElement("LFPDISPLAY");
 
 
-	xmlNode->setAttribute("Range",selectedVoltageRangeValues[0]+","+selectedVoltageRangeValues[1]+
-		","+selectedVoltageRangeValues[2]);
+    xmlNode->setAttribute("Range",selectedVoltageRangeValues[0]+","+selectedVoltageRangeValues[1]+
+        ","+selectedVoltageRangeValues[2]);
     xmlNode->setAttribute("Timebase",timebaseSelection->getText());
     xmlNode->setAttribute("Spread",spreadSelection->getText());
     xmlNode->setAttribute("colorGrouping",colorGroupingSelection->getSelectedId());
@@ -940,15 +974,15 @@ void LfpDisplayCanvas::loadVisualizerParameters(XmlElement* xml)
     {
         if (xmlNode->hasTagName("LFPDISPLAY"))
         {
-			StringArray ranges;
-			ranges.addTokens(xmlNode->getStringAttribute("Range"),",",String::empty);
-			selectedVoltageRangeValues[0] = ranges[0];
-			selectedVoltageRangeValues[1] = ranges[1];
-			selectedVoltageRangeValues[2] = ranges[2];
-			selectedVoltageRange[0] = voltageRanges[0].indexOf(ranges[0])+1;
-			selectedVoltageRange[1] = voltageRanges[1].indexOf(ranges[1])+1;
-			selectedVoltageRange[2] = voltageRanges[2].indexOf(ranges[2])+1;
-			rangeSelection->setText(ranges[0]);
+            StringArray ranges;
+            ranges.addTokens(xmlNode->getStringAttribute("Range"),",",String::empty);
+            selectedVoltageRangeValues[0] = ranges[0];
+            selectedVoltageRangeValues[1] = ranges[1];
+            selectedVoltageRangeValues[2] = ranges[2];
+            selectedVoltageRange[0] = voltageRanges[0].indexOf(ranges[0])+1;
+            selectedVoltageRange[1] = voltageRanges[1].indexOf(ranges[1])+1;
+            selectedVoltageRange[2] = voltageRanges[2].indexOf(ranges[2])+1;
+            rangeSelection->setText(ranges[0]);
 
             timebaseSelection->setText(xmlNode->getStringAttribute("Timebase"));
             spreadSelection->setText(xmlNode->getStringAttribute("Spread"));
@@ -1002,43 +1036,42 @@ void LfpDisplayCanvas::loadVisualizerParameters(XmlElement* xml)
 
 }
 
-channelType LfpDisplayCanvas::getChannelType(int n)
+ChannelType LfpDisplayCanvas::getChannelType(int n)
 {
-	if (n < processor->channels.size())
-		return processor->channels[n]->getType();
-	else
-		return DATA_CHANNEL;
+    return processor->channels[n]->getType();
 }
 
-channelType LfpDisplayCanvas::getSelectedType()
+ChannelType LfpDisplayCanvas::getSelectedType()
 {
-	return selectedChannelType;
+    return selectedChannelType;
 }
 
-void LfpDisplayCanvas::setSelectedType(channelType type, bool toggleButton)
+void LfpDisplayCanvas::setSelectedType(ChannelType type, bool toggleButton)
 {
-	if (selectedChannelType == type)
-		return; //Nothing to do here
-	selectedChannelType = type;
-	rangeSelection->clear(dontSendNotification);
-	rangeSelection->addItemList(voltageRanges[type],1);
-	int id = selectedVoltageRange[type];
-	if (id)
-		rangeSelection->setSelectedId(id,sendNotification);
-	else
-		rangeSelection->setText(selectedVoltageRangeValues[selectedChannelType],dontSendNotification);
-	if (toggleButton)
-		typeButtons[type]->setToggleState(true,dontSendNotification);
+    if (selectedChannelType == type)
+        return; //Nothing to do here
+    selectedChannelType = type;
+    rangeSelection->clear(dontSendNotification);
+    rangeSelection->addItemList(voltageRanges[type],1);
+    int id = selectedVoltageRange[type];
+    if (id)
+        rangeSelection->setSelectedId(id,sendNotification);
+    else
+        rangeSelection->setText(selectedVoltageRangeValues[selectedChannelType],dontSendNotification);
+    repaint(5,getHeight()-55,300,100);
+
+    if (toggleButton)
+        typeButtons[type]->setToggleState(true,dontSendNotification);
 }
 
-String LfpDisplayCanvas::getTypeName(channelType type)
+String LfpDisplayCanvas::getTypeName(ChannelType type)
 {
-	return typeNames[type];
+    return typeNames[type];
 }
 
-int LfpDisplayCanvas::getRangeStep(channelType type)
+int LfpDisplayCanvas::getRangeStep(ChannelType type)
 {
-	return rangeSteps[type];
+    return rangeSteps[type];
 }
 
 // -------------------------------------------------------------
@@ -1103,9 +1136,9 @@ LfpDisplay::LfpDisplay(LfpDisplayCanvas* c, Viewport* v) :
     totalHeight = 0;
     colorGrouping=1;
 
-	range[0] = 1000;
-	range[1] = 500;
-	range[2] = 500000;
+    range[0] = 1000;
+    range[1] = 500;
+    range[2] = 500000;
 
     addMouseListener(this, true);
 
@@ -1183,7 +1216,7 @@ void LfpDisplay::setNumChannels(int numChannels)
         LfpChannelDisplay* lfpChan = new LfpChannelDisplay(canvas, this, i);
 
         //lfpChan->setColour(channelColours[i % channelColours.size()]);
-		lfpChan->setRange(range[canvas->getChannelType(i)]);
+        lfpChan->setRange(range[canvas->getChannelType(i)]);
         lfpChan->setChannelHeight(canvas->getChannelHeight());
 
         addAndMakeVisible(lfpChan);
@@ -1200,8 +1233,6 @@ void LfpDisplay::setNumChannels(int numChannels)
 
         channelInfo.add(lfpInfo);
 
-		savedChannelState.add(true);
-
         totalHeight += lfpChan->getChannelHeight();
 
     }
@@ -1299,7 +1330,7 @@ void LfpDisplay::refresh()
             }
             else
             {
-                channels[i]->repaint(canvas->lastScreenBufferIndex-2, 0, (canvas->screenBufferIndex-canvas->lastScreenBufferIndex)+3, getChildComponent(i)->getHeight());  //repaint only the updated portion
+                channels[i]->repaint(canvas->lastScreenBufferIndex[i]-2, 0, (canvas->screenBufferIndex[i]-canvas->lastScreenBufferIndex[i])+3, getChildComponent(i)->getHeight());  //repaint only the updated portion
                 // we redraw from -2 to +1 relative to the real redraw window, the -2 makes sure that the lines join nicely, and the +1 draws the vertical update line
             }
             //std::cout << i << std::endl;
@@ -1310,30 +1341,30 @@ void LfpDisplay::refresh()
     canvas->fullredraw = false;
 }
 
-void LfpDisplay::setRange(float r, channelType type)
+void LfpDisplay::setRange(float r, ChannelType type)
 {
     range[type] = r;
 
     for (int i = 0; i < numChans; i++)
     {
-		if (channels[i]->getType() == type)
-			channels[i]->setRange(range[type]);
+        if (channels[i]->getType() == type)
+            channels[i]->setRange(range[type]);
     }
     canvas->fullredraw = true; //issue full redraw
 }
 
 int LfpDisplay::getRange()
 {
-	return getRange(canvas->getSelectedType());
+    return getRange(canvas->getSelectedType());
 }
 
-int LfpDisplay::getRange(channelType type)
+int LfpDisplay::getRange(ChannelType type)
 {
-	for (int i=0; i < numChans; i++)
-	{
-		if (channels[i]->getType() == type)
-			return channels[i]->getRange();
-	}
+    for (int i=0; i < numChans; i++)
+    {
+        if (channels[i]->getType() == type)
+            return channels[i]->getRange();
+    }
 }
 
 
@@ -1353,7 +1384,7 @@ void LfpDisplay::setChannelHeight(int r, bool resetSingle)
         singleChan = -1;
         for (int n = 0; n < numChans; n++)
         {
-			channelInfo[n]->setEnabledState(savedChannelState[n]);
+            channelInfo[n]->setEnabledState(true);
         }
     }
 
@@ -1395,8 +1426,8 @@ void LfpDisplay::mouseWheelMove(const MouseEvent&  e, const MouseWheelDetails&
 {
 
     //std::cout << "Mouse wheel " <<  e.mods.isCommandDown() << "  " << wheel.deltaY << std::endl;
-	//TODO Changing ranges with the wheel is currently broken. With multiple ranges, most
-	//of the wheel range code needs updating
+    //TODO Changing ranges with the wheel is currently broken. With multiple ranges, most
+    //of the wheel range code needs updating
     if (e.mods.isCommandDown())  // CTRL + scroll wheel -> change channel spacing
     {
         int h = getChannelHeight();
@@ -1435,18 +1466,18 @@ void LfpDisplay::mouseWheelMove(const MouseEvent&  e, const MouseWheelDetails&
         if (e.mods.isShiftDown())  // SHIFT + scroll wheel -> change channel range
         {
             int h = getRange();
-			int step = canvas->getRangeStep(canvas->getSelectedType());
+            int step = canvas->getRangeStep(canvas->getSelectedType());
             
             std::cout << wheel.deltaY << std::endl;
             
             if (wheel.deltaY > 0)
             {
-				setRange(h+step,canvas->getSelectedType());
+                setRange(h+step,canvas->getSelectedType());
             }
             else
             {
                 if (h > step+1)
-					setRange(h-step,canvas->getSelectedType());
+                    setRange(h-step,canvas->getSelectedType());
             }
 
             canvas->setRangeSelection(h); // update combobox
@@ -1474,14 +1505,12 @@ void LfpDisplay::toggleSingleChannel(int chan)
     {
         singleChan = chan;
         int newHeight = viewport->getHeight();
-		channelInfo[chan]->setEnabledState(true);
         setChannelHeight(newHeight, false);
         setSize(getWidth(), numChans*getChannelHeight());
         viewport->setScrollBarsShown(false,false);
         viewport->setViewPosition(Point<int>(0,chan*newHeight));
         for (int n = 0; n < numChans; n++)
         {
-			savedChannelState.set(n,channels[n]->getEnabledState());
             if (n != chan) channelInfo[n]->setEnabledState(false);
         }
 
@@ -1528,7 +1557,7 @@ void LfpDisplay::mouseDown(const MouseEvent& event)
     //lcd->select();
 
     channels[closest]->select();
-	canvas->setSelectedType(channels[closest]->getType());
+    canvas->setSelectedType(channels[closest]->getType());
 
     if (event.getNumberOfClicks() == 2)
         toggleSingleChannel(closest);
@@ -1601,8 +1630,8 @@ LfpChannelDisplay::LfpChannelDisplay(LfpDisplayCanvas* c, LfpDisplay* d, int cha
 
     lineColour = Colour(255,255,255);
 
-	type = c->getChannelType(channelNumber);
-	typeStr = c->getTypeName(type);
+    type = c->getChannelType(channelNumber);
+    typeStr = c->getTypeName(type);
 
 }
 
@@ -1613,8 +1642,8 @@ LfpChannelDisplay::~LfpChannelDisplay()
 
 void LfpChannelDisplay::updateType()
 {
-	type = canvas->getChannelType(chan);
-	typeStr = canvas->getTypeName(type);
+    type = canvas->getChannelType(chan);
+    typeStr = canvas->getTypeName(type);
 }
 
 void LfpChannelDisplay::setEnabledState(bool state)
@@ -1635,7 +1664,7 @@ void LfpChannelDisplay::paint(Graphics& g)
     //g.fillAll(Colours::grey);
 
     g.setColour(Colours::yellow);   // draw most recent drawn sample position
-    g.drawLine(canvas->screenBufferIndex+1, 0, canvas->screenBufferIndex+1, getHeight());
+    g.drawLine(canvas->screenBufferIndex[chan]+1, 0, canvas->screenBufferIndex[chan]+1, getHeight());
 
 
     //g.setColour(Colours::red); // draw oldest drawn sample position
@@ -1675,7 +1704,7 @@ void LfpChannelDisplay::paint(Graphics& g)
 
             int leftEdge = 150;
 
-			float r = range;
+            float r = range;
 
             g.setColour(Colours::lightgrey);
             g.setFont(channelFont);
@@ -1683,10 +1712,10 @@ void LfpChannelDisplay::paint(Graphics& g)
             String unitString;
             if (getType() == ADC_CHANNEL)
             {
-            	unitString = " V";
-				//r = range / 1000.0f;
+                unitString = " V";
+                //r = range / 1000.0f;
             } else {
-            	unitString = " uV";
+                unitString = " uV";
             }
             g.drawText(String(0) + unitString, 20, center, leftEdge, 25, Justification::left, false);
             g.drawText(String(r/2) + unitString, 20, center-channelHeight/2, leftEdge, 25, Justification::left, false);
@@ -1705,12 +1734,12 @@ void LfpChannelDisplay::paint(Graphics& g)
         int to = 0;
 
         //for (int i = 0; i < getWidth()-stepSize; i += stepSize) // redraw entire display
-        int ifrom = canvas->lastScreenBufferIndex - 3; // need to start drawing a bit before the actual redraw windowfor the interpolated line to join correctly
+        int ifrom = canvas->lastScreenBufferIndex[chan] - 3; // need to start drawing a bit before the actual redraw windowfor the interpolated line to join correctly
 
         if (ifrom < 0)
             ifrom = 0;
 
-        int ito = canvas->screenBufferIndex - 1;
+        int ito = canvas->screenBufferIndex[chan] - 1;
 
         if (fullredraw)
         {
@@ -1724,12 +1753,17 @@ void LfpChannelDisplay::paint(Graphics& g)
 
             // draw event markers
             int rawEventState = canvas->getYCoord(canvas->getNumChannels(), i);// get last channel+1 in buffer (represents events)
+            
+            //if (i == ifrom)
+            //    std::cout << rawEventState << std::endl;
+
             for (int ev_ch = 0; ev_ch < 8 ; ev_ch++) // for all event channels
             {
                 if (display->getEventDisplayState(ev_ch))  // check if plotting for this channel is enabled
                 {
                     if (rawEventState & (1 << ev_ch))    // events are  representet by a bit code, so we have to extract the individual bits with a mask
                     {
+                        //std::cout << "Drawing event." << std::endl;
                         g.setColour(display->channelColours[ev_ch*2]); // get color from lfp color scheme
                         g.setOpacity(0.35f);
                         g.drawLine(i, center-channelHeight/2 , i, center+channelHeight/2);
@@ -1817,7 +1851,7 @@ void LfpChannelDisplay::paint(Graphics& g)
 
 void LfpChannelDisplay::setRange(float r)
 {
-	
+    
     range = r;
 
     //std::cout << "Range: " << r << std::endl;
@@ -1841,7 +1875,7 @@ void LfpChannelDisplay::deselect()
 
 bool LfpChannelDisplay::getSelected()
 {
-	return isSelected;
+   return isSelected;
 }
 
 void LfpChannelDisplay::setColour(Colour c)
@@ -1906,9 +1940,9 @@ void LfpChannelDisplay::setName(String name_)
     name = name_;
 }
 
-channelType LfpChannelDisplay::getType()
+ChannelType LfpChannelDisplay::getType()
 {
-	return type;
+    return type;
 }
 
 // -------------------------------
@@ -1934,9 +1968,9 @@ LfpChannelDisplayInfo::LfpChannelDisplayInfo(LfpDisplayCanvas* canvas_, LfpDispl
 
 void LfpChannelDisplayInfo::updateType()
 {
-	type = canvas->getChannelType(chan);
-	typeStr = canvas->getTypeName(type);
-	repaint();
+    type = canvas->getChannelType(chan);
+    typeStr = canvas->getTypeName(type);
+    repaint();
 }
 
 void LfpChannelDisplayInfo::buttonClicked(Button* button)
@@ -1972,12 +2006,12 @@ void LfpChannelDisplayInfo::paint(Graphics& g)
     g.setColour(lineColour);
 
     //if (chan > 98)
-    //	g.fillRoundedRectangle(5,center-8,51,22,8.0f);
+    //  g.fillRoundedRectangle(5,center-8,51,22,8.0f);
     //else
     g.fillRoundedRectangle(5,center-8,41,22,8.0f);
 
       g.setFont(Font("Small Text", 13, Font::plain));
-	  g.drawText(typeStr,5,center+16,41,10,Justification::centred,false);
+      g.drawText(typeStr,5,center+16,41,10,Justification::centred,false);
     // g.setFont(channelHeightFloat*0.3);
 
     //  g.drawText(name, 10, center-channelHeight/2, 200, channelHeight, Justification::left, false);
@@ -1990,7 +2024,7 @@ void LfpChannelDisplayInfo::resized()
     int center = getHeight()/2;
 
     //if (chan > 98)
-    //	enableButton->setBounds(8,center-5,45,16);
+    //  enableButton->setBounds(8,center-5,45,16);
     //else
     enableButton->setBounds(8,center-5,35,16);
 }
@@ -2066,13 +2100,13 @@ void EventDisplayInterface::paint(Graphics& g)
 // Lfp Viewport -------------------------------------------
 
 LfpViewport::LfpViewport(LfpDisplayCanvas *canvas)
-	: Viewport()
+    : Viewport()
 {
-	this->canvas = canvas;
+    this->canvas = canvas;
 }
 
 void LfpViewport::visibleAreaChanged(const Rectangle<int>& newVisibleArea)
 {
-	canvas->fullredraw = true;
-	canvas->refresh();
+    canvas->fullredraw = true;
+    canvas->refresh();
 }
diff --git a/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.h b/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.h
index 4c326e42a1aa24b0d446cdc9794ffcadbd6bcf28..d814232a6e3e6fc2695e7605c01e6a2b40ad12fe 100755
--- a/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.h
+++ b/Source/Processors/LfpDisplayNode/LfpDisplayCanvas.h
@@ -64,8 +64,8 @@ public:
     void setParameter(int, float);
     void setParameter(int, int, int, float) {}
 
-	void setRangeSelection(float range, bool canvasMustUpdate = false); // set range selection combo box to correct value if it has been changed by scolling etc.
-	void setSpreadSelection(int spread, bool canvasMustUpdate = false); // set spread selection combo box to correct value if it has been changed by scolling etc.
+    void setRangeSelection(float range, bool canvasMustUpdate = false); // set range selection combo box to correct value if it has been changed by scolling etc.
+    void setSpreadSelection(int spread, bool canvasMustUpdate = false); // set spread selection combo box to correct value if it has been changed by scolling etc.
 
     void paint(Graphics& g);
 
@@ -86,8 +86,8 @@ public:
     const float getYCoordMean(int chan, int samp);
     const float getYCoordMax(int chan, int samp);
 
-    int screenBufferIndex;
-    int lastScreenBufferIndex;
+    Array<int> screenBufferIndex;
+    Array<int> lastScreenBufferIndex;
 
     void comboBoxChanged(ComboBox* cb);
     void buttonClicked(Button* button);
@@ -98,12 +98,12 @@ public:
     bool keyPressed(const KeyPress& key);
     bool keyPressed(const KeyPress& key, Component* orig);
 
-	channelType getChannelType(int n);
-	channelType getSelectedType();
-	String getTypeName(channelType type);
-	int getRangeStep(channelType type);
+    ChannelType getChannelType(int n);
+    ChannelType getSelectedType();
+    String getTypeName(ChannelType type);
+    int getRangeStep(ChannelType type);
 
-	void setSelectedType(channelType type, bool toggleButton = true);
+    void setSelectedType(ChannelType type, bool toggleButton = true);
 
     //void scrollBarMoved(ScrollBar *scrollBarThatHasMoved, double newRangeStart);
 
@@ -112,18 +112,18 @@ public:
 
     Array<bool> isChannelEnabled;
 
-	int nChans;
+    int nChans;
 
 private:
 
-    float sampleRate;
+    Array<float> sampleRate;
     float timebase;
     float displayGain;
     float timeOffset;
     //int spread ; // vertical spacing between channels
 
 
-    static const int MAX_N_CHAN = 1028;  // maximum number of channels
+    static const int MAX_N_CHAN = 2048;  // maximum number of channels
     static const int MAX_N_SAMP = 5000; // maximum display size in pixels
     //float waves[MAX_N_CHAN][MAX_N_SAMP*2]; // we need an x and y point for each sample
 
@@ -150,36 +150,36 @@ private:
     ScopedPointer<UtilityButton> invertInputButton;
     ScopedPointer<UtilityButton> drawMethodButton;
     ScopedPointer<UtilityButton> pauseButton;
-	OwnedArray<UtilityButton> typeButtons;
+    OwnedArray<UtilityButton> typeButtons;
 
     StringArray voltageRanges[CHANNEL_TYPES];
     StringArray timebases;
     StringArray spreads; // option for vertical spacing between channels
     StringArray colorGroupings; // option for coloring every N channels the same
 
-	channelType selectedChannelType;
-	int selectedVoltageRange[CHANNEL_TYPES];
-	String selectedVoltageRangeValues[CHANNEL_TYPES];
-	float rangeGain[CHANNEL_TYPES];
-	StringArray rangeUnits;
-	StringArray typeNames;
-	int rangeSteps[CHANNEL_TYPES];
+    ChannelType selectedChannelType;
+    int selectedVoltageRange[CHANNEL_TYPES];
+    String selectedVoltageRangeValues[CHANNEL_TYPES];
+    float rangeGain[CHANNEL_TYPES];
+    StringArray rangeUnits;
+    StringArray typeNames;
+    int rangeSteps[CHANNEL_TYPES];
 
-	int selectedSpread;
-	String selectedSpreadValue;
+    int selectedSpread;
+    String selectedSpreadValue;
 
-	int selectedTimebase;
-	String selectedTimebaseValue;
+    int selectedTimebase;
+    String selectedTimebaseValue;
 
     OwnedArray<EventDisplayInterface> eventDisplayInterfaces;
 
     void refreshScreenBuffer();
     void updateScreenBuffer();
 
-    int displayBufferIndex;
+    Array<int> displayBufferIndex;
     int displayBufferSize;
 
-	int scrollBarThickness;
+    int scrollBarThickness;
 
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LfpDisplayCanvas);
 
@@ -228,11 +228,11 @@ public:
     void mouseWheelMove(const MouseEvent&  event, const MouseWheelDetails&   wheel) ;
 
 
-    void setRange(float range, channelType type);
-	
-	//Withouth parameters returns selected type
+    void setRange(float range, ChannelType type);
+    
+    //Withouth parameters returns selected type
     int getRange();
-	int getRange(channelType type);
+    int getRange(ChannelType type);
 
     void setChannelHeight(int r, bool resetSingle = true);
     int getChannelHeight();
@@ -251,7 +251,7 @@ public:
     bool getEnabledState(int);
     void enableChannel(bool, int);
 
-	bool getSingleChannelState();
+    bool getSingleChannelState();
 
     Array<Colour> channelColours;
 
@@ -262,9 +262,8 @@ public:
     bool isPaused; // simple pause function, skips screen bufer updates
 
 private:
-	void toggleSingleChannel(int chan);
-	int singleChan;
-	Array<bool> savedChannelState;
+    void toggleSingleChannel(int chan);
+    int singleChan;
 
     int numChans;
 
@@ -290,7 +289,8 @@ public:
 
     void select();
     void deselect();
-	bool getSelected();
+
+    bool getSelected();
 
     void setName(String);
 
@@ -316,8 +316,8 @@ public:
         return isEnabled;
     }
 
-	channelType getType();
-	void updateType();
+    ChannelType getType();
+    void updateType();
 
     bool fullredraw; // used to indicate that a full redraw is required. is set false after each full redraw
 
@@ -347,8 +347,8 @@ protected:
     bool canBeInverted;
     bool drawMethod;
 
-	channelType type;
-	String typeStr;
+    ChannelType type;
+    String typeStr;
 
 };
 
@@ -365,7 +365,7 @@ public:
     void resized();
 
     void setEnabledState(bool);
-	void updateType();
+    void updateType();
 
 private:
 
@@ -402,11 +402,11 @@ private:
 class LfpViewport : public Viewport
 {
 public:
-	LfpViewport(LfpDisplayCanvas* canvas);
-	void visibleAreaChanged(const Rectangle<int>& newVisibleArea);
+    LfpViewport(LfpDisplayCanvas* canvas);
+    void visibleAreaChanged(const Rectangle<int>& newVisibleArea);
 
 private:
-	LfpDisplayCanvas* canvas;
+    LfpDisplayCanvas* canvas;
 };
 
 
diff --git a/Source/Processors/LfpDisplayNode/LfpDisplayNode.cpp b/Source/Processors/LfpDisplayNode/LfpDisplayNode.cpp
index bc6b8dd153d91e5791bc86c0cb24c7e274d84533..06b4acd31ecb3888f9349810b877c594e885289c 100755
--- a/Source/Processors/LfpDisplayNode/LfpDisplayNode.cpp
+++ b/Source/Processors/LfpDisplayNode/LfpDisplayNode.cpp
@@ -27,12 +27,11 @@
 
 LfpDisplayNode::LfpDisplayNode()
     : GenericProcessor("LFP Viewer"),
-      displayBufferIndex(0), displayGain(1), bufferLength(5.0f),
-      abstractFifo(100), ttlState(0)
+      displayGain(1), bufferLength(5.0f),
+      abstractFifo(100)
 {
     //std::cout << " LFPDisplayNodeConstructor" << std::endl;
     displayBuffer = new AudioSampleBuffer(8, 100);
-    eventBuffer = new MidiBuffer();
 
     arrayOfOnes = new float[5000];
 
@@ -58,7 +57,38 @@ AudioProcessorEditor* LfpDisplayNode::createEditor()
 
 void LfpDisplayNode::updateSettings()
 {
-    // std::cout << "Setting num inputs on LfpDisplayNode to " << getNumInputs() << std::endl;
+    std::cout << "Setting num inputs on LfpDisplayNode to " << getNumInputs() << std::endl;
+
+    channelForEventSource.clear();
+    eventSourceNodes.clear();
+    ttlState.clear();
+
+    for (int i = 0; i < eventChannels.size(); i++)
+    {
+        if (!eventSourceNodes.contains(eventChannels[i]->sourceNodeId))
+        {
+            eventSourceNodes.add(eventChannels[i]->sourceNodeId);
+
+        }
+    }
+
+    numEventChannels = eventSourceNodes.size();
+
+    std::cout << "Found " << numEventChannels << " event channels." << std::endl;
+
+    for (int i = 0; i < eventSourceNodes.size(); i++)
+    {
+        std::cout << "Adding channel " << getNumInputs() + i << " for event source node " << eventSourceNodes[i] << std::endl;
+        channelForEventSource[eventSourceNodes[i]] = getNumInputs() + i;
+        ttlState[eventSourceNodes[i]] = 0;
+        Channel* eventChan = new Channel(this, getNumInputs() + i, EVENT_CHANNEL);
+        eventChan->sourceNodeId = eventSourceNodes[i];
+        channels.add(eventChan); // add a channel for event data for each source node
+    }
+
+    displayBufferIndex.clear();
+    displayBufferIndex.insertMultiple(0, 0, getNumInputs() + numEventChannels);
+
 }
 
 bool LfpDisplayNode::resizeBuffer()
@@ -71,7 +101,7 @@ bool LfpDisplayNode::resizeBuffer()
     if (nSamples > 0 && nInputs > 0)
     {
         abstractFifo.setTotalSize(nSamples);
-        displayBuffer->setSize(nInputs+1, nSamples); // add an extra channel for TTLs
+        displayBuffer->setSize(nInputs + numEventChannels, nSamples); // add extra channels for TTLs
         return true;
     }
     else
@@ -108,8 +138,8 @@ void LfpDisplayNode::setParameter(int parameterIndex, float newValue)
 {
     editor->updateParameterButtons(parameterIndex);
     //Sets Parameter in parameters array for processor
-    Parameter* parameterPointer=parameters.getRawDataPointer();
-    parameterPointer=parameterPointer+parameterIndex;
+    Parameter* parameterPointer = parameters.getRawDataPointer();
+    parameterPointer = parameterPointer+parameterIndex;
     parameterPointer->setValue(newValue, currentChannel);
 
     //std::cout << "Saving Parameter from " << currentChannel << ", channel ";
@@ -125,61 +155,64 @@ void LfpDisplayNode::handleEvent(int eventType, MidiMessage& event, int sampleNu
     {
         const uint8* dataptr = event.getRawData();
 
-        // int eventNodeId = *(dataptr+1);
+        int eventSourceNode = *(dataptr+1);
         int eventId = *(dataptr+2);
         int eventChannel = *(dataptr+3);
         int eventTime = event.getTimeStamp();
 
-        int samplesLeft = totalSamples - eventTime;
+        int nSamples = numSamples.at(eventSourceNode);
 
-        //	std::cout << "Received event from " << eventNodeId << ", channel "
-        //	          << eventChannel << ", with ID " << eventId << std::endl;
-        //
-        int bufferIndex = (displayBufferIndex + eventTime);// % displayBuffer->getNumSamples();
+        int samplesToFill = nSamples - eventTime;
+
+        //	std::cout << "Received event from " << eventSourceNode << ", channel "
+        //	          << eventChannel << ", with ID " << eventId << ", copying to "
+         //             << channelForEventSource[eventSourceNode] << std::endl;
+        ////
+        int bufferIndex = (displayBufferIndex[channelForEventSource[eventSourceNode]] + eventTime) % displayBuffer->getNumSamples();
 
         if (eventId == 1)
         {
-            ttlState |= (1L << eventChannel);
+            ttlState[eventSourceNode] |= (1L << eventChannel);
         }
         else
         {
-            ttlState &= ~(1L << eventChannel);
+            ttlState[eventSourceNode] &= ~(1L << eventChannel);
         }
 
-        if (samplesLeft + bufferIndex < displayBuffer->getNumSamples())
+        if (samplesToFill + bufferIndex < displayBuffer->getNumSamples())
         {
 
-            //	std::cout << bufferIndex << " " << samplesLeft << " " << ttlState << std::endl;
+            //std::cout << bufferIndex << " " << samplesToFill << " " << ttlState[eventSourceNode] << std::endl;
 
-            displayBuffer->copyFrom(displayBuffer->getNumChannels()-1,  // destChannel
+            displayBuffer->copyFrom(channelForEventSource[eventSourceNode],  // destChannel
                                     bufferIndex,		// destStartSample
                                     arrayOfOnes, 		// source
-                                    samplesLeft, 		// numSamples
-                                    float(ttlState));   // gain
+                                    samplesToFill, 		// numSamples
+                                    float(ttlState[eventSourceNode]));   // gain
         }
         else
         {
 
-            int block2Size = (samplesLeft + bufferIndex) % displayBuffer->getNumSamples();
-            int block1Size = samplesLeft - block2Size;
+            int block2Size = (samplesToFill + bufferIndex) % displayBuffer->getNumSamples();
+            int block1Size = samplesToFill - block2Size;
 
             //std::cout << "OVERFLOW." << std::endl;
 
             //std::cout << bufferIndex << " " << block1Size << " " << ttlState << std::endl;
 
-            displayBuffer->copyFrom(displayBuffer->getNumChannels()-1,  // destChannel
+            displayBuffer->copyFrom(channelForEventSource[eventSourceNode],  // destChannel
                                     bufferIndex,		// destStartSample
                                     arrayOfOnes, 		// source
                                     block1Size, 		// numSamples
-                                    float(ttlState));   // gain
+                                    float(ttlState[eventSourceNode]));   // gain
 
             //std::cout << 0 << " " << block2Size << " " << ttlState << std::endl;
 
-            displayBuffer->copyFrom(displayBuffer->getNumChannels()-1,  // destChannel
-                                    0,		// destStartSample
+            displayBuffer->copyFrom(channelForEventSource[eventSourceNode],  // destChannel
+                                    0,		                        // destStartSample
                                     arrayOfOnes, 		// source
                                     block2Size, 		// numSamples
-                                    float(ttlState));   // gain
+                                    float(ttlState[eventSourceNode]));   // gain
 
 
         }
@@ -194,132 +227,108 @@ void LfpDisplayNode::handleEvent(int eventType, MidiMessage& event, int sampleNu
 
 
     }
-    else if (eventType == TIMESTAMP)
-    {
-
-        const uint8* dataptr = event.getRawData();
-
-        // int eventNodeId = *(dataptr+1);
-        // int eventId = *(dataptr+2);
-        // int eventChannel = *(dataptr+3);
-
-        // update the timestamp for the current buffer:
-        memcpy(&bufferTimestamp, dataptr+4, 4);
-
-
 
-        //   	double timeInSeconds = double(ts)/Time::getHighResolutionTicksPerSecond();
-        //   	//int64 timestamp = ts[0] << 32 +
-        //   	//				  ts[1] << 16 +
-        //   	//				  ts[2] << 8 +
-        //   	//				  ts[3];
-        //   	//memcpy(ts, dataptr+4, 1);
-
-        //   	std::cout << "Time in seconds is " << timeInSeconds << std::endl;
-
-        // // std::cout << "Received event from " << eventNodeId <<
-        //    	//              " on channel " << eventChannel <<
-        //    	 //             " with value " << eventId <<
-        //    	 //             " for time: " << ts << std::endl;
-    }
 }
 
-void LfpDisplayNode::initializeEventChannel()
+void LfpDisplayNode::initializeEventChannels()
 {
-    if (displayBufferIndex + totalSamples < displayBuffer->getNumSamples())
-    {
 
-        //	std::cout << getNumInputs()+1 << " " << displayBufferIndex << " " << totalSamples << " " << ttlState << std::endl;
-        //
-        displayBuffer->copyFrom(displayBuffer->getNumChannels()-1,  // destChannel
-                                displayBufferIndex,		// destStartSample
-                                arrayOfOnes, 		// source
-                                totalSamples, 		// numSamples
-                                float(ttlState));   // gain
-    }
-    else
+    for (int i = 0; i < eventSourceNodes.size(); i++)
     {
 
-        int block2Size = (displayBufferIndex + totalSamples) % displayBuffer->getNumSamples();
-        int block1Size = totalSamples - block2Size;
+        int chan = channelForEventSource[eventSourceNodes[i]];
+        int index = displayBufferIndex[15]; //displayBufferIndex[chan];
 
-        // std::cout << "OVERFLOW." << std::endl;
+        int samplesLeft = displayBuffer->getNumSamples() - index;
+        int nSamples = numSamples.at(eventSourceNodes[i]);
 
-        // std::cout << bufferIndex << " " << block1Size << " " << ttlState << std::endl;
+        if (nSamples < samplesLeft)
+        {
 
-        displayBuffer->copyFrom(displayBuffer->getNumChannels()-1,  // destChannel
-                                displayBufferIndex,		// destStartSample
-                                arrayOfOnes, 		// source
-                                block1Size, 		// numSamples
-                                float(ttlState));   // gain
-        // std::cout << 0 << " " << block2Size << " " << ttlState << std::endl;
+            //	std::cout << getNumInputs()+1 << " " << displayBufferIndex << " " << totalSamples << " " << ttlState << std::endl;
+            //
+            displayBuffer->copyFrom(chan,  // destChannel
+                                    index,		// destStartSample
+                                    arrayOfOnes, 		// source
+                                    nSamples, 		// numSamples
+                                    float(ttlState[eventSourceNodes[i]]));   // gain
+
+            displayBufferIndex.set(chan, index + nSamples);
+        }
+        else
+        {
 
-        displayBuffer->copyFrom(displayBuffer->getNumChannels()-1,  // destChannel
-                                0,		// destStartSample
-                                arrayOfOnes, 		// source
-                                block2Size, 		// numSamples
-                                float(ttlState));   // gain
+            int extraSamples = nSamples - samplesLeft;
 
+            // std::cout << "OVERFLOW." << std::endl;
+            // std::cout << bufferIndex << " " << block1Size << " " << ttlState << std::endl;
 
-    }
+            displayBuffer->copyFrom(chan,    // destChannel
+                                    index,		// destStartSample
+                                    arrayOfOnes, 		// source
+                                    samplesLeft, 		// numSamples
+                                    float(ttlState[eventSourceNodes[i]]));   // gain
+            // std::cout << 0 << " " << block2Size << " " << ttlState << std::endl;
+
+            displayBuffer->copyFrom(chan,  // destChannel
+                                    0,		// destStartSample
+                                    arrayOfOnes, 		// source
+                                    extraSamples, 		// numSamples
+                                    float(ttlState[eventSourceNodes[i]]));   // gain
+
+            displayBufferIndex.set(chan, extraSamples);
+        }
+    }   
 }
 
-void LfpDisplayNode::process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSamples)
+void LfpDisplayNode::process(AudioSampleBuffer& buffer, MidiBuffer& events)
 {
     // 1. place any new samples into the displayBuffer
     //std::cout << "Display node sample count: " << nSamples << std::endl; ///buffer.getNumSamples() << std::endl;
 
-    totalSamples = nSamples;
-    displayBufferIndexEvents = displayBufferIndex;
-
-    initializeEventChannel();
-
-    checkForEvents(events); // update timestamp, see if we got any TTL events
+    initializeEventChannels();
 
-    int samplesLeft = displayBuffer->getNumSamples() - displayBufferIndex;
+    checkForEvents(events); // see if we got any TTL events
 
-    if (nSamples < samplesLeft)
+    for (int chan = 0; chan < buffer.getNumChannels(); chan++)
     {
+         int samplesLeft = displayBuffer->getNumSamples() - displayBufferIndex[chan];
+         int nSamples = getNumSamples(chan);
 
-        for (int chan = 0; chan < buffer.getNumChannels(); chan++)
+        if (nSamples < samplesLeft)
         {
+
             displayBuffer->copyFrom(chan,  			// destChannel
-                                    displayBufferIndex, // destStartSample
+                                    displayBufferIndex[chan], // destStartSample
                                     buffer, 			// source
                                     chan, 				// source channel
                                     0,					// source start sample
                                     nSamples); 			// numSamples
-
+        
+            displayBufferIndex.set(chan, displayBufferIndex[chan] + nSamples);
         }
-        displayBufferIndex += (nSamples);
-
-    }
-    else
-    {
+        else
+        {
 
-        int extraSamples = nSamples - samplesLeft;
+            int extraSamples = nSamples - samplesLeft;
 
-        for (int chan = 0; chan < buffer.getNumChannels(); chan++)
-        {
             displayBuffer->copyFrom(chan,  				// destChannel
-                                    displayBufferIndex, // destStartSample
-                                    buffer, 			// source
-                                    chan, 				// source channel
-                                    0,					// source start sample
-                                    samplesLeft); 		// numSamples
-
-            displayBuffer->copyFrom(chan,
-                                    0,
-                                    buffer,
-                                    chan,
-                                    samplesLeft,
-                                    extraSamples);
+                                    displayBufferIndex[chan], // destStartSample
+                                        buffer, 			// source
+                                        chan, 				// source channel
+                                        0,					// source start sample
+                                        samplesLeft); 		// numSamples
+
+                displayBuffer->copyFrom(chan,
+                                        0,
+                                        buffer,
+                                        chan,
+                                        samplesLeft,
+                                        extraSamples);
+
+            displayBufferIndex.set(chan, extraSamples);
         }
-
-        displayBufferIndex = extraSamples;
     }
 
-
-
 }
 
diff --git a/Source/Processors/LfpDisplayNode/LfpDisplayNode.h b/Source/Processors/LfpDisplayNode/LfpDisplayNode.h
index 6a061d44d482980328178747ec256ef5fe79480c..a475e19f35f5849822b23b5833da402389c00b99 100755
--- a/Source/Processors/LfpDisplayNode/LfpDisplayNode.h
+++ b/Source/Processors/LfpDisplayNode/LfpDisplayNode.h
@@ -55,7 +55,7 @@ public:
         return true;
     }
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
 
     void setParameter(int, float);
 
@@ -70,20 +70,22 @@ public:
     {
         return displayBuffer;
     }
-    int getDisplayBufferIndex()
+    int getDisplayBufferIndex(int chan)
     {
-        return displayBufferIndex;
+        return displayBufferIndex[chan];
     }
 
 private:
 
-    void initializeEventChannel();
+    void initializeEventChannels();
 
     ScopedPointer<AudioSampleBuffer> displayBuffer;
-    ScopedPointer<MidiBuffer> eventBuffer;
 
-    int displayBufferIndex;
-    int displayBufferIndexEvents;
+    Array<int> displayBufferIndex;
+    Array<int> eventSourceNodes;
+    std::map<int, int> channelForEventSource;
+
+    int numEventChannels;
 
     float displayGain; //
     float bufferLength; // s
@@ -91,12 +93,10 @@ private:
     AbstractFifo abstractFifo;
 
     int64 bufferTimestamp;
-    int ttlState;
+    std::map<int, int> ttlState;
     float* arrayOfOnes;
     int totalSamples;
 
-    //Time timer;
-
     bool resizeBuffer();
 
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LfpDisplayNode);
diff --git a/Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.cpp b/Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.cpp
index 8e9773c270c8a59f93b835915fba22f70115ffd0..1562df5ce2e1c274d8554625135407932210f5ac 100755
--- a/Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.cpp
+++ b/Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.cpp
@@ -119,7 +119,7 @@ void LfpTriggeredAverageNode::setParameter(int parameterIndex, float newValue)
         ed->canvas->setParameter(parameterIndex, newValue);
 }
 
-void LfpTriggeredAverageNode::handleEvent(int eventType, MidiMessage& event, int sampleNum)
+void LfpTriggeredAverageNode::handleEvent(int eventType, MidiMessage& event)
 {
     if (eventType == TTL)
     {
@@ -264,12 +264,14 @@ void LfpTriggeredAverageNode::initializeEventChannel()
     }
 }
 
-void LfpTriggeredAverageNode::process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSamples)
+void LfpTriggeredAverageNode::process(AudioSampleBuffer& buffer, MidiBuffer& events)
 {
     // 1. place any new samples into the displayBuffer
     //std::cout << "Display node sample count: " << nSamples << std::endl; ///buffer.getNumSamples() << std::endl;
 
-    totalSamples = nSamples;
+    int nSamples = 100;
+
+    totalSamples = nSamples; //nSamples;
     displayBufferIndexEvents = displayBufferIndex;
 
     initializeEventChannel();
diff --git a/Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.h b/Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.h
index 413a1732323a19eb5933ad34c0cc1a17e83fa6cb..3614c1ce4de0e5f5316cb6a22608063f735f7ca4 100755
--- a/Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.h
+++ b/Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.h
@@ -54,7 +54,7 @@ public:
         return true;
     }
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
 
     void setParameter(int, float);
 
@@ -63,7 +63,7 @@ public:
     bool enable();
     bool disable();
 
-    void handleEvent(int, MidiMessage&, int);
+    void handleEvent(int, MidiMessage&);
 
     AudioSampleBuffer* getDisplayBufferAddress()
     {
diff --git a/Source/Processors/Merger/Merger.cpp b/Source/Processors/Merger/Merger.cpp
index 40ec6bc5439f0515bde717b2c5fdfcf073c02002..464d64a442fe25b0d67dcd1af98024e777dcb0e5 100755
--- a/Source/Processors/Merger/Merger.cpp
+++ b/Source/Processors/Merger/Merger.cpp
@@ -178,11 +178,11 @@ void Merger::updateSettings()
     {
 
         settings.sampleRate = getDefaultSampleRate();
-        settings.numOutputs = getDefaultNumOutputs();
+        settings.numOutputs = getNumHeadstageOutputs();
 
         for (int i = 0; i < getNumOutputs(); i++)
         {
-            Channel* ch = new Channel(this, i);
+            Channel* ch = new Channel(this, i, HEADSTAGE_CHANNEL);
             ch->sampleRate = getDefaultSampleRate();
             ch->bitVolts = getDefaultBitVolts();
 
diff --git a/Source/Processors/Merger/Merger.h b/Source/Processors/Merger/Merger.h
index 90699a154da90ffb9e21f928939ba030a346e7a8..6c1bc679960948f4cce4e81b30656c9efe8f274c 100755
--- a/Source/Processors/Merger/Merger.h
+++ b/Source/Processors/Merger/Merger.h
@@ -52,7 +52,7 @@ public:
     AudioProcessorEditor* createEditor();
 
     /** Nothing happens here, because Mergers are not part of the ProcessorGraph. */
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples) {}
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages) {}
 
     bool isMerger()
     {
diff --git a/Source/Processors/MessageCenter/MessageCenter.cpp b/Source/Processors/MessageCenter/MessageCenter.cpp
index e07812744df37e0146153048db9617614c5649a8..30c7615b6b9708591a24fd09434b510c92cf0cb3 100644
--- a/Source/Processors/MessageCenter/MessageCenter.cpp
+++ b/Source/Processors/MessageCenter/MessageCenter.cpp
@@ -27,7 +27,7 @@
 //---------------------------------------------------------------------
 
 MessageCenter::MessageCenter() :
-    GenericProcessor("Message Center"), newEventAvailable(false), isRecording(false)
+    GenericProcessor("Message Center"), newEventAvailable(false), isRecording(false), sourceNodeId(0)
 {
 
     setPlayConfigDetails(0, // number of inputs
@@ -65,27 +65,54 @@ void MessageCenter::setParameter(int parameterIndex, float newValue)
 
 }
 
-void MessageCenter::process(AudioSampleBuffer& buffer, MidiBuffer& eventBuffer, int& nSamples)
+void MessageCenter::setSourceNodeId(int id)
+{
+    sourceNodeId = id;
+}
+
+int MessageCenter::getSourceNodeId()
+{
+    return sourceNodeId;
+}
+
+void MessageCenter::process(AudioSampleBuffer& buffer, MidiBuffer& eventBuffer)
 {
 
     if (newEventAvailable)
     {
         int numBytes = 0;
-        
+
         String eventString = messageCenterEditor->getLabelString();
 
         CharPointer_UTF8 data = eventString.toUTF8();
+        int realId = getNodeId();
+
+        //Fake node ID to the specified source for the event timestamps
+        if (sourceNodeId > 0)
+            setNodeId(sourceNodeId);
 
         addEvent(eventBuffer,
-                MESSAGE,
-                0,
-                0,
-                0,
-                data.length()+1, //It doesn't hurt to send the end-string null and can help avoid issues
-                (uint8*) data.getAddress());
+                 MESSAGE,
+                 0,
+                 0,
+                 0,
+                 data.length()+1, //It doesn't hurt to send the end-string null and can help avoid issues
+                 (uint8*) data.getAddress());
+
+        setNodeId(realId);
 
         newEventAvailable = false;
     }
 
-  
+
 }
+
+void MessageCenter::addSourceProcessor(GenericProcessor* p)
+{
+    messageCenterEditor->addSourceProcessor(p);
+}
+
+void MessageCenter::removeSourceProcessor(GenericProcessor* p)
+{
+    messageCenterEditor->removeSourceProcessor(p);
+}
\ No newline at end of file
diff --git a/Source/Processors/MessageCenter/MessageCenter.h b/Source/Processors/MessageCenter/MessageCenter.h
index ec4218ce6ef12ddf33c8520d076197b1c06b47ac..82b9a11c59b1832d5ad3114fc3e7916cc4c6c7dd 100644
--- a/Source/Processors/MessageCenter/MessageCenter.h
+++ b/Source/Processors/MessageCenter/MessageCenter.h
@@ -50,7 +50,7 @@ public:
     ~MessageCenter();
 
     /** Handle incoming data and decide which files and events to write to disk. */
-    void process(AudioSampleBuffer& buffer, MidiBuffer& eventBuffer, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& eventBuffer);
 
     /** Called when new events arrive. */
     void setParameter(int parameterIndex, float newValue);
@@ -61,8 +61,20 @@ public:
     /** A pointer to the Message Center editor. */
     ScopedPointer<MessageCenterEditor> messageCenterEditor;
 
-    void startRecording() {isRecording = true;}
-    void stopRecording() {isRecording = false;}
+    void startRecording()
+    {
+        isRecording = true;
+    }
+    void stopRecording()
+    {
+        isRecording = false;
+    }
+
+    void setSourceNodeId(int id);
+    int getSourceNodeId();
+
+    void addSourceProcessor(GenericProcessor* p);
+    void removeSourceProcessor(GenericProcessor* p);
 
 private:
 
@@ -70,6 +82,8 @@ private:
 
     bool isRecording;
 
+    int sourceNodeId;
+
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MessageCenter);
 
 };
diff --git a/Source/Processors/MessageCenter/MessageCenterEditor.cpp b/Source/Processors/MessageCenter/MessageCenterEditor.cpp
index ab457e9906e0b7919189bf3ff7498e3f3bc6ca0d..ae76f9b37c9115186c498506c6009f33ae9e57bb 100644
--- a/Source/Processors/MessageCenter/MessageCenterEditor.cpp
+++ b/Source/Processors/MessageCenter/MessageCenterEditor.cpp
@@ -24,14 +24,14 @@
 #include "MessageCenterEditor.h"
 
 MessageCenterEditor::MessageCenterEditor(MessageCenter* owner) :
-	AudioProcessorEditor(owner),
-	messageCenter(owner),
+    AudioProcessorEditor(owner),
+    messageCenter(owner),
     incomingBackground(100, 100, 100),
     outgoingBackground(100, 100, 100)
 {
 
-    incomingMessageDisplayArea = new Label("Message Display Area","No new messages.");
-    outgoingMessageDisplayArea = new Label("Message Display Area","Type a new message here.");
+    incomingMessageDisplayArea = new MessageLabel("Message Display Area","No new messages.");
+    outgoingMessageDisplayArea = new MessageLabel("Message Display Area","Type a new message here.");
     outgoingMessageDisplayArea->setEditable(true);
 
     addAndMakeVisible(incomingMessageDisplayArea);
@@ -42,6 +42,8 @@ MessageCenterEditor::MessageCenterEditor(MessageCenter* owner) :
     sendMessageButton->setTooltip("Send a message to be saved by the record node");
     addAndMakeVisible(sendMessageButton);
 
+    sourceMenu = new PopupMenu();
+
 }
 
 MessageCenterEditor::~MessageCenterEditor()
@@ -52,7 +54,7 @@ MessageCenterEditor::~MessageCenterEditor()
 
 void MessageCenterEditor::buttonClicked(Button* button)
 {
-	messageCenter->setParameter(1,1);
+    messageCenter->setParameter(1,1);
 
 }
 
@@ -64,62 +66,64 @@ void MessageCenterEditor::labelTextChanged(Label* label)
 void MessageCenterEditor::timerCallback()
 {
 
-	bool shouldRepaint = false;
+    bool shouldRepaint = false;
 
-	float incomingAlpha = incomingBackground.getFloatAlpha();
+    float incomingAlpha = incomingBackground.getFloatAlpha();
 
-	if (incomingAlpha > 0)
-	{
-		incomingAlpha -= 0.05;
+    if (incomingAlpha > 0)
+    {
+        incomingAlpha -= 0.05;
 
-		if (incomingAlpha < 0)
-			incomingAlpha = 0;
+        if (incomingAlpha < 0)
+            incomingAlpha = 0;
 
-		incomingBackground = incomingBackground.withAlpha(incomingAlpha);
+        incomingBackground = incomingBackground.withAlpha(incomingAlpha);
 
-		shouldRepaint = true;
-	}
+        shouldRepaint = true;
+    }
 
-	if (shouldRepaint)
-		repaint();
-	else
-		stopTimer();
+    if (shouldRepaint)
+        repaint();
+    else
+        stopTimer();
 
 }
 
 bool MessageCenterEditor::keyPressed(const KeyPress& key)
 {
-	return false;
+    return false;
 }
 
 String MessageCenterEditor::getLabelString()
 {
-	return outgoingMessageDisplayArea->getText();
+    return outgoingMessageDisplayArea->getText();
 }
 
 
 void MessageCenterEditor::enable()
 {
-	//sendMessageButton->setVisible(true);
+    //sendMessageButton->setVisible(true);
 }
 
 void MessageCenterEditor::disable()
 {
-	//sendMessageButton->setVisible(false);
+    //sendMessageButton->setVisible(false);
 }
 
 void MessageCenterEditor::messageReceived(bool state)
 {
-	if (!state)
-	{
-		incomingMessageDisplayArea->setText("Cannot save messages when recording is not active.", sendNotification);
-		incomingBackground = Colours::red;
-	} else {
-		incomingMessageDisplayArea->setText("Message sent.", sendNotification);
-		incomingBackground = Colours::green;
-	}
+    if (!state)
+    {
+        incomingMessageDisplayArea->setText("Cannot save messages when recording is not active.", sendNotification);
+        incomingBackground = Colours::red;
+    }
+    else
+    {
+        incomingMessageDisplayArea->setText("Message sent.", sendNotification);
+        incomingBackground = Colours::green;
+    }
 
-	startTimer(75);
+    startTimer(75);
 }
 
 void MessageCenterEditor::paint(Graphics& g)
@@ -168,10 +172,70 @@ void MessageCenterEditor::actionListenerCallback(const String& message)
 
 void MessageCenterEditor::saveStateToXml(XmlElement* xml)
 {
-
+    XmlElement* messageEditorState = xml->createNewChildElement("MESSAGECENTER");
+    messageEditorState->setAttribute("sourceNodeId",messageCenter->getSourceNodeId());
 }
 
 void MessageCenterEditor::loadStateFromXml(XmlElement* xml)
 {
+    forEachXmlChildElement(*xml, xmlNode)
+    {
+        if (xmlNode->hasTagName("MESSAGECENTER"))
+        {
+            messageCenter->setSourceNodeId(xmlNode->getIntAttribute("sourceNodeId"));
+        }
+    }
+}
 
+void MessageCenterEditor::addSourceProcessor(GenericProcessor* p)
+{
+    sourcesList.add(p);
+}
+
+void MessageCenterEditor::removeSourceProcessor(GenericProcessor* p)
+{
+    sourcesList.removeAllInstancesOf(p);
+}
+
+void MessageCenterEditor::mouseDown(const MouseEvent& event)
+{
+    int res;
+    if (event.mods.isPopupMenu())
+    {
+        PopupMenu::dismissAllActiveMenus();
+        sourceMenu->clear();
+        if (sourcesList.size() > 0)
+        {
+            for (int i=0; i < sourcesList.size(); i++)
+            {
+                GenericProcessor* p = sourcesList[i];
+                sourceMenu->addItem(i+1,p->getName(),true,(p->nodeId == messageCenter->getSourceNodeId()));
+            }
+        }
+        else
+        {
+            sourceMenu->addItem(-1,"No sources",false,false);
+        }
+        res = sourceMenu->show(0,50,0,0);
+
+        if (res > 0)
+        {
+            GenericProcessor* p = sourcesList[res-1];
+            std::cout << "Selecting " << p->getName() << " with id " << p->nodeId << " as message source" << std::endl;
+            messageCenter->setSourceNodeId(p->nodeId);
+        }
+    }
+}
+
+MessageLabel::MessageLabel(const String& componentName, const String& labelText)
+    : Label(componentName,labelText)
+{
+}
+
+void MessageLabel::mouseDown(const MouseEvent& event)
+{
+    if (event.mods.isPopupMenu())
+    {
+        getParentComponent()->mouseDown(event.getEventRelativeTo(getParentComponent()));
+    }
 }
diff --git a/Source/Processors/MessageCenter/MessageCenterEditor.h b/Source/Processors/MessageCenter/MessageCenterEditor.h
index 81df70a72fedf4335398efbfb9df21ff35b75ace..800a14c899d98df9a3dd7608f4767c293d3cb5b4 100644
--- a/Source/Processors/MessageCenter/MessageCenterEditor.h
+++ b/Source/Processors/MessageCenter/MessageCenterEditor.h
@@ -28,6 +28,8 @@
 #include "MessageCenter.h"
 #include <stdio.h>
 
+class MessageLabel;
+
 /**
 	Holds the interface for adding events to the message queue
 
@@ -61,8 +63,13 @@ public:
     void saveStateToXml(XmlElement* xml);
     void loadStateFromXml(XmlElement* xml);
 
+    void addSourceProcessor(GenericProcessor* p);
+    void removeSourceProcessor(GenericProcessor* p);
+
     String getLabelString();
 
+    void mouseDown(const MouseEvent& event);
+
 private:
 
     void buttonClicked(Button* button);
@@ -75,14 +82,17 @@ private:
     void actionListenerCallback(const String& message);
 
     /** A JUCE label used to display message text. */
-    ScopedPointer<Label> incomingMessageDisplayArea;
+    ScopedPointer<MessageLabel> incomingMessageDisplayArea;
 
     /** A JUCE label used to display message text. */
-    ScopedPointer<Label> outgoingMessageDisplayArea;
+    ScopedPointer<MessageLabel> outgoingMessageDisplayArea;
 
     /** A JUCE button used to send messages. */
     ScopedPointer<Button> sendMessageButton;
 
+    ScopedPointer<PopupMenu> sourceMenu;
+    Array<GenericProcessor*> sourcesList;
+
     MessageCenter* messageCenter;
 
     Colour incomingBackground;
@@ -92,6 +102,11 @@ private:
 
 };
 
-
+class MessageLabel : public Label
+{
+public:
+    MessageLabel(const String& componentName=String::empty, const String& labelText=String::empty);
+    void mouseDown(const MouseEvent& event);
+};
 
 #endif  // MESSAGECENTEREDITOR_H_INCLUDED
diff --git a/Source/Processors/NetworkEvents/NetworkEvents.cpp b/Source/Processors/NetworkEvents/NetworkEvents.cpp
index ba1e1c09ae2cd65d99ecb47df43f83e2b4309de9..0e04c91e22887ddab7fe685dd48fe76749c61f64 100644
--- a/Source/Processors/NetworkEvents/NetworkEvents.cpp
+++ b/Source/Processors/NetworkEvents/NetworkEvents.cpp
@@ -269,7 +269,7 @@ void NetworkEvents::postTimestamppedStringToMidiBuffer(StringTS s, MidiBuffer& e
 			 (uint8) NETWORK,
 			 0,
 			 0,
-			 (uint8) GENERIC_EVENT,
+			 0,
 			 (uint8) s.len+8,
 			 msg_with_ts);
 
@@ -380,8 +380,7 @@ String NetworkEvents::handleSpecialMessages(StringTS msg)
 }
 
 void NetworkEvents::process(AudioSampleBuffer& buffer,
-							MidiBuffer& events,
-							int& nSamples)
+							MidiBuffer& events)
 {
 
 	//std::cout << "NETWORK NODE" << std::endl;
@@ -399,8 +398,7 @@ void NetworkEvents::process(AudioSampleBuffer& buffer,
 		     networkMessagesQueue.pop();
 	 }
 	 lock.exit();
-	 nSamples = -10; // make sure this is not processed;
-	//printf("Exitting NetworkEvents::process\n");	
+
 }
 
 
diff --git a/Source/Processors/NetworkEvents/NetworkEvents.h b/Source/Processors/NetworkEvents/NetworkEvents.h
index 6dc9c4ac0cf8cd855c4d04fdd2e2f52f42a8e06f..0609d5d1bfaf93469d24b6933f10a297672e73b0 100644
--- a/Source/Processors/NetworkEvents/NetworkEvents.h
+++ b/Source/Processors/NetworkEvents/NetworkEvents.h
@@ -74,7 +74,7 @@ public:
 	int64 getExtrapolatedHardwareTimestamp(int64 softwareTS);
 	void initSimulation();
 	void simulateDesignAndTrials(juce::MidiBuffer& events);
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     void setParameter(int parameterIndex, float newValue);
 	String handleSpecialMessages(StringTS msg);
 	std::vector<String> splitString(String S, char sep);
diff --git a/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.cpp b/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.cpp
index 9fa3ecda7a50c086c5f7c7a56acc0932da381a96..b4659e074b5e3d89f8ecb3f209facc77b0cea0d5 100644
--- a/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.cpp
+++ b/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.cpp
@@ -126,7 +126,10 @@ void PeriStimulusTimeHistogramNode::updateSettings()
 //    diskWriteLock = recordNode->getLock();
 }
 
-
+void PeriStimulusTimeHistogramNode::setHardwareTriggerAlignmentChannel(int chan)
+{
+	trialCircularBuffer->setHardwareTriggerAlignmentChannel(chan);
+}
 
 bool PeriStimulusTimeHistogramNode::enable()
 {
@@ -157,7 +160,7 @@ void PeriStimulusTimeHistogramNode::toggleConditionVisibility(int cond)
 	}
 }
 
-void PeriStimulusTimeHistogramNode::process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSamples)
+void PeriStimulusTimeHistogramNode::process(AudioSampleBuffer& buffer, MidiBuffer& events)
 {
 	//printf("Entering PeriStimulusTimeHistogramNode::process\n");
 	// Update internal statistics 
@@ -169,7 +172,7 @@ void PeriStimulusTimeHistogramNode::process(AudioSampleBuffer& buffer, MidiBuffe
 		syncInternalDataStructuresWithSpikeSorter();	
 	} else if (trialCircularBuffer != nullptr)
 	{
-		trialCircularBuffer->process(buffer,nSamples,hardware_timestamp,software_timestamp);
+		trialCircularBuffer->process(buffer,getNumSamples(0),hardware_timestamp,software_timestamp);
 	}
 
 
@@ -464,16 +467,20 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even
     } 
 	if (eventType == TTL)
 	{
-		   const uint8* dataptr = event.getRawData();
-		   bool ttl_raise = dataptr[2] > 0;
-		   int channel = dataptr[3];
-		   int64  ttl_timestamp_software,ttl_timestamp_hardware;
-		   memcpy(&ttl_timestamp_software, dataptr+4, 8);
-		   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 );
+	Time t;
+	   const uint8* dataptr = event.getRawData();
+	   int ttl_source = dataptr[1];
+	   bool ttl_raise = dataptr[2] > 0;
+	   int channel = dataptr[3];
+	   int64 ttl_timestamp_hardware = timestamps[ttl_source] + samplePosition; // hardware time
+	   int64 ttl_timestamp_software = t.getHighResolutionTicks(); // get software time
+	   //int64  ttl_timestamp_software,ttl_timestamp_hardware;
+	   //memcpy(&ttl_timestamp_software, dataptr+4, 8);
+	   //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)
@@ -534,7 +541,7 @@ String PeriStimulusTimeHistogramNode::generateHeader()
     header += "header.bitVolts = ";
 	if (recordNode->channels.size() > 0)
 	{
-		header += String(recordNode->channels[0]->getChannelGain());
+		header += String(recordNode->channels[0]->bitVolts);
 	}
 	else
 	{
diff --git a/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.h b/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.h
index 72bd2e016825f4711dd5f70d1ffc1610e8cdfbae..f5c3fdc8e46517fd0077bd781e5f57e0b3afdc82 100644
--- a/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.h
+++ b/Source/Processors/PSTH/PeriStimulusTimeHistogramNode.h
@@ -39,8 +39,6 @@ class DataViewport;
 class SpikePlot;
 class TrialCircularBuffer;
 
-
-
 class PeriStimulusTimeHistogramNode :  public GenericProcessor
 {
 public:
@@ -57,11 +55,10 @@ public:
         return true;
     }
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
 
     void syncInternalDataStructuresWithSpikeSorter();
 
-	
 	void allocateTrialCircularBuffer();
     void handleEvent(int, MidiMessage&, int);
 
@@ -87,6 +84,8 @@ public:
 	bool saveTTLs, saveNetworkEvents,saveEyeTracking ;
 	int spikeSavingMode;
 	bool saveNetworkEventsWhenNotRecording;
+
+    void setHardwareTriggerAlignmentChannel(int chan);
 	
 	void handleNetworkMessage(StringTS s);
 private:
@@ -106,7 +105,7 @@ private:
     int displayBufferSize;
     bool redrawRequested;
 	int syncCounter;
-	int64 hardware_timestamp,software_timestamp;
+	int64 hardware_timestamp, software_timestamp;
 
 	std::queue<StringTS> networkEventsHistory;
     RecordNode* recordNode;
diff --git a/Source/Processors/PSTH/TrialCircularBuffer.cpp b/Source/Processors/PSTH/TrialCircularBuffer.cpp
index 897f7e469fc79f97e7035b3cd47a4cf108f13089..1a14799b9f1a56f6f4c25c17636edb6453981373 100644
--- a/Source/Processors/PSTH/TrialCircularBuffer.cpp
+++ b/Source/Processors/PSTH/TrialCircularBuffer.cpp
@@ -57,7 +57,6 @@ void setDefaultColors(uint8 &R, uint8 &G, uint8 &B, int ID)
 	{52, 73, 94},
 	{230, 126, 34},
 	{231, 76, 60},
-	//{22, 160, 133},
 	{255, 0, 0},
 	{39, 174, 96},
 	{41, 128, 185},
@@ -66,24 +65,22 @@ void setDefaultColors(uint8 &R, uint8 &G, uint8 &B, int ID)
 	{243, 156, 18},
 	{211, 84, 0},
 	{192, 57, 43},
-
-		{224,185,36},
-  {214,210,182},
-  {243,119,33},
-  {186,157,168},
-  {237,37,36},
-  {179,122,79},
-  {217,46,171},
-  {217, 139,196},
-  {101,31,255},
-  {141,111,181},
-  {48,117,255},
-  {184,198,224},
-  {116,227,156},
-  {150,158,155},
-  {82,173,0},
-		{125,99,32}};
-
+	{224,185,36},
+	{214,210,182},
+	{243,119,33},
+	{186,157,168},
+	{237,37,36},
+	{179,122,79},
+	{217,46,171},
+	{217, 139,196},
+	{101,31,255},
+	{141,111,181},
+	{48,117,255},
+	{184,198,224},
+	{116,227,156},
+	{150,158,155},
+	{82,173,0},
+	{125,99,32}};
 
 	/*
    {      0,         0,    255},
@@ -101,7 +98,7 @@ void setDefaultColors(uint8 &R, uint8 &G, uint8 &B, int ID)
 
 
 /******************************/
-PSTH::PSTH(int ID, TrialCircularBufferParams params_,bool vis) : conditionID(ID),params(params_),numTrials(0),visible(vis)
+PSTH::PSTH(int ID, TrialCircularBufferParams params_, bool vis) : conditionID(ID),params(params_),numTrials(0),visible(vis)
 {
 	// if approximate is on, we won't sample exactly xmin and xmax
 	if (params.approximate)
@@ -1355,14 +1352,15 @@ std::vector<int64> SmartSpikeCircularBuffer::getAlignedSpikes(Trial *trial, floa
 
 TrialCircularBuffer::~TrialCircularBuffer()
 {
-	delete lfpBuffer;
-	lfpBuffer = nullptr;
-	delete ttlBuffer;
-	ttlBuffer = nullptr;
+	//delete lfpBuffer;
+	//lfpBuffer = nullptr;
+	//delete ttlBuffer;
+	//ttlBuffer = nullptr;
 	electrodesPSTH.clear();
-	delete threadpool;
-	threadpool = nullptr;
+	//delete threadpool;
+	//threadpool = nullptr;
 }
+
 TrialCircularBuffer::TrialCircularBuffer()
 {
 	lfpBuffer = ttlBuffer = nullptr;
@@ -1374,6 +1372,38 @@ TrialCircularBuffer::TrialCircularBuffer()
 	useThreads = true;
 }
 
+TrialCircularBuffer::TrialCircularBuffer(TrialCircularBufferParams params_) : params(params_)
+{
+	Time t;
+	numTicksPerSecond = t.getHighResolutionTicksPerSecond();
+	useThreads = false;
+	conditionCounter = 0;
+	firstTime = true;
+	trialCounter = 0;
+	lastSimulatedTrialTS = 0;
+	lastTrialID = 0;
+	hardwareTriggerAlignmentChannel = -1;
+	uniqueIntervalID = 0;
+	// sampling them should be at least 600 Hz (Nyquist!)
+	// We typically sample everything at 30000, so a sub-sampling by a factor of 50 should be good
+	int subSample = params.sampleRate/ params.desiredSamplingRateHz;
+	float numSeconds = 2*(params.maxTrialTimeSeconds+params.preSec+params.postSec);
+	lfpBuffer = new SmartContinuousCircularBuffer(params.numChannels, params.sampleRate, subSample, numSeconds);
+	ttlBuffer = new SmartContinuousCircularBuffer(params.numTTLchannels, params.sampleRate, subSample, numSeconds);
+	lastTTLts.resize(params.numTTLchannels);
+	ttlChannelStatus.resize(params.numTTLchannels);
+	for (int k=0;k<params.numTTLchannels;k++) {
+		ttlChannelStatus[k] = false;
+		lastTTLts[k] = 0;
+	}
+	int numCpus = SystemStats::getNumCpus();
+	// create a thead pool to analyze incoming trials
+	if (useThreads)
+		threadpool = new ThreadPool(numCpus);
+
+	clearDesign();
+}
+
 void TrialCircularBuffer::getLastTrial(int electrodeIndex, int channelIndex, int conditionIndex, float &x0, float &dx, std::vector<float> &y)
 {
 	const ScopedLock myScopedLock (psthMutex);
@@ -1452,37 +1482,6 @@ void TrialCircularBuffer::setHardwareTriggerAlignmentChannel(int k)
 	hardwareTriggerAlignmentChannel = k;
 }
 
-TrialCircularBuffer::TrialCircularBuffer(TrialCircularBufferParams params_) : params(params_)
-{
-	Time t;
-	numTicksPerSecond = t.getHighResolutionTicksPerSecond();
-	useThreads = true;
-	conditionCounter = 0;
-	firstTime = true;
-	trialCounter = 0;
-	lastSimulatedTrialTS = 0;
-	lastTrialID = 0;
-	hardwareTriggerAlignmentChannel = -1;
-	uniqueIntervalID = 0;
-	// sampling them should be at least 600 Hz (Nyquist!)
-	// We typically sample everything at 30000, so a sub-sampling by a factor of 50 should be good
-	int subSample = params.sampleRate/ params.desiredSamplingRateHz;
-	float numSeconds = 2*(params.maxTrialTimeSeconds+params.preSec+params.postSec);
-	lfpBuffer = new SmartContinuousCircularBuffer(params.numChannels, params.sampleRate, subSample, numSeconds);
-	ttlBuffer = new SmartContinuousCircularBuffer(params.numTTLchannels, params.sampleRate, subSample, numSeconds);
-	lastTTLts.resize(params.numTTLchannels);
-	ttlChannelStatus.resize(params.numTTLchannels);
-	for (int k=0;k<params.numTTLchannels;k++) {
-		ttlChannelStatus[k] = false;
-		lastTTLts[k] = 0;
-	}
-	int numCpus = SystemStats::getNumCpus();
-	// create a thead pool to analyze incoming trials
-	threadpool = new ThreadPool(numCpus);
-	clearDesign();
-}
-
-
 
 
 /*
@@ -1514,6 +1513,7 @@ void TrialCircularBuffer::addDefaultTTLConditions(Array<bool> visibility)
 	  for (int channel = 0; channel < params.numTTLchannels; channel++)
 	  {
 		  StringTS simulatedConditionString;
+
 		  if (visibility[channel])
 			simulatedConditionString = StringTS("addcondition name ttl"+String(channel+1)+" trialtypes "+String(TTL_TRIAL_OFFSET+channel)+" visible 1");
 		  else
@@ -1551,7 +1551,7 @@ void TrialCircularBuffer::clearAll()
 {
 	const ScopedLock myScopedLock (psthMutex);
 	//lockPSTH();
-	for (int i=0;i<electrodesPSTH.size();i++) 
+	for (int i = 0; i < electrodesPSTH.size(); i++) 
 	{
 		for (int ch=0;ch<electrodesPSTH[i].channelsPSTHs.size();ch++)
 		{
@@ -1632,15 +1632,16 @@ void TrialCircularBuffer::modifyConditionVisibility(int cond, bool newstate)
 
 //	lockPSTH();
 	conditions[cond].visible = newstate;
-	for (int i=0;i<electrodesPSTH.size();i++) 
+
+	for (int i = 0; i < electrodesPSTH.size(); i++) 
 	{
-		for (int ch=0;ch<electrodesPSTH[i].channelsPSTHs.size();ch++)
+		for (int ch = 0; ch < electrodesPSTH[i].channelsPSTHs.size(); ch++)
 		{
 			electrodesPSTH[i].channelsPSTHs[ch].conditionPSTHs[cond].visible = newstate;
 			electrodesPSTH[i].channelsPSTHs[ch].redrawNeeded = true;
 		}
 
-		for (int u=0;u<electrodesPSTH[i].unitsPSTHs.size();u++)
+		for (int u = 0; u < electrodesPSTH[i].unitsPSTHs.size(); u++)
 		{
 			electrodesPSTH[i].unitsPSTHs[u].conditionPSTHs[cond].visible = newstate;
 			electrodesPSTH[i].unitsPSTHs[u].redrawNeeded = true;
@@ -1656,6 +1657,7 @@ void TrialCircularBuffer::toggleConditionVisibility(int cond)
 
 	//lockPSTH();
 	conditions[cond].visible = !conditions[cond].visible;
+
 	for (int i=0;i<electrodesPSTH.size();i++) 
 	{
 		for (int ch=0;ch<electrodesPSTH[i].channelsPSTHs.size();ch++)
@@ -1708,13 +1710,14 @@ void TrialCircularBuffer::syncInternalDataStructuresWithSpikeSorter(Array<Electr
 	//lockConditions();
 	// note. This will erase all existing internal structures. Only call this in the constructor.
 	electrodesPSTH.clear();
-	for (int electrodeIter=0;electrodeIter<electrodes.size();electrodeIter++)
+
+	for (int electrodeIter = 0; electrodeIter < electrodes.size(); electrodeIter++)
 	{
 
 		ElectrodePSTH electrodePSTH(electrodes[electrodeIter]->electrodeID,electrodes[electrodeIter]->name);
 		int numChannels = electrodes[electrodeIter]->numChannels;
 		  
-		for (int k=0;k<numChannels;k++) {
+		for (int k = 0; k < numChannels; k++) {
 			int channelID = electrodes[electrodeIter]->channels[k];
 			electrodePSTH.channels.push_back(channelID);
 			ChannelPSTHs channelPSTH(channelID,params);
@@ -1729,7 +1732,7 @@ void TrialCircularBuffer::syncInternalDataStructuresWithSpikeSorter(Array<Electr
 		  // add all known units
 		  std::vector<BoxUnit> boxUnits = electrodes[electrodeIter]->spikeSort->getBoxUnits();
 		  std::vector<PCAUnit> pcaUnits = electrodes[electrodeIter]->spikeSort->getPCAUnits();
-		  for (int boxIter=0;boxIter<boxUnits.size();boxIter++)
+		  for (int boxIter = 0; boxIter < boxUnits.size(); boxIter++)
 		  {
 
 			  int unitID = boxUnits[boxIter].UnitID;
@@ -1742,13 +1745,13 @@ void TrialCircularBuffer::syncInternalDataStructuresWithSpikeSorter(Array<Electr
 			  electrodePSTH.unitsPSTHs.push_back(unitPSTHs);
 		  }
 
-		  for (int pcaIter=0;pcaIter<pcaUnits.size();pcaIter++)
+		  for (int pcaIter = 0; pcaIter < pcaUnits.size(); pcaIter++)
 		  {
 
 			  int unitID = pcaUnits[pcaIter].UnitID;
 			  UnitPSTHs unitPSTHs(unitID, params,pcaUnits[pcaIter].ColorRGB[0],
 				  pcaUnits[pcaIter].ColorRGB[1],pcaUnits[pcaIter].ColorRGB[2]);
-			  for (int k=0;k<conditions.size();k++)
+			  for (int k = 0; k < conditions.size(); k++)
 			  {
 				  unitPSTHs.conditionPSTHs.push_back(PSTH(conditions[k].conditionID, params,conditions[k].visible));
 			  }
@@ -1768,7 +1771,7 @@ void TrialCircularBuffer::addNewElectrode(Electrode *electrode)
 	ElectrodePSTH e(electrode->electrodeID,electrode->name);
 	int numChannels = electrode->numChannels;
 
-	for (int k=0;k<numChannels;k++) 
+	for (int k = 0; k < numChannels; k++) 
 	{
 		int channelID = electrode->channels[k];
 		e.channels.push_back(channelID);
@@ -1782,17 +1785,16 @@ void TrialCircularBuffer::addNewElectrode(Electrode *electrode)
 	}
 	electrodesPSTH.push_back(e);
 
-
 	// Usually when we add a new electrode it doesn't have any units, unless it was added when loading an xml...
 		if (electrode->spikeSort != nullptr)
 		{
 			std::vector<BoxUnit> boxUnits = electrode->spikeSort->getBoxUnits();
-			for (int boxIter=0;boxIter < boxUnits.size();boxIter++)
+			for (int boxIter = 0; boxIter < boxUnits.size(); boxIter++)
 			{
 				addNewUnit(electrode->electrodeID, boxUnits[boxIter].UnitID, boxUnits[boxIter].ColorRGB[0],boxUnits[boxIter].ColorRGB[1],boxUnits[boxIter].ColorRGB[2]);
 			}
 			std::vector<PCAUnit> PcaUnits = electrode->spikeSort->getPCAUnits();
-			for (int pcaIter=0;pcaIter < PcaUnits.size();pcaIter++)
+			for (int pcaIter = 0; pcaIter < PcaUnits.size(); pcaIter++)
 			{
 				addNewUnit(electrode->electrodeID, PcaUnits[pcaIter].UnitID, PcaUnits[pcaIter].ColorRGB[0],PcaUnits[pcaIter].ColorRGB[1],PcaUnits[pcaIter].ColorRGB[2]);
 			}
@@ -1804,14 +1806,14 @@ void  TrialCircularBuffer::addNewUnit(int electrodeID, int unitID, uint8 r,uint8
 {
 	// build a new PSTH for all defined conditions
 	//lockPSTH();
-		const ScopedLock myScopedLock (psthMutex);
+	const ScopedLock myScopedLock (psthMutex);
 
 	UnitPSTHs unitPSTHs(unitID, params,r,g,b);
-	for (int k=0;k<conditions.size();k++)
+	for (int k = 0; k < conditions.size(); k++)
 	{
 		unitPSTHs.conditionPSTHs.push_back(PSTH(conditions[k].conditionID, params,conditions[k].visible));
 	}
-	for (int k=0;k<electrodesPSTH.size();k++) {
+	for (int k = 0; k < electrodesPSTH.size(); k++) {
 		if (electrodesPSTH[k].electrodeID == electrodeID) {
 			electrodesPSTH[k].unitsPSTHs.push_back(unitPSTHs);
 			break;
@@ -1824,7 +1826,7 @@ void  TrialCircularBuffer::addNewUnit(int electrodeID, int unitID, uint8 r,uint8
 void  TrialCircularBuffer::removeUnit(int electrodeID, int unitID)
 {
   //lockPSTH();
-	const ScopedLock myScopedLock (psthMutex);
+  const ScopedLock myScopedLock (psthMutex);
 
   for (int e =0;e<electrodesPSTH.size();e++)
   {
@@ -1873,8 +1875,6 @@ void TrialCircularBuffer::removeElectrode(int electrodeID)
 //	unlockPSTH();
 }
 
-
-
 bool TrialCircularBuffer::parseMessage(StringTS msg)
   {
 	  bool redrawNeeded = false;
@@ -1900,6 +1900,9 @@ bool TrialCircularBuffer::parseMessage(StringTS msg)
 
  if (command == "trialstart")
 	  {
+
+	  	std::cout << "Got start of trial!" << std::endl;
+
 		  currentTrial.trialID = ++trialCounter;
 		  currentTrial.startTS = msg.timestamp;
 		  currentTrial.alignTS = 0;
@@ -1913,7 +1916,7 @@ bool TrialCircularBuffer::parseMessage(StringTS msg)
 		  const ScopedLock myScopedLock (psthMutex);
 
 		  //lockPSTH();
-		  for (int i=0;i<electrodesPSTH.size();i++) 
+		  for (int i = 0; i < electrodesPSTH.size(); i++) 
 			{
 				for (int u=0;u<electrodesPSTH[i].unitsPSTHs.size();u++)
 				{
@@ -1927,7 +1930,7 @@ bool TrialCircularBuffer::parseMessage(StringTS msg)
 	  } else if (command == "dropoutcomes")
 	  {
 		  dropOutcomes.clear();
-		  for (int k=1;k<input.size();k++)
+		  for (int k = 1; k < input.size(); k++)
 		  {
 			  dropOutcomes.push_back(input[k].getIntValue());
 		  }
@@ -2002,14 +2005,14 @@ bool TrialCircularBuffer::parseMessage(StringTS msg)
 		  //unlockConditions();
 		  // now add a new psth for this condition for all sorted units on all electrodes
 		  //lockPSTH();
-		  for (int i=0;i<electrodesPSTH.size();i++) 
+		  for (int i = 0; i < electrodesPSTH.size(); i++) 
 		  {
-			  for (int ch=0;ch<electrodesPSTH[i].channelsPSTHs.size();ch++)
+			  for (int ch = 0; ch < electrodesPSTH[i].channelsPSTHs.size(); ch++)
 			  {
 				  electrodesPSTH[i].channelsPSTHs[ch].conditionPSTHs.push_back(PSTH(newcondition.conditionID, params, newcondition.visible));
 			  }
 
-			  for (int u=0;u<electrodesPSTH[i].unitsPSTHs.size();u++)
+			  for (int u = 0; u < electrodesPSTH[i].unitsPSTHs.size(); u++)
 			  {
 				  electrodesPSTH[i].unitsPSTHs[u].conditionPSTHs.push_back(PSTH(newcondition.conditionID, params, newcondition.visible));
 			  }
@@ -2020,17 +2023,18 @@ bool TrialCircularBuffer::parseMessage(StringTS msg)
 
 	  }
 	  return   redrawNeeded ;
-  }
+}
 
 void TrialCircularBuffer::addSpikeToSpikeBuffer(SpikeObject newSpike)
 {
 	//lockPSTH();
 	const ScopedLock myScopedLock (psthMutex);
-	for (int e=0;e<electrodesPSTH.size();e++)
+
+	for (int e = 0; e < electrodesPSTH.size(); e++)
 	{
 		if (electrodesPSTH[e].electrodeID == newSpike.electrodeID)
 		{
-			for (int u=0;u<electrodesPSTH[e].unitsPSTHs.size();u++)
+			for (int u = 0; u < electrodesPSTH[e].unitsPSTHs.size(); u++)
 			{
 				if (electrodesPSTH[e].unitsPSTHs[u].unitID == newSpike.sortedId)
 				{
@@ -2049,7 +2053,7 @@ void TrialCircularBuffer::addSpikeToSpikeBuffer(SpikeObject newSpike)
 
 bool TrialCircularBuffer::contains(std::vector<int> v, int x)
 {
-	for (int k=0;k<v.size();k++)
+	for (int k = 0; k < v.size(); k++)
 		if (v[k] == x)
 			return true;
 	return false;
@@ -2099,7 +2103,7 @@ void TrialCircularBuffer::updatePSTHwithTrial(Trial *trial)
 	if (!useThreads)
 	{
 		// these two parts can be fully distributed along several threads because they are completely independent.
-		//printf("Calling updatePSTHwithTrial::update without streads\n");
+		//printf("Calling updatePSTHwithTrial::update without threads\n");
 
 		tictoc.Tic(23);
 		for (int i=0;i<electrodesPSTH.size();i++) 
@@ -2115,7 +2119,7 @@ void TrialCircularBuffer::updatePSTHwithTrial(Trial *trial)
 			}
 		}
 		tictoc.Toc(23);
-		//printf("Finished updatePSTHwithTrial::update without streads\n");
+		//printf("Finished updatePSTHwithTrial::update without threads\n");
 
 	} else {
 		tictoc.Tic(24);
@@ -2123,7 +2127,7 @@ void TrialCircularBuffer::updatePSTHwithTrial(Trial *trial)
 		int numElectrodes = electrodesPSTH.size();
 		//printf("Calling updatePSTHwithTrial::update with threads\n");
 
-		for (int i=0;i<numElectrodes;i++) 
+		for (int i = 0; i < numElectrodes; i++) 
 		{
 			TrialCircularBufferThread *job = new TrialCircularBufferThread(this,&conditionsNeedUpdating,trial,cnt++,0,i,-1);
 			threadpool->addJob(job, true);
@@ -2199,9 +2203,13 @@ void TrialCircularBuffer::addTTLevent(int channel,int64 ttl_timestamp_software,
 	// and only if its above some threshold, simulate a ttl trial.
 	// this is useful when sending train of pulses and you are interested in aligning things just
 	// to the first pulse.
+
+	std::cout << "Got that TTL event" << std::endl;
+
 	if (channel >= 0 && channel < lastTTLts.size())
 	{
-		ttlBuffer->update(channel, ttl_timestamp_software, ttl_timestamp_hardware,rise);
+		ttlBuffer->update(channel, ttl_timestamp_software, ttl_timestamp_hardware, rise);
+
 		if (params.reconstructTTL)
 		{
 			ttlStatus tmp;
@@ -2211,7 +2219,7 @@ void TrialCircularBuffer::addTTLevent(int channel,int64 ttl_timestamp_software,
 			ttlQueue.push(tmp);
 		}
 
-	if (simulateTrial)
+		if (simulateTrial)
 		{
 			int64 tickdiff = ttl_timestamp_software-lastTTLts[channel];
 			float secElapsed = float(tickdiff) / numTicksPerSecond;
@@ -2224,7 +2232,9 @@ void TrialCircularBuffer::addTTLevent(int channel,int64 ttl_timestamp_software,
 
 			if (channel == hardwareTriggerAlignmentChannel)
 			{
-				currentTrial.alignTS = ttl_timestamp_software;
+
+				std::cout << "TTL channel matches alignment channel!" << std::endl;
+				currentTrial.alignTS = ttl_timestamp_software; 
 				currentTrial.alignTS_hardware = ttl_timestamp_hardware;
 				currentTrial.hardwareAlignment = true;
 			}
@@ -3141,17 +3151,19 @@ void TrialCircularBuffer::process(AudioSampleBuffer& buffer,int nSamples,int64 h
 	tictoc.Tic(1);
 	lfpBuffer->update(buffer, hardware_timestamp,software_timestamp, nSamples);
 	tictoc.Toc(1);
-	//printf("Exitting lfpBuffer->update\n");
+	//printf("Exiting lfpBuffer->update\n");
 
 	//printf("Entering reconstructedTTLs\n");
 	tictoc.Tic(2);
-	// for oscilloscope purposes, it is easier to reconstruct TTL chnages to "continuous" form.
+
+	// for oscilloscope purposes, it is easier to reconstruct TTL changes to "continuous" form.
 	if (params.reconstructTTL) {
 		std::vector<std::vector<bool>> reconstructedTTLs = reconstructTTLchannels(hardware_timestamp,nSamples);
 		ttlBuffer->update(reconstructedTTLs,hardware_timestamp,software_timestamp,nSamples);
 	}
 	tictoc.Toc(2);
-	//printf("Exitting reconstructedTTLs\n");
+
+	//printf("Exiting reconstructedTTLs\n");
 
 	// now, check if a trial finished, and enough time has elapsed so we also
 	// have post trial information
diff --git a/Source/Processors/PSTH/TrialCircularBuffer.h b/Source/Processors/PSTH/TrialCircularBuffer.h
index 317d429b573fee160a6386a2b94037a784e5106b..b297ea307895d45124ca5905714e28d525573462 100644
--- a/Source/Processors/PSTH/TrialCircularBuffer.h
+++ b/Source/Processors/PSTH/TrialCircularBuffer.h
@@ -398,11 +398,11 @@ private:
 	std::queue<Trial> aliveTrials;
 	std::vector<Condition> conditions;
 	std::vector<ElectrodePSTH> electrodesPSTH;
-	SmartContinuousCircularBuffer *lfpBuffer;
-	SmartContinuousCircularBuffer *ttlBuffer;
+	ScopedPointer<SmartContinuousCircularBuffer> lfpBuffer;
+	ScopedPointer<SmartContinuousCircularBuffer> ttlBuffer;
 	std::queue<ttlStatus> ttlQueue;
 	TrialCircularBufferParams params;
-	ThreadPool *threadpool;
+	ScopedPointer<ThreadPool> threadpool;
 };
 
 class TrialCircularBufferThread : public ThreadPoolJob
diff --git a/Source/Processors/PhaseDetector/PhaseDetector.cpp b/Source/Processors/PhaseDetector/PhaseDetector.cpp
index 069b76454b3786709a8fc7b15cc3101eba0f510b..b8673fd45fb7d2c1c2aca843af7f2fecec1cb933 100644
--- a/Source/Processors/PhaseDetector/PhaseDetector.cpp
+++ b/Source/Processors/PhaseDetector/PhaseDetector.cpp
@@ -167,8 +167,7 @@ void PhaseDetector::handleEvent(int eventType, MidiMessage& event, int sampleNum
 }
 
 void PhaseDetector::process(AudioSampleBuffer& buffer,
-                            MidiBuffer& events,
-                            int& nSamples)
+                            MidiBuffer& events)
 {
 
     checkForEvents(events);
@@ -184,7 +183,7 @@ void PhaseDetector::process(AudioSampleBuffer& buffer,
             module.inputChan < buffer.getNumChannels())
         {
 
-            for (int i = 0; i < nSamples; i++)
+            for (int i = 0; i < getNumSamples(channels[module.inputChan]->sourceNodeId); i++)
             {
                 const float sample = *buffer.getReadPointer(module.inputChan, i);
 
diff --git a/Source/Processors/PhaseDetector/PhaseDetector.h b/Source/Processors/PhaseDetector/PhaseDetector.h
index 6116e2f2fe6ef0de397f5ba3233a99659d7b5a28..ea099df2031e779422843eef221e359d142cc997 100644
--- a/Source/Processors/PhaseDetector/PhaseDetector.h
+++ b/Source/Processors/PhaseDetector/PhaseDetector.h
@@ -46,7 +46,7 @@ public:
     PhaseDetector();
     ~PhaseDetector();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     void setParameter(int parameterIndex, float newValue);
 
     AudioProcessorEditor* createEditor();
diff --git a/Source/Processors/ProcessorGraph/ProcessorGraph.cpp b/Source/Processors/ProcessorGraph/ProcessorGraph.cpp
index e4f55a32fc4df6a225e1570ab53f4cba850565d1..ffef2749a216965a16f3cb12f766bdbf188e644a 100644
--- a/Source/Processors/ProcessorGraph/ProcessorGraph.cpp
+++ b/Source/Processors/ProcessorGraph/ProcessorGraph.cpp
@@ -33,19 +33,15 @@
 #include "../FilterNode/FilterNode.h"
 #include "../RecordNode/RecordNode.h"
 #include "../ResamplingNode/ResamplingNode.h"
-#include "../ReferenceNode/ReferenceNode.h"
 #include "../ChannelMappingNode/ChannelMappingNode.h"
-#include "../AudioResamplingNode/AudioResamplingNode.h"
 #include "../SignalGenerator/SignalGenerator.h"
 #include "../SourceNode/SourceNode.h"
 #include "../EventDetector/EventDetector.h"
 #include "../SpikeDetector/SpikeDetector.h"
 #include "../SpikeSorter/SpikeSorter.h"
 #include "../PhaseDetector/PhaseDetector.h"
-#include "../WiFiOutput/WiFiOutput.h"
 #include "../FileReader/FileReader.h"
 #include "../ArduinoOutput/ArduinoOutput.h"
-#include "../FPGAOutput/FPGAOutput.h"
 #include "../PulsePalOutput/PulsePalOutput.h"
 #include "../SerialInput/SerialInput.h"
 #include "../MessageCenter/MessageCenter.h"
@@ -94,15 +90,10 @@ void ProcessorGraph::createDefaultNodes()
     RecordNode* recn = new RecordNode();
     recn->setNodeId(RECORD_NODE_ID);
 
-
     // add audio node -- takes all inputs and selects those to be used for audio monitoring
     AudioNode* an = new AudioNode();
     an->setNodeId(AUDIO_NODE_ID);
 
-    // add audio resampling node -- resamples continuous signals to 44.1kHz
-    AudioResamplingNode* arn = new AudioResamplingNode();
-    arn->setNodeId(RESAMPLING_NODE_ID);
-
     // add message center
     MessageCenter* msgCenter = new MessageCenter();
     msgCenter->setNodeId(MESSAGE_CENTER_ID);
@@ -110,7 +101,6 @@ void ProcessorGraph::createDefaultNodes()
     addNode(on, OUTPUT_NODE_ID);
     addNode(recn, RECORD_NODE_ID);
     addNode(an, AUDIO_NODE_ID);
-    addNode(arn, RESAMPLING_NODE_ID);
     addNode(msgCenter, MESSAGE_CENTER_ID);
 
 }
@@ -155,6 +145,12 @@ void* ProcessorGraph::createNewProcessor(String& description, int id)//,
         {
             // by default, all source nodes record automatically
             processor->setAllChannelsToRecord();
+
+            getMessageCenter()->addSourceProcessor(processor);
+            if (getMessageCenter()->getSourceNodeId() == 0)
+            {
+                getMessageCenter()->setSourceNodeId(processor->getNodeId());
+            }
         }
 
         return processor->createEditor();
@@ -199,7 +195,6 @@ void ProcessorGraph::refreshColors()
         if (nodeId != OUTPUT_NODE_ID &&
             nodeId != AUDIO_NODE_ID &&
             nodeId != RECORD_NODE_ID &&
-            nodeId != RESAMPLING_NODE_ID &&
             nodeId != MESSAGE_CENTER_ID)
         {
             GenericProcessor* p =(GenericProcessor*) node->getProcessor();
@@ -223,7 +218,6 @@ void ProcessorGraph::restoreParameters()
         if (nodeId != OUTPUT_NODE_ID &&
             nodeId != AUDIO_NODE_ID &&
             nodeId != RECORD_NODE_ID &&
-            nodeId != RESAMPLING_NODE_ID &&
             nodeId != MESSAGE_CENTER_ID)
         {
             GenericProcessor* p =(GenericProcessor*) node->getProcessor();
@@ -247,7 +241,6 @@ Array<GenericProcessor*> ProcessorGraph::getListOfProcessors()
         if (nodeId != OUTPUT_NODE_ID &&
             nodeId != AUDIO_NODE_ID &&
             nodeId != RECORD_NODE_ID &&
-            nodeId != RESAMPLING_NODE_ID &&
             nodeId != MESSAGE_CENTER_ID)
         {
             GenericProcessor* p =(GenericProcessor*) node->getProcessor();
@@ -267,8 +260,7 @@ void ProcessorGraph::clearConnections()
         Node* node = getNode(i);
         int nodeId = node->nodeId;
 
-        if (nodeId != OUTPUT_NODE_ID &&
-            nodeId != RESAMPLING_NODE_ID)
+        if (nodeId != OUTPUT_NODE_ID)
         {
 
             if (nodeId != RECORD_NODE_ID && nodeId != AUDIO_NODE_ID)
@@ -287,16 +279,10 @@ void ProcessorGraph::clearConnections()
     {
 
         addConnection(AUDIO_NODE_ID, n,
-                      RESAMPLING_NODE_ID, n);
-
-        addConnection(RESAMPLING_NODE_ID, n,
                       OUTPUT_NODE_ID, n);
 
     }
 
-    addConnection(AUDIO_NODE_ID, midiChannelIndex,
-                  RESAMPLING_NODE_ID, midiChannelIndex);
-
     addConnection(MESSAGE_CENTER_ID, midiChannelIndex,
                   RECORD_NODE_ID, midiChannelIndex);
 }
@@ -465,7 +451,8 @@ void ProcessorGraph::connectProcessorToAudioAndRecordNodes(GenericProcessor* sou
     if (source == nullptr)
         return;
 
-	getRecordNode()->registerProcessor(source);
+    getRecordNode()->registerProcessor(source);
+
     for (int chan = 0; chan < source->getNumOutputs(); chan++)
     {
 
@@ -655,21 +642,11 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip
             processor = new SpikeDisplayNode();
         }
 
-        else if (subProcessorType.equalsIgnoreCase("WiFi Output"))
-        {
-            std::cout << "Creating a WiFi node." << std::endl;
-            processor = new WiFiOutput();
-        }
         else if (subProcessorType.equalsIgnoreCase("Arduino Output"))
         {
             std::cout << "Creating an Arduino node." << std::endl;
             processor = new ArduinoOutput();
         }
-        else if (subProcessorType.equalsIgnoreCase("FPGA Output"))
-        {
-            std::cout << "Creating an FPGA output node." << std::endl;
-            processor = new FPGAOutput();
-        }
         else if (subProcessorType.equalsIgnoreCase("Pulse Pal"))
         {
             std::cout << "Creating a Pulse Pal output node." << std::endl;
@@ -709,8 +686,31 @@ void ProcessorGraph::removeProcessor(GenericProcessor* processor)
 
     std::cout << "Removing processor with ID " << processor->getNodeId() << std::endl;
 
-    disconnectNode(processor->getNodeId());
-    removeNode(processor->getNodeId());
+    int nodeId = processor->getNodeId();
+
+    if (processor->isSource())
+    {
+        getMessageCenter()->removeSourceProcessor(processor);
+    }
+
+    disconnectNode(nodeId);
+    removeNode(nodeId);
+
+    if (getMessageCenter()->getSourceNodeId() == nodeId)
+    {
+        int newId = 0;
+
+        //Look for the next source node. If none is found, set the sourceid to 0
+        for (int i = 0; i < getNumNodes() && newId == 0; i++)
+        {
+            GenericProcessor* p = static_cast<GenericProcessor*>(getNode(i)->getProcessor());
+            if (p->isSource())
+            {
+                newId = p->nodeId;
+            }
+        }
+        getMessageCenter()->setSourceNodeId(newId);
+    }
 
 }
 
@@ -822,7 +822,7 @@ void ProcessorGraph::setRecordState(bool isRecording)
         {
             GenericProcessor* p = (GenericProcessor*) node->getProcessor();
 
-			p->setRecording(isRecording);
+            p->setRecording(isRecording);
         }
     }
 
diff --git a/Source/Processors/ProcessorGraph/ProcessorGraph.h b/Source/Processors/ProcessorGraph/ProcessorGraph.h
index 4bedf2bed8e08233dd1a8b3ddb32461dd4500c2c..cad797fcd5938de94b742feb3f4a8ec1103a6ee9 100644
--- a/Source/Processors/ProcessorGraph/ProcessorGraph.h
+++ b/Source/Processors/ProcessorGraph/ProcessorGraph.h
@@ -98,7 +98,6 @@ void* zmqcontext;
         RECORD_NODE_ID = 900,
         AUDIO_NODE_ID = 901,
         OUTPUT_NODE_ID = 902,
-        RESAMPLING_NODE_ID = 903,
         MESSAGE_CENTER_ID = 904
     };
 
diff --git a/Source/Processors/PulsePalOutput/PulsePalOutput.cpp b/Source/Processors/PulsePalOutput/PulsePalOutput.cpp
index a616bfcb59581859a3dd4ba374526d5b19edbebc..14ade399d1c2e8c79d228890c53e95155357a8c1 100644
--- a/Source/Processors/PulsePalOutput/PulsePalOutput.cpp
+++ b/Source/Processors/PulsePalOutput/PulsePalOutput.cpp
@@ -121,8 +121,7 @@ void PulsePalOutput::setParameter(int parameterIndex, float newValue)
 }
 
 void PulsePalOutput::process(AudioSampleBuffer& buffer,
-                             MidiBuffer& events,
-                             int& nSamples)
+                             MidiBuffer& events)
 {
 
     checkForEvents(events);
diff --git a/Source/Processors/PulsePalOutput/PulsePalOutput.h b/Source/Processors/PulsePalOutput/PulsePalOutput.h
index e9f52a13b60178757136c5568e2db767424af58a..113cb202986c48e2272af3f09f8f79499377cc3c 100644
--- a/Source/Processors/PulsePalOutput/PulsePalOutput.h
+++ b/Source/Processors/PulsePalOutput/PulsePalOutput.h
@@ -46,7 +46,7 @@ public:
     PulsePalOutput();
     ~PulsePalOutput();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     void setParameter(int parameterIndex, float newValue);
 
     void handleEvent(int eventType, MidiMessage& event, int sampleNum);
diff --git a/Source/Processors/RecordControl/RecordControl.cpp b/Source/Processors/RecordControl/RecordControl.cpp
index b3ca5b019e3f32dc6a7252f140ed5f01a241a1ba..f230171af1a9ce8dad223630ffa0f992b50c5732 100644
--- a/Source/Processors/RecordControl/RecordControl.cpp
+++ b/Source/Processors/RecordControl/RecordControl.cpp
@@ -68,8 +68,7 @@ bool RecordControl::enable()
 }
 
 void RecordControl::process(AudioSampleBuffer& buffer,
-                            MidiBuffer& events,
-                            int& nSamples)
+                            MidiBuffer& events)
 {
     checkForEvents(events);
 }
diff --git a/Source/Processors/RecordControl/RecordControl.h b/Source/Processors/RecordControl/RecordControl.h
index ffdfb4239694930dd6027cb8bace79c2216dc156..ee5ea3ed939fa6bd77f936aecd66f7f73b758b35 100644
--- a/Source/Processors/RecordControl/RecordControl.h
+++ b/Source/Processors/RecordControl/RecordControl.h
@@ -43,7 +43,7 @@ public:
     RecordControl();
     ~RecordControl();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     void setParameter(int, float);
     void updateTriggerChannel(int newChannel);
     void handleEvent(int eventType, MidiMessage& event, int);
diff --git a/Source/Processors/RecordNode/HDF5FileFormat.cpp b/Source/Processors/RecordNode/HDF5FileFormat.cpp
index 0e1d1e2c3c83482a08355566cc0fa0b778a5413f..83f967ad7991d64627f70e37189abdedb5e0d595 100644
--- a/Source/Processors/RecordNode/HDF5FileFormat.cpp
+++ b/Source/Processors/RecordNode/HDF5FileFormat.cpp
@@ -124,7 +124,9 @@ int HDF5FileBase::setAttribute(DataTypes type, void* data, String path, String n
 
 int HDF5FileBase::setAttributeArray(DataTypes type, void* data, int size, String path, String name)
 {
-    Group loc;
+    H5Location* loc;
+    Group gloc;
+    DataSet dloc;
     Attribute attr;
     DataType H5type;
     DataType origType;
@@ -132,26 +134,35 @@ int HDF5FileBase::setAttributeArray(DataTypes type, void* data, int size, String
     if (!opened) return -1;
     try
     {
-        loc = file->openGroup(path.toUTF8());
+        try
+        {
+            gloc = file->openGroup(path.toUTF8());
+            loc = &gloc;
+        }
+        catch (FileIException error) //If there is no group with that path, try a dataset
+        {
+            dloc = file->openDataSet(path.toUTF8());
+            loc = &dloc;
+        }
 
         H5type = getH5Type(type);
         origType = getNativeType(type);
 
-		if (size > 1)
-		{
-			hsize_t dims = size;
-			H5type = ArrayType(H5type,1,&dims);
-			origType = ArrayType(origType,1,&dims);
-		}
+        if (size > 1)
+        {
+            hsize_t dims = size;
+            H5type = ArrayType(H5type,1,&dims);
+            origType = ArrayType(origType,1,&dims);
+        }
 
-        if (loc.attrExists(name.toUTF8()))
+        if (loc->attrExists(name.toUTF8()))
         {
-            attr = loc.openAttribute(name.toUTF8());
+            attr = loc->openAttribute(name.toUTF8());
         }
         else
         {
             DataSpace attr_dataspace(H5S_SCALAR);
-            attr = loc.createAttribute(name.toUTF8(),H5type,attr_dataspace);
+            attr = loc->createAttribute(name.toUTF8(),H5type,attr_dataspace);
         }
 
         attr.write(origType,data);
@@ -165,13 +176,23 @@ int HDF5FileBase::setAttributeArray(DataTypes type, void* data, int size, String
     {
         PROCESS_ERROR;
     }
+    catch (DataSetIException error)
+    {
+        PROCESS_ERROR;
+    }
+    catch (FileIException error)
+    {
+        PROCESS_ERROR;
+    }
 
     return 0;
 }
 
 int HDF5FileBase::setAttributeStr(String value, String path, String name)
 {
-    Group loc;
+    H5Location* loc;
+    Group gloc;
+    DataSet dloc;
     Attribute attr;
 
     if (!opened) return -1;
@@ -179,9 +200,18 @@ int HDF5FileBase::setAttributeStr(String value, String path, String name)
     StrType type(PredType::C_S1, value.length());
     try
     {
-        loc = file->openGroup(path.toUTF8());
+        try
+        {
+            gloc = file->openGroup(path.toUTF8());
+            loc = &gloc;
+        }
+        catch (FileIException error) //If there is no group with that path, try a dataset
+        {
+            dloc = file->openDataSet(path.toUTF8());
+            loc = &dloc;
+        }
 
-        if (loc.attrExists(name.toUTF8()))
+        if (loc->attrExists(name.toUTF8()))
         {
             //attr = loc.openAttribute(name.toUTF8());
             return -1; //string attributes cannot change size easily, better not allow overwritting.
@@ -189,7 +219,7 @@ int HDF5FileBase::setAttributeStr(String value, String path, String name)
         else
         {
             DataSpace attr_dataspace(H5S_SCALAR);
-            attr = loc.createAttribute(name.toUTF8(), type, attr_dataspace);
+            attr = loc->createAttribute(name.toUTF8(), type, attr_dataspace);
         }
         attr.write(type,value.toUTF8());
 
@@ -206,6 +236,11 @@ int HDF5FileBase::setAttributeStr(String value, String path, String name)
     {
         PROCESS_ERROR;
     }
+    catch (DataSetIException error)
+    {
+        PROCESS_ERROR;
+    }
+
 
     return 0;
 }
@@ -378,9 +413,9 @@ H5::DataType HDF5FileBase::getNativeType(DataTypes type)
         case F32:
             return PredType::NATIVE_FLOAT;
             break;
-		case STR:
-			return StrType(PredType::C_S1,MAX_STR_SIZE);
-			break;
+        case STR:
+            return StrType(PredType::C_S1,MAX_STR_SIZE);
+            break;
     }
     return PredType::NATIVE_INT32;
 }
@@ -416,9 +451,9 @@ H5::DataType HDF5FileBase::getH5Type(DataTypes type)
         case F32:
             return PredType::IEEE_F32LE;
             break;
-		case STR:
-			return StrType(PredType::C_S1,MAX_STR_SIZE);
-			break;
+        case STR:
+            return StrType(PredType::C_S1,MAX_STR_SIZE);
+            break;
     }
     return PredType::STD_I32LE;
 }
@@ -449,8 +484,8 @@ HDF5RecordingData::HDF5RecordingData(DataSet* data)
     this->xChunkSize = chunk[0];
     this->xPos = dims[0];
     this->dSet = dataSet;
-    this->rowXPos = 0;
-    this->rowDataSize = 0;
+    this->rowXPos.clear();
+    this->rowXPos.insertMultiple(0,0,this->size[1]);
 }
 
 HDF5RecordingData::~HDF5RecordingData()
@@ -495,7 +530,7 @@ int HDF5RecordingData::writeDataBlock(int xDataSize, int yDataSize, HDF5FileBase
         offset[0]=xPos;
         offset[1]=0;
         offset[2]=0;
-		
+
         fSpace.selectHyperslab(H5S_SELECT_SET, dim, offset);
 
         nativeType = HDF5FileBase::getNativeType(type);
@@ -514,32 +549,6 @@ int HDF5RecordingData::writeDataBlock(int xDataSize, int yDataSize, HDF5FileBase
     return 0;
 }
 
-int HDF5RecordingData::prepareDataBlock(int xDataSize)
-{
-    hsize_t dim[3];
-    DataSpace fSpace;
-    if (dimension > 2) return -4; //We're not going to write rows in datasets bigger than 2d.
-
-    dim[2] = size[2];
-    dim[1] = size[1];
-    dim[0] = xPos + xDataSize;
-    try
-    {
-        dSet->extend(dim);
-
-        fSpace = dSet->getSpace();
-        fSpace.getSimpleExtentDims(dim);
-        size[0]=dim[0];
-    }
-    catch (DataSetIException error)
-    {
-        PROCESS_ERROR;
-    }
-    rowXPos = xPos;
-    rowDataSize = xDataSize;
-    xPos += xDataSize;
-    return 0;
-}
 
 int HDF5RecordingData::writeDataRow(int yPos, int xDataSize, HDF5FileBase::DataTypes type, void* data)
 {
@@ -547,17 +556,32 @@ int HDF5RecordingData::writeDataRow(int yPos, int xDataSize, HDF5FileBase::DataT
     DataSpace fSpace;
     DataType nativeType;
     if (dimension > 2) return -4; //We're not going to write rows in datasets bigger than 2d.
-    if (xDataSize != rowDataSize) return -2;
-    if ((yPos < 0) || (yPos >= size[1])) return -3;
+    //    if (xDataSize != rowDataSize) return -2;
+    if ((yPos < 0) || (yPos >= size[1])) return -2;
 
     try
     {
+        if (rowXPos[yPos]+xDataSize > size[0])
+        {
+            dim[1] = size[1];
+            dim[0] = rowXPos[yPos] + xDataSize;
+            dSet->extend(dim);
+
+            fSpace = dSet->getSpace();
+            fSpace.getSimpleExtentDims(dim);
+            size[0]=dim[0];
+        }
+        if (rowXPos[yPos]+xDataSize > xPos)
+        {
+            xPos = rowXPos[yPos]+xDataSize;
+        }
+
         dim[0] = xDataSize;
         dim[1] = 1;
         DataSpace mSpace(dimension,dim);
 
         fSpace = dSet->getSpace();
-        offset[0] = rowXPos;
+        offset[0] = rowXPos[yPos];
         offset[1] = yPos;
         fSpace.selectHyperslab(H5S_SELECT_SET, dim, offset);
 
@@ -565,6 +589,8 @@ int HDF5RecordingData::writeDataRow(int yPos, int xDataSize, HDF5FileBase::DataT
 
 
         dSet->write(data,nativeType,mSpace,fSpace);
+
+        rowXPos.set(yPos,rowXPos[yPos] + xDataSize);
     }
     catch (DataSetIException error)
     {
@@ -581,6 +607,12 @@ int HDF5RecordingData::writeDataRow(int yPos, int xDataSize, HDF5FileBase::DataT
     return 0;
 }
 
+void HDF5RecordingData::getRowXPositions(Array<uint32>& rows)
+{
+    rows.clear();
+    rows.addArray(rowXPos);
+}
+
 //KWD File
 
 KWDFile::KWDFile(int processorNumber, String basename) : HDF5FileBase()
@@ -610,6 +642,8 @@ void KWDFile::startNewRecording(int recordingNumber, int nChannels, HDF5Recordin
 {
     this->recordingNumber = recordingNumber;
     this->nChannels = nChannels;
+    this->multiSample = info->multiSample;
+    uint8 mSample = info->multiSample ? 1 : 0;
 
     String recordPath = String("/recordings/")+String(recordingNumber);
     CHECK_ERROR(createGroup(recordPath));
@@ -618,8 +652,10 @@ void KWDFile::startNewRecording(int recordingNumber, int nChannels, HDF5Recordin
     //	CHECK_ERROR(setAttribute(U32,&(info->start_sample),recordPath,String("start_sample")));
     CHECK_ERROR(setAttribute(F32,&(info->sample_rate),recordPath,String("sample_rate")));
     CHECK_ERROR(setAttribute(U32,&(info->bit_depth),recordPath,String("bit_depth")));
-	CHECK_ERROR(createGroup(recordPath+"/application_data"));
-	CHECK_ERROR(setAttributeArray(F32,info->bitVolts.getRawDataPointer(),info->bitVolts.size(),recordPath+"/application_data",String("channel_bit_volts")));
+    CHECK_ERROR(createGroup(recordPath+"/application_data"));
+    CHECK_ERROR(setAttributeArray(F32,info->bitVolts.getRawDataPointer(),info->bitVolts.size(),recordPath+"/application_data",String("channel_bit_volts")));
+    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;
@@ -628,6 +664,11 @@ void KWDFile::startNewRecording(int recordingNumber, int nChannels, HDF5Recordin
 
 void KWDFile::stopRecording()
 {
+    Array<uint32> samples;
+    String path = String("/recordings/")+String(recordingNumber)+String("/data");
+    recdata->getRowXPositions(samples);
+
+    CHECK_ERROR(setAttributeArray(U32,samples.getRawDataPointer(),samples.size(),path,"valid_samples"));
     //ScopedPointer does the deletion and destructors the closings
     recdata = nullptr;
 }
@@ -649,7 +690,6 @@ void KWDFile::writeRowData(int16* data, int nSamples)
 {
     if (curChan >= nChannels)
     {
-        CHECK_ERROR(recdata->prepareDataBlock(nSamples));
         curChan=0;
     }
     CHECK_ERROR(recdata->writeDataRow(curChan,nSamples,I16,data));
@@ -704,7 +744,7 @@ int KWIKFile::createFileStructure()
         if (!dSet) return -1;
         dSet = createDataSet(U8,0,EVENT_CHUNK_SIZE,path + "/nodeID");
         if (!dSet) return -1;
-		dSet = createDataSet(eventTypes[i],0,EVENT_CHUNK_SIZE,path + "/" + eventDataNames[i]);
+        dSet = createDataSet(eventTypes[i],0,EVENT_CHUNK_SIZE,path + "/" + eventDataNames[i]);
         if (!dSet) return -1;
     }
     if (setAttribute(U16,(void*)&ver,"/","kwik_version")) return -1;
@@ -745,7 +785,7 @@ void KWIKFile::startNewRecording(int recordingNumber, HDF5RecordingInfo* info)
         if (!dSet)
             std::cerr << "Error loading event node ID dataset for type " << i << std::endl;
         nodeID.add(dSet);
-		dSet = getDataSet(path + "/user_data/" + eventDataNames[i]);
+        dSet = getDataSet(path + "/user_data/" + eventDataNames[i]);
         if (!dSet)
             std::cerr << "Error loading event channel dataset for type " << i << std::endl;
         eventData.add(dSet);
@@ -757,8 +797,8 @@ void KWIKFile::stopRecording()
     timeStamps.clear();
     recordings.clear();
     eventID.clear();
-	nodeID.clear();
-	eventData.clear();
+    nodeID.clear();
+    eventData.clear();
 }
 
 void KWIKFile::writeEvent(int type, uint8 id, uint8 processor, void* data, uint64 timestamp)
@@ -772,7 +812,7 @@ void KWIKFile::writeEvent(int type, uint8 id, uint8 processor, void* data, uint6
     CHECK_ERROR(recordings[type]->writeDataBlock(1,I32,&recordingNumber));
     CHECK_ERROR(eventID[type]->writeDataBlock(1,U8,&id));
     CHECK_ERROR(nodeID[type]->writeDataBlock(1,U8,&processor));
-	CHECK_ERROR(eventData[type]->writeDataBlock(1,eventTypes[type],data));
+    CHECK_ERROR(eventData[type]->writeDataBlock(1,eventTypes[type],data));
 }
 
 void KWIKFile::addKwdFile(String filename)
@@ -785,8 +825,8 @@ void KWIKFile::addKwdFile(String filename)
 void KWIKFile::addEventType(String name, DataTypes type, String dataName)
 {
     eventNames.add(name);
-	eventTypes.add(type);
-	eventDataNames.add(dataName);
+    eventTypes.add(type);
+    eventDataNames.add(dataName);
 }
 
 //KWX File
diff --git a/Source/Processors/RecordNode/HDF5FileFormat.h b/Source/Processors/RecordNode/HDF5FileFormat.h
index c228647ef344a5565f75474ee3229daed6e79a5c..a29c019da74a179c522e22cecf3ad3584ca7a128 100644
--- a/Source/Processors/RecordNode/HDF5FileFormat.h
+++ b/Source/Processors/RecordNode/HDF5FileFormat.h
@@ -41,7 +41,9 @@ struct HDF5RecordingInfo
     uint32 start_sample;
     float sample_rate;
     uint32 bit_depth;
-	Array<float> bitVolts;
+    Array<float> bitVolts;
+    Array<float> channelSampleRates;
+    bool multiSample;
 };
 
 class HDF5FileBase
@@ -65,7 +67,7 @@ protected:
 
     int setAttribute(DataTypes type, void* data, String path, String name);
     int setAttributeStr(String value, String path, String name);
-	int setAttributeArray(DataTypes type, void* data, int size, String path, String name);
+    int setAttributeArray(DataTypes type, void* data, int size, String path, String name);
     int createGroup(String path);
 
     HDF5RecordingData* getDataSet(String path);
@@ -97,19 +99,19 @@ public:
     int writeDataBlock(int xDataSize, HDF5FileBase::DataTypes type, void* data);
     int writeDataBlock(int xDataSize, int yDataSize, HDF5FileBase::DataTypes type, void* data);
 
-    int prepareDataBlock(int xDataSize);
     int writeDataRow(int yPos, int xDataSize, HDF5FileBase::DataTypes type, void* data);
 
+    void getRowXPositions(Array<uint32>& rows);
+
 private:
     int xPos;
     int xChunkSize;
     int size[3];
     int dimension;
-    int rowXPos;
-    int rowDataSize;
+    Array<uint32> rowXPos;
     ScopedPointer<H5::DataSet> dSet;
 
-	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(HDF5RecordingData);
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(HDF5RecordingData);
 };
 
 class KWDFile : public HDF5FileBase
@@ -133,9 +135,10 @@ private:
     int nChannels;
     int curChan;
     String filename;
+    bool multiSample;
     ScopedPointer<HDF5RecordingData> recdata;
 
-	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(KWDFile);
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(KWDFile);
 };
 
 class KWIKFile : public HDF5FileBase
@@ -164,11 +167,11 @@ private:
     OwnedArray<HDF5RecordingData> nodeID;
     OwnedArray<HDF5RecordingData> eventData;
     Array<String> eventNames;
-	Array<DataTypes> eventTypes;
-	Array<String> eventDataNames;
+    Array<DataTypes> eventTypes;
+    Array<String> eventDataNames;
     int kwdIndex;
 
-	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(KWIKFile);
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(KWIKFile);
 };
 
 class KWXFile : public HDF5FileBase
@@ -199,7 +202,7 @@ private:
     int numElectrodes;
     int16* transformVector;
 
-	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(KWXFile);
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(KWXFile);
 };
 
 #endif  // HDF5FILEFORMAT_H_INCLUDED
diff --git a/Source/Processors/RecordNode/HDF5Recording.cpp b/Source/Processors/RecordNode/HDF5Recording.cpp
index cbbf37700ec6a80eb134358f44f08d68ab3902a2..4a4938553a3fb728c4f1bf5db58b56fe4e72ae7d 100644
--- a/Source/Processors/RecordNode/HDF5Recording.cpp
+++ b/Source/Processors/RecordNode/HDF5Recording.cpp
@@ -26,7 +26,7 @@
 
 HDF5Recording::HDF5Recording() : processorIndex(-1)
 {
-    timestamp = 0;
+    //timestamp = 0;
     scaledBuffer = new float[MAX_BUFFER_SIZE];
     intBuffer = new int16[MAX_BUFFER_SIZE];
 }
@@ -39,22 +39,24 @@ HDF5Recording::~HDF5Recording()
 
 String HDF5Recording::getEngineID()
 {
-	return "KWIK";
+    return "KWIK";
 }
 
-void HDF5Recording::updateTimeStamp(int64 timestamp)
-{
-    this->timestamp = timestamp;
-}
+// void HDF5Recording::updateTimeStamp(int64 timestamp)
+// {
+//     this->timestamp = timestamp;
+// }
 
 void HDF5Recording::registerProcessor(GenericProcessor* proc)
 {
     HDF5RecordingInfo* info = new HDF5RecordingInfo();
     info->sample_rate = proc->getSampleRate();
     info->bit_depth = 16;
+    info->multiSample = false;
     infoArray.add(info);
     fileArray.add(new KWDFile());
-	bitVoltsArray.add(new Array<float>);
+    bitVoltsArray.add(new Array<float>);
+    sampleRatesArray.add(new Array<float>);
     processorIndex++;
 }
 
@@ -62,7 +64,8 @@ void HDF5Recording::resetChannels()
 {
     processorIndex = -1;
     fileArray.clear();
-	bitVoltsArray.clear();
+    bitVoltsArray.clear();
+    sampleRatesArray.clear();
     processorMap.clear();
     infoArray.clear();
     if (spikesFile)
@@ -103,7 +106,12 @@ void HDF5Recording::openFiles(File rootFolder,  int experimentNumber, int record
                 fileArray[index]->initFile(getChannel(i)->nodeId,basepath);
                 fileArray[index]->open();
             }
-			bitVoltsArray[index]->add(getChannel(i)->bitVolts);
+            bitVoltsArray[index]->add(getChannel(i)->bitVolts);
+            sampleRatesArray[index]->add(getChannel(i)->sampleRate);
+            if (getChannel(i)->sampleRate != infoArray[index]->sample_rate)
+            {
+                infoArray[index]->multiSample = true;
+            }
         }
     }
     for (int i = 0; i < fileArray.size(); i++)
@@ -116,9 +124,11 @@ void HDF5Recording::openFiles(File rootFolder,  int experimentNumber, int record
             infoArray[i]->name = String("Open-Ephys Recording #") + String(recordingNumber);
             infoArray[i]->start_time = timestamp;
             infoArray[i]->start_sample = 0;
-			infoArray[i]->bitVolts.clear();
-			infoArray[i]->bitVolts.addArray(*bitVoltsArray[i]);
-			fileArray[i]->startNewRecording(recordingNumber,bitVoltsArray[i]->size(),infoArray[i]);
+            infoArray[i]->bitVolts.clear();
+            infoArray[i]->bitVolts.addArray(*bitVoltsArray[i]);
+            infoArray[i]->channelSampleRates.clear();
+            infoArray[i]->channelSampleRates.addArray(*sampleRatesArray[i]);
+            fileArray[i]->startNewRecording(recordingNumber,bitVoltsArray[i]->size(),infoArray[i]);
         }
     }
 }
@@ -133,17 +143,21 @@ void HDF5Recording::closeFiles()
     {
         fileArray[i]->stopRecording();
         fileArray[i]->close();
-		bitVoltsArray[i]->clear();
+        bitVoltsArray[i]->clear();
     }
 }
 
-void HDF5Recording::writeData(AudioSampleBuffer& buffer, int nSamples)
+void HDF5Recording::writeData(AudioSampleBuffer& buffer)
 {
     int index;
     for (int i = 0; i < buffer.getNumChannels(); i++)
     {
         if (getChannel(i)->getRecordState())
         {
+
+            int sourceNodeId = getChannel(i)->sourceNodeId;
+            int nSamples = (*numSamples)[sourceNodeId];
+
             double multFactor = 1/(float(0x7fff) * getChannel(i)->bitVolts);
             int index = processorMap[getChannel(i)->recordIndex];
             FloatVectorOperations::copyWithMultiply(scaledBuffer,buffer.getReadPointer(i,0),multFactor,nSamples);
@@ -156,10 +170,10 @@ void HDF5Recording::writeData(AudioSampleBuffer& buffer, int nSamples)
 void HDF5Recording::writeEvent(int eventType, MidiMessage& event, int samplePosition)
 {
     const uint8* dataptr = event.getRawData();
-	if (eventType == GenericProcessor::TTL)
-		mainFile->writeEvent(0,*(dataptr+2),*(dataptr+1),(void*)(dataptr+3),timestamp+samplePosition);
-	else if (eventType == GenericProcessor::MESSAGE)
-		mainFile->writeEvent(1,*(dataptr+2),*(dataptr+1),(void*)(dataptr+4),timestamp+samplePosition);
+    if (eventType == GenericProcessor::TTL)
+        mainFile->writeEvent(0,*(dataptr+2),*(dataptr+1),(void*)(dataptr+3),timestamp+samplePosition);
+    else if (eventType == GenericProcessor::MESSAGE)
+        mainFile->writeEvent(1,*(dataptr+2),*(dataptr+1),(void*)(dataptr+4),timestamp+samplePosition);
 }
 
 void HDF5Recording::addSpikeElectrode(int index, SpikeRecordInfo* elec)
@@ -174,13 +188,13 @@ void HDF5Recording::writeSpike(const SpikeObject& spike, int electrodeIndex)
 void HDF5Recording::startAcquisition()
 {
     mainFile = new KWIKFile();
-	mainFile->addEventType("TTL",HDF5FileBase::U8,"event_channels");
-	mainFile->addEventType("Messages",HDF5FileBase::STR,"Text");
+    mainFile->addEventType("TTL",HDF5FileBase::U8,"event_channels");
+    mainFile->addEventType("Messages",HDF5FileBase::STR,"Text");
     spikesFile = new KWXFile();
 }
 
 RecordEngineManager* HDF5Recording::getEngineManager()
 {
-	RecordEngineManager* man = new RecordEngineManager("KWIK","Kwik",nullptr);
-	return man;
+    RecordEngineManager* man = new RecordEngineManager("KWIK","Kwik",nullptr);
+    return man;
 }
\ No newline at end of file
diff --git a/Source/Processors/RecordNode/HDF5Recording.h b/Source/Processors/RecordNode/HDF5Recording.h
index 9be5e3942929b93014826b0f7b6f1a474075e5d7..9b9466dd7ac63230866fa8c3f5af2091df40ca2b 100644
--- a/Source/Processors/RecordNode/HDF5Recording.h
+++ b/Source/Processors/RecordNode/HDF5Recording.h
@@ -32,26 +32,27 @@ class HDF5Recording : public RecordEngine
 public:
     HDF5Recording();
     ~HDF5Recording();
-	String getEngineID();
+    String getEngineID();
     void openFiles(File rootFolder, int experimentNumber, int recordingNumber);
     void closeFiles();
-    void writeData(AudioSampleBuffer& buffer, int nSamples);
+    void writeData(AudioSampleBuffer& buffer);
     void writeEvent(int eventType, MidiMessage& event, int samplePosition);
     void addChannel(int index, Channel* chan);
     void addSpikeElectrode(int index, SpikeRecordInfo* elec);
     void writeSpike(const SpikeObject& spike, int electrodeIndex);
     void registerProcessor(GenericProcessor* processor);
     void resetChannels();
-    void updateTimeStamp(int64 timestamp);
+    //oid updateTimeStamp(int64 timestamp);
     void startAcquisition();
 
-	static RecordEngineManager* getEngineManager();
+    static RecordEngineManager* getEngineManager();
 private:
 
     int processorIndex;
 
     Array<int> processorMap;
     OwnedArray<Array<float>> bitVoltsArray;
+    OwnedArray<Array<float>> sampleRatesArray;
     OwnedArray<KWDFile> fileArray;
     OwnedArray<HDF5RecordingInfo> infoArray;
     ScopedPointer<KWIKFile> mainFile;
@@ -60,7 +61,7 @@ private:
     int16* intBuffer;
     int64 timestamp;
 
-	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(HDF5Recording);
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(HDF5Recording);
 };
 
 
diff --git a/Source/Processors/RecordNode/OriginalRecording.cpp b/Source/Processors/RecordNode/OriginalRecording.cpp
index c03b27491e1d451d0249ea9ced5ac20e30a8c360..d0d3eb0a945dad1f1333405eb4c3b2f0111015f6 100644
--- a/Source/Processors/RecordNode/OriginalRecording.cpp
+++ b/Source/Processors/RecordNode/OriginalRecording.cpp
@@ -25,8 +25,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "../../Audio/AudioComponent.h"
 
 OriginalRecording::OriginalRecording() : separateFiles(false),
-    blockIndex(0), recordingNumber(0), experimentNumber(0),  zeroBuffer(1, 50000), 
-	eventFile(nullptr), messageFile(nullptr), lastProcId(0)
+    recordingNumber(0), experimentNumber(0),  zeroBuffer(1, 50000),
+    eventFile(nullptr), messageFile(nullptr), lastProcId(0)
 {
     continuousDataIntegerBuffer = new int16[10000];
     continuousDataFloatBuffer = new float[10000];
@@ -66,6 +66,8 @@ void OriginalRecording::addChannel(int index, Channel* chan)
 {
     //Just populate the file array with null so we can address it by index afterwards
     fileArray.add(nullptr);
+    blockIndex.add(0);
+    samplesSinceLastTimestamp.add(0);
 }
 
 void OriginalRecording::addSpikeElectrode(int index, SpikeRecordInfo* elec)
@@ -77,7 +79,9 @@ void OriginalRecording::resetChannels()
 {
     fileArray.clear();
     spikeFileArray.clear();
-	processorArray.clear();
+    blockIndex.clear();
+    processorArray.clear();
+    samplesSinceLastTimestamp.clear();
 }
 
 void OriginalRecording::openFiles(File rootFolder, int experimentNumber, int recordingNumber)
@@ -85,24 +89,26 @@ void OriginalRecording::openFiles(File rootFolder, int experimentNumber, int rec
     this->recordingNumber = recordingNumber;
     this->experimentNumber = experimentNumber;
 
-	processorArray.clear();
-	lastProcId = 0;
+    processorArray.clear();
+    lastProcId = 0;
 
     openFile(rootFolder,nullptr);
     openMessageFile(rootFolder);
+
     for (int i = 0; i < fileArray.size(); i++)
     {
         if (getChannel(i)->getRecordState())
         {
             openFile(rootFolder,getChannel(i));
+            blockIndex.set(i,0);
+            samplesSinceLastTimestamp.set(i,0);
         }
+
     }
     for (int i = 0; i < spikeFileArray.size(); i++)
     {
         openSpikeFile(rootFolder,getSpikeElectrode(i));
     }
-    blockIndex = 0;
-	startTimestamp = timestamp;
 }
 
 void OriginalRecording::openFile(File rootFolder, Channel* ch)
@@ -110,9 +116,9 @@ void OriginalRecording::openFile(File rootFolder, Channel* ch)
     FILE* chFile;
     bool isEvent;
     String fullPath(rootFolder.getFullPathName() + rootFolder.separatorString);
-	String fileName;
+    String fileName;
 
-	recordPath = fullPath;
+    recordPath = fullPath;
 
     isEvent = (ch == nullptr) ? true : false;
     if (isEvent)
@@ -127,8 +133,8 @@ void OriginalRecording::openFile(File rootFolder, Channel* ch)
         fileName += getFileName(ch);
     }
 
-	fullPath += fileName;
-	std::cout << "OPENING FILE: " << fullPath << std::endl;
+    fullPath += fileName;
+    std::cout << "OPENING FILE: " << fullPath << std::endl;
 
     File f = File(fullPath);
 
@@ -151,36 +157,36 @@ void OriginalRecording::openFile(File rootFolder, Channel* ch)
 
         std::cout << "Wrote header." << std::endl;
 
-        std::cout << "Block index: " << blockIndex << std::endl;
+        // std::cout << "Block index: " << blockIndex << std::endl;
 
     }
     else
     {
         std::cout << "File already exists, just opening." << std::endl;
-		fseek(chFile, 0, SEEK_END );
+        fseek(chFile, 0, SEEK_END);
     }
 
     if (isEvent)
         eventFile = chFile;
     else
-	{
+    {
         fileArray.set(ch->recordIndex,chFile);
-		if (ch->nodeId != lastProcId)
-		{
-			lastProcId = ch->nodeId;
-			ProcInfo* p = new ProcInfo();
-			p->id = ch->nodeId;
-			p->sampleRate = ch->sampleRate;
-			processorArray.add(p);
-		}
-		ChannelInfo* c = new ChannelInfo();
-		c->filename = fileName;
-		c->name = ch->name;
-		c->startPos = ftell(chFile);
-		c->bitVolts = ch->bitVolts;
-		processorArray.getLast()->channels.add(c);
-	}
-	diskWriteLock.exit();
+        if (ch->nodeId != lastProcId)
+        {
+            lastProcId = ch->nodeId;
+            ProcInfo* p = new ProcInfo();
+            p->id = ch->nodeId;
+            p->sampleRate = ch->sampleRate;
+            processorArray.add(p);
+        }
+        ChannelInfo* c = new ChannelInfo();
+        c->filename = fileName;
+        c->name = ch->name;
+        c->startPos = ftell(chFile);
+        c->bitVolts = ch->bitVolts;
+        processorArray.getLast()->channels.add(c);
+    }
+    diskWriteLock.exit();
 
 }
 
@@ -269,7 +275,7 @@ String OriginalRecording::generateHeader(Channel* ch)
 
     String header = "header.format = 'Open Ephys Data Format'; \n";
 
-	header += "header.version = "+ String(VERSION_STRING) +"; \n";
+    header += "header.version = "+ String(VERSION_STRING) +"; \n";
     header += "header.header_bytes = ";
     header += String(HEADER_SIZE);
     header += ";\n";
@@ -333,7 +339,7 @@ String OriginalRecording::generateSpikeHeader(SpikeRecordInfo* elec)
     header += String(HEADER_SIZE);
     header += ";\n";
 
-    header += "header.description = 'Each record contains 1 uint8 eventType, 1 uint64 timestamp, 1 uint16 electrodeID, 1 uint16 numChannels (n), 1 uint16 numSamples (m), n*m uint16 samples, n uint16 channelGains, n uint16 thresholds, and 1 uint16 recordingNumber'; \n";
+    header += "header.description = 'Each record contains 1 uint8 eventType, 1 int64 timestamp, 1 uint16 electrodeID, 1 uint16 numChannels (n), 1 uint16 numSamples (m), n*m uint16 samples, n uint16 channelGains, n uint16 thresholds, and 1 uint16 recordingNumber'; \n";
 
     header += "header.date_created = '";
     header += generateDateString();
@@ -371,8 +377,9 @@ void OriginalRecording::writeMessage(MidiMessage& event, int samplePosition)
     if (messageFile == nullptr)
         return;
     uint64 samplePos = (uint64) samplePosition;
+    uint8 sourceNodeId = event.getNoteNumber();
 
-    int64 eventTimestamp = timestamp + samplePos;
+    int64 eventTimestamp = (*timestamps)[sourceNodeId] + samplePos;
 
     int msgLength = event.getRawDataSize() - 5;
     const char* dataptr = (const char*)event.getRawData() + 4;
@@ -400,7 +407,9 @@ void OriginalRecording::writeTTLEvent(MidiMessage& event, int samplePosition)
 
     uint64 samplePos = (uint64) samplePosition;
 
-    int64 eventTimestamp = timestamp + samplePos; // add the sample position to the buffer timestamp
+    uint8 sourceNodeId = event.getNoteNumber();
+
+    int64 eventTimestamp = (*timestamps)[sourceNodeId] + samplePos; // add the sample position to the buffer timestamp
 
     diskWriteLock.enter();
 
@@ -426,63 +435,60 @@ void OriginalRecording::writeTTLEvent(MidiMessage& event, int samplePosition)
     diskWriteLock.exit();
 }
 
-void OriginalRecording::writeData(AudioSampleBuffer& buffer, int nSamples)
+void OriginalRecording::writeData(AudioSampleBuffer& buffer)
 {
-    int samplesWritten = 0;
 
-    while (samplesWritten < nSamples) // there are still unwritten samples in the buffer
+    for (int i = 0; i < buffer.getNumChannels(); i++)
     {
+        if (getChannel(i)->getRecordState())
+        {
+            int samplesWritten = 0;
 
-        int numSamplesToWrite = nSamples - samplesWritten; // samples remaining in the buffer
+            int sourceNodeId = getChannel(i)->sourceNodeId;
 
-        if (blockIndex + numSamplesToWrite < BLOCK_LENGTH) // we still have space in this block
-        {
-            for (int i = 0; i < buffer.getNumChannels(); i++)
+            samplesSinceLastTimestamp.set(i,0);
+
+            int nSamples = (*numSamples)[sourceNodeId];
+
+            while (samplesWritten < nSamples) // there are still unwritten samples in this buffer
             {
+                int numSamplesToWrite = nSamples - samplesWritten;
 
-                if (getChannel(i)->getRecordState())
+                if (blockIndex[i] + numSamplesToWrite < BLOCK_LENGTH) // we still have space in this block
                 {
+
                     // write buffer to disk!
                     writeContinuousBuffer(buffer.getReadPointer(i,samplesWritten),
                                           numSamplesToWrite,
                                           i);
 
+                    //timestamp += numSamplesToWrite;
+                    samplesSinceLastTimestamp.set(i, samplesSinceLastTimestamp[i] + numSamplesToWrite);
+                    blockIndex.set(i, blockIndex[i] + numSamplesToWrite);
+                    samplesWritten += numSamplesToWrite;
 
                 }
-            }
-
-            // update our variables
-            samplesWritten += numSamplesToWrite;
-            timestamp += numSamplesToWrite;
-            blockIndex += numSamplesToWrite;
-
-        }
-        else // there's not enough space left in this block for all remaining samples
-        {
-
-            numSamplesToWrite = BLOCK_LENGTH - blockIndex;
+                else   // there's not enough space left in this block for all remaining samples
+                {
 
-            for (int i = 0; i < buffer.getNumChannels(); i++)
-            {
+                    numSamplesToWrite = BLOCK_LENGTH - blockIndex[i];
 
-                if (getChannel(i)->getRecordState())
-                {
                     // write buffer to disk!
                     writeContinuousBuffer(buffer.getReadPointer(i,samplesWritten),
                                           numSamplesToWrite,
                                           i);
 
-                    //std::cout << "Record channel " << i << std::endl;
+                    // update our variables
+                    samplesWritten += numSamplesToWrite;
+                    //timestamp += numSamplesToWrite;
+                    samplesSinceLastTimestamp.set(i, samplesSinceLastTimestamp[i] + numSamplesToWrite);
+                    blockIndex.set(i,0); // back to the beginning of the block
                 }
             }
 
-            // update our variables
-            samplesWritten += numSamplesToWrite;
-            timestamp += numSamplesToWrite;
-            blockIndex = 0; // back to the beginning of the block
-
         }
     }
+
 }
 
 void OriginalRecording::writeContinuousBuffer(const float* data, int nSamples, int channel)
@@ -493,15 +499,16 @@ void OriginalRecording::writeContinuousBuffer(const float* data, int nSamples, i
 
     // scale the data back into the range of int16
     float scaleFactor =  float(0x7fff) * getChannel(channel)->bitVolts;
+
     for (int n = 0; n < nSamples; n++)
     {
         *(continuousDataFloatBuffer+n) = *(data+n) / scaleFactor;
     }
     AudioDataConverters::convertFloatToInt16BE(continuousDataFloatBuffer, continuousDataIntegerBuffer, nSamples);
 
-    if (blockIndex == 0)
+    if (blockIndex[channel] == 0)
     {
-        writeTimestampAndSampleCount(fileArray[channel]);
+        writeTimestampAndSampleCount(fileArray[channel], channel);
     }
 
     diskWriteLock.enter();
@@ -511,23 +518,29 @@ void OriginalRecording::writeContinuousBuffer(const float* data, int nSamples, i
                           nSamples,                        // count
                           fileArray[channel]); // ptr to FILE object
 
+    //std::cout << channel << " : " << nSamples << " : " << count << std::endl;
+
     jassert(count == nSamples); // make sure all the data was written
 
     diskWriteLock.exit();
 
-    if (blockIndex + nSamples == BLOCK_LENGTH)
+    if (blockIndex[channel] + nSamples == BLOCK_LENGTH)
     {
         writeRecordMarker(fileArray[channel]);
     }
 }
 
-void OriginalRecording::writeTimestampAndSampleCount(FILE* file)
+void OriginalRecording::writeTimestampAndSampleCount(FILE* file, int channel)
 {
     diskWriteLock.enter();
 
     uint16 samps = BLOCK_LENGTH;
 
-    fwrite(&timestamp,                       // ptr
+    int sourceNodeId = getChannel(channel)->sourceNodeId;
+
+    int64 ts = (*timestamps)[sourceNodeId] + samplesSinceLastTimestamp[channel];
+
+    fwrite(&ts,                       // ptr
            8,                               // size of each element
            1,                               // count
            file); // ptr to FILE object
@@ -564,16 +577,18 @@ void OriginalRecording::closeFiles()
     {
         if (fileArray[i] != nullptr)
         {
-            if (blockIndex < BLOCK_LENGTH)
+            if (blockIndex[i] < BLOCK_LENGTH)
             {
                 // fill out the rest of the current buffer
-                writeContinuousBuffer(zeroBuffer.getReadPointer(0), BLOCK_LENGTH - blockIndex, i);
+                writeContinuousBuffer(zeroBuffer.getReadPointer(0), BLOCK_LENGTH - blockIndex[i], i);
                 diskWriteLock.enter();
                 fclose(fileArray[i]);
                 fileArray.set(i,nullptr);
                 diskWriteLock.exit();
             }
         }
+
+        blockIndex.set(i,0);
     }
     for (int i = 0; i < spikeFileArray.size(); i++)
     {
@@ -599,15 +614,16 @@ void OriginalRecording::closeFiles()
         messageFile = nullptr;
         diskWriteLock.exit();
     }
-	writeXml();
-    blockIndex = 0;
-}
 
-void OriginalRecording::updateTimeStamp(int64 timestamp)
-{
-    this->timestamp = timestamp;
+    writeXml();
+
 }
 
+// void OriginalRecording::updateTimeStamp(int64 timestamp)
+// {
+//     this->timestamp = timestamp;
+// }
+
 void OriginalRecording::writeSpike(const SpikeObject& spike, int electrodeIndex)
 {
     uint8_t spikeBuffer[MAX_SPIKE_BUFFER_LEN];
@@ -649,46 +665,46 @@ void OriginalRecording::writeSpike(const SpikeObject& spike, int electrodeIndex)
 
 void OriginalRecording::writeXml()
 {
-	String name = recordPath + "Continuous_Data";
-	if (experimentNumber > 1)
-	{
-		name += "_";
-		name += String(experimentNumber);
-	}
-	name += ".openephys";
-
-	File file(name);
-	XmlDocument doc(file);
-	ScopedPointer<XmlElement> xml = doc.getDocumentElement();
-	if ( !xml || ! xml->hasTagName("EXPERIMENT"))
-	{
-		xml = new XmlElement("EXPERIMENT");
-		xml->setAttribute("version",VERSION);
-		xml->setAttribute("number",experimentNumber);
-		xml->setAttribute("separatefiles",separateFiles);
-	}
-	XmlElement* rec = new XmlElement("RECORDING");
-	rec->setAttribute("number",recordingNumber);
-	rec->setAttribute("length",(double)(timestamp-startTimestamp));
-	for (int i = 0; i < processorArray.size(); i++)
-	{
-		XmlElement* proc = new XmlElement("PROCESSOR");
-		proc->setAttribute("id",processorArray[i]->id);
-		rec->setAttribute("samplerate",processorArray[i]->sampleRate);
-		for (int j = 0; j < processorArray[i]->channels.size(); j++)
-		{
-			ChannelInfo* c = processorArray[i]->channels[j];
-			XmlElement* chan = new XmlElement("CHANNEL");
-			chan->setAttribute("name",c->name);
-			chan->setAttribute("bitVolts",c->bitVolts);
-			chan->setAttribute("filename",c->filename);
-			chan->setAttribute("position",(double)(c->startPos)); //As long as the file doesnt exceed 2^53 bytes, this will have integer precission. Better than limiting to 32bits.
-			proc->addChildElement(chan);
-		}
-		rec->addChildElement(proc);
-	}
-	xml->addChildElement(rec);
-	xml->writeToFile(file,String::empty);
+    String name = recordPath + "Continuous_Data";
+    if (experimentNumber > 1)
+    {
+        name += "_";
+        name += String(experimentNumber);
+    }
+    name += ".openephys";
+
+    File file(name);
+    XmlDocument doc(file);
+    ScopedPointer<XmlElement> xml = doc.getDocumentElement();
+    if (!xml || ! xml->hasTagName("EXPERIMENT"))
+    {
+        xml = new XmlElement("EXPERIMENT");
+        xml->setAttribute("version",VERSION);
+        xml->setAttribute("number",experimentNumber);
+        xml->setAttribute("separatefiles",separateFiles);
+    }
+    XmlElement* rec = new XmlElement("RECORDING");
+    rec->setAttribute("number",recordingNumber);
+    //rec->setAttribute("length",(double)(timestamp-startTimestamp));
+    for (int i = 0; i < processorArray.size(); i++)
+    {
+        XmlElement* proc = new XmlElement("PROCESSOR");
+        proc->setAttribute("id",processorArray[i]->id);
+        rec->setAttribute("samplerate",processorArray[i]->sampleRate);
+        for (int j = 0; j < processorArray[i]->channels.size(); j++)
+        {
+            ChannelInfo* c = processorArray[i]->channels[j];
+            XmlElement* chan = new XmlElement("CHANNEL");
+            chan->setAttribute("name",c->name);
+            chan->setAttribute("bitVolts",c->bitVolts);
+            chan->setAttribute("filename",c->filename);
+            chan->setAttribute("position",(double)(c->startPos)); //As long as the file doesnt exceed 2^53 bytes, this will have integer precission. Better than limiting to 32bits.
+            proc->addChildElement(chan);
+        }
+        rec->addChildElement(proc);
+    }
+    xml->addChildElement(rec);
+    xml->writeToFile(file,String::empty);
 }
 
 void OriginalRecording::setParameter(EngineParameter& parameter)
diff --git a/Source/Processors/RecordNode/OriginalRecording.h b/Source/Processors/RecordNode/OriginalRecording.h
index f269d06634ea174a9b21da166bfcfae28de19a9c..5a1447167d4f763e3c84f46c46120ff30607e49c 100644
--- a/Source/Processors/RecordNode/OriginalRecording.h
+++ b/Source/Processors/RecordNode/OriginalRecording.h
@@ -28,6 +28,7 @@
 
 #include "RecordEngine.h"
 #include <stdio.h>
+#include <map>
 
 #define HEADER_SIZE 1024
 #define BLOCK_LENGTH 1024
@@ -48,11 +49,11 @@ public:
     String getEngineID();
     void openFiles(File rootFolder, int experimentNumber, int recordingNumber);
     void closeFiles();
-    void writeData(AudioSampleBuffer& buffer, int nSamples);
+    void writeData(AudioSampleBuffer& buffer);
     void writeEvent(int eventType, MidiMessage& event, int samplePosition);
     void addChannel(int index, Channel* chan);
     void resetChannels();
-    void updateTimeStamp(int64 timestamp);
+    //void updateTimeStamp(int64 timestamp);
     void addSpikeElectrode(int index, SpikeRecordInfo* elec);
     void writeSpike(const SpikeObject& spike, int electrodeIndex);
 
@@ -63,7 +64,7 @@ private:
     void openFile(File rootFolder, Channel* ch);
     String generateHeader(Channel* ch);
     void writeContinuousBuffer(const float* data, int nSamples, int channel);
-    void writeTimestampAndSampleCount(FILE* file);
+    void writeTimestampAndSampleCount(FILE* file, int channel);
     void writeRecordMarker(FILE* file);
 
     void openSpikeFile(File rootFolder, SpikeRecordInfo* elec);
@@ -73,10 +74,11 @@ private:
     void writeTTLEvent(MidiMessage& event, int samplePosition);
     void writeMessage(MidiMessage& event, int samplePosition);
 
-	void writeXml();
+    void writeXml();
 
     bool separateFiles;
-    int blockIndex;
+    Array<int> blockIndex;
+    Array<int> samplesSinceLastTimestamp;
     int recordingNumber;
     int experimentNumber;
 
@@ -94,31 +96,32 @@ private:
     char* recordMarker;
 
     AudioSampleBuffer zeroBuffer;
-    int64 timestamp;
 
     FILE* eventFile;
     FILE* messageFile;
     Array<FILE*> fileArray;
     Array<FILE*> spikeFileArray;
-	
+
     CriticalSection diskWriteLock;
 
-	struct ChannelInfo {
-		String name;
-		String filename;
-		float bitVolts;
-		long int startPos;
-	};
-	struct ProcInfo {
-		int id;
-		float sampleRate;
-		OwnedArray<ChannelInfo> channels;
-	};
-
-	OwnedArray<ProcInfo> processorArray;
-	int lastProcId;
-	String recordPath;
-	int64 startTimestamp;
+    struct ChannelInfo
+    {
+        String name;
+        String filename;
+        float bitVolts;
+        long int startPos;
+    };
+    struct ProcInfo
+    {
+        int id;
+        float sampleRate;
+        OwnedArray<ChannelInfo> channels;
+    };
+
+    OwnedArray<ProcInfo> processorArray;
+    int lastProcId;
+    String recordPath;
+    int64 startTimestamp;
 
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(OriginalRecording);
 };
diff --git a/Source/Processors/RecordNode/RecordEngine.cpp b/Source/Processors/RecordNode/RecordEngine.cpp
index 3d187092502ecfb2dc987d5ff8c55b1147424de1..d6cc769e26e5ef3a0a3501bfa7bac3ef37ceddf3 100644
--- a/Source/Processors/RecordNode/RecordEngine.cpp
+++ b/Source/Processors/RecordNode/RecordEngine.cpp
@@ -57,7 +57,16 @@ SpikeRecordInfo* RecordEngine::getSpikeElectrode(int index)
     return getProcessorGraph()->getRecordNode()->getSpikeElectrode(index);
 }
 
-void RecordEngine::updateTimeStamp(int64 timestamp) {}
+void RecordEngine::updateTimestamps(std::map<uint8, int64>* ts)
+{
+    timestamps = ts;
+}
+
+void RecordEngine::updateNumSamples(std::map<uint8, int>* ns)
+{
+    numSamples = ns;
+}
+
 
 void RecordEngine::registerSpikeSource(GenericProcessor* processor) {}
 
diff --git a/Source/Processors/RecordNode/RecordEngine.h b/Source/Processors/RecordNode/RecordEngine.h
index 09ff73ceefa34f9805d0354d7d890cbc6752ed92..44d48163b229eeb3c2531db7125d1261347a23b3 100644
--- a/Source/Processors/RecordNode/RecordEngine.h
+++ b/Source/Processors/RecordNode/RecordEngine.h
@@ -29,6 +29,8 @@
 #include "../GenericProcessor/GenericProcessor.h"
 #include "../Visualization/SpikeObject.h"
 
+#include <map>
+
 //Handy macros for setParameter
 #define boolParameter(i,v) if ((parameter.id == i) && (parameter.type == EngineParameter::BOOL)) \
         v = parameter.boolParam.value
@@ -65,8 +67,8 @@ public:
     	2-registerProcessor, addChannel, registerSpikeSource, addspikeelectrode
     	3-configureEngine (which calls setParameter)
     	3-startAcquisition
-	During acquisition:
-		updateTimeStamps
+    During acquisition:
+    	updateTimeStamps
     When recording starts (in the specified order):
     	1-directoryChanged (if needed)
     	2-openFiles
@@ -91,9 +93,10 @@ public:
 
     /** Write continuous data.
     	This method gets the full data buffer, it must query getRecordState for
-    	each registered channel to determine which channels to actually write to disk
+    	each registered channel to determine which channels to actually write to disk.
+        The number of samples to write will be found in the numSamples object.
     */
-    virtual void writeData(AudioSampleBuffer& buffer, int nSamples) = 0;
+    virtual void writeData(AudioSampleBuffer& buffer) = 0;
 
     /** Write a single event to disk.
     */
@@ -127,7 +130,10 @@ public:
 
     /** Called every time a new timestamp event is received
     */
-    virtual void updateTimeStamp(int64 timestamp);
+    void updateTimestamps(std::map<uint8, int64>* timestamps);
+
+    /** Called every time a new numSamples event is received */
+    void updateNumSamples(std::map<uint8, int>* numSamples);
 
     /** Called after all channels and spike groups have been registered,
     	just before acquisition starts
@@ -158,6 +164,9 @@ protected:
     */
     String generateDateString();
 
+    std::map<uint8, int>* numSamples;
+    std::map<uint8, int64>* timestamps;
+
 private:
     RecordEngineManager* manager;
 
diff --git a/Source/Processors/RecordNode/RecordNode.cpp b/Source/Processors/RecordNode/RecordNode.cpp
index 1bc936469c6d91ba457a8bcf2953894ba9a542f9..48b283eee7c446071bb6ee376814e92e34c51551 100755
--- a/Source/Processors/RecordNode/RecordNode.cpp
+++ b/Source/Processors/RecordNode/RecordNode.cpp
@@ -48,11 +48,9 @@ RecordNode::RecordNode()
     settings.numInputs = 2048;
     settings.numOutputs = 0;
 
-    eventChannel = new Channel(this, 0);
-    eventChannel->setType(EVENT_CHANNEL);
+    eventChannel = new Channel(this, 0, EVENT_CHANNEL);
     recordingNumber = 0;
 
-
     spikeElectrodeIndex = 0;
 
     experimentNumber = 0;
@@ -412,53 +410,34 @@ float RecordNode::getFreeSpace()
 
 void RecordNode::handleEvent(int eventType, MidiMessage& event, int samplePosition)
 {
-    if (eventType == TIMESTAMP)
-    {
-        const uint8* dataptr = event.getRawData();
-
-        // // double-check buffer contents:
-        // std::cout << (int) *(dataptr + 11) << " " <<
-        //             (int) *(dataptr + 10) << " " <<
-        //             (int) *(dataptr + 9) << " " <<
-        //             (int) *(dataptr + 8) << " " <<
-        //             (int) *(dataptr + 7) << " " <<
-        //             (int) *(dataptr + 6) << " " <<
-        //             (int) *(dataptr + 5) << " " <<
-        //             (int) *(dataptr + 4) << std::endl;
-
-        memcpy(&timestamp, dataptr + 4, 8); // remember to skip first four bytes
-        EVERY_ENGINE->updateTimeStamp(timestamp);
-    }
     if (isRecording && allFilesOpened)
     {
         if ((eventType == TTL) || (eventType == MESSAGE))
         {
-            if (event.getNoteNumber() > 0) // processor ID > 0
+            if (event.getRawData()+4 > 0) // saving flag > 0 (i.e., event has not already been processed)
             {
                 EVERY_ENGINE->writeEvent(eventType, event, samplePosition);
             }
         }
-        else if (eventType == MESSAGE)
-        {
-            std::cout << "Received event!" << std::endl;
-        }
     }
-
 }
 
 void RecordNode::process(AudioSampleBuffer& buffer,
-                         MidiBuffer& events,
-                         int& nSamples)
+                         MidiBuffer& events)
 {
-	// FIRST: cycle through events -- extract the TTLs and the timestamps
+    // FIRST: cycle through events -- extract the TTLs and the timestamps
     checkForEvents(events);
+
+    //update timstamp data even if we're not recording yet
+    EVERY_ENGINE->updateTimestamps(&timestamps);
+    EVERY_ENGINE->updateNumSamples(&numSamples);
+
     if (isRecording && allFilesOpened)
     {
-
         // SECOND: write channel data
         if (channelPointers.size() > 0)
         {
-            EVERY_ENGINE->writeData(buffer,nSamples);
+            EVERY_ENGINE->writeData(buffer);
         }
 
         //  std::cout << nSamples << " " << samplesWritten << " " << blockIndex << std::endl;
diff --git a/Source/Processors/RecordNode/RecordNode.h b/Source/Processors/RecordNode/RecordNode.h
index 032db2f73c295c78b5bf9750d8cc88f8a48b7285..2ef65fb021b73fb2a00453ee6aca728498eb7665 100755
--- a/Source/Processors/RecordNode/RecordNode.h
+++ b/Source/Processors/RecordNode/RecordNode.h
@@ -60,7 +60,7 @@ public:
 
     /** Handle incoming data and decide which files and events to write to disk.
     */
-    void process(AudioSampleBuffer& buffer, MidiBuffer& eventBuffer, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& eventBuffer);
 
 
     /** Overrides implementation in GenericProcessor; used to change recording parameters
@@ -74,24 +74,24 @@ public:
     */
     void setParameter(int parameterIndex, float newValue);
 
-	/** Called by the processor graph for each processor that could record data
-	*/
+    /** Called by the processor graph for each processor that could record data
+    */
     void registerProcessor(GenericProcessor* sourceNode);
-	/** Called by the processor graph for each recordable channel
-	*/
+    /** Called by the processor graph for each recordable channel
+    */
     void addInputChannel(GenericProcessor* sourceNode, int chan);
 
     bool enable();
     bool disable();
 
     /** returns channel names and whether we record them */
-    void getChannelNamesAndRecordingStatus(StringArray &names, Array<bool> &recording);
+    void getChannelNamesAndRecordingStatus(StringArray& names, Array<bool>& recording);
 
     /** update channel name */
     void updateChannelName(int channelIndex, String newname);
 
-	/** Get channel stored in channelPointers array
-	*/
+    /** Get channel stored in channelPointers array
+    */
     Channel* getDataChannel(int index);
 
     /** Called by the ControlPanel to determine the amount of space
@@ -128,29 +128,29 @@ public:
     }
 
     void appendTrialNumber(bool);
-    
+
     void updateTrialNumber();
 
-	/** Adds a Record Engine to use
-	*/
+    /** Adds a Record Engine to use
+    */
     void registerRecordEngine(RecordEngine* engine);
 
-	/** Clears the list of active Record Engines
-	*/
-	void clearRecordEngines();
+    /** Clears the list of active Record Engines
+    */
+    void clearRecordEngines();
 
-	/** Must be called by a spike recording source on the "enable" method
-	*/
+    /** Must be called by a spike recording source on the "enable" method
+    */
     void registerSpikeSource(GenericProcessor* processor);
 
-	/** Registers an electrode group for spike recording
-	Must be called by a spike recording source on the "enable" method
-	after the call to registerSpikeSource 
-	*/
+    /** Registers an electrode group for spike recording
+    Must be called by a spike recording source on the "enable" method
+    after the call to registerSpikeSource
+    */
     int addSpikeElectrode(SpikeRecordInfo* elec);
 
-	/** Called by a spike recording source to write a spike to file
-	*/
+    /** Called by a spike recording source to write a spike to file
+    */
     void writeSpike(SpikeObject& spike, int electrodeIndex);
 
     SpikeRecordInfo* getSpikeElectrode(int index);
diff --git a/Source/Processors/ReferenceNode/ReferenceNode.cpp b/Source/Processors/ReferenceNode/ReferenceNode.cpp
deleted file mode 100644
index b162d8b42d619a820491c8be70e5c6f9b4871da6..0000000000000000000000000000000000000000
--- a/Source/Processors/ReferenceNode/ReferenceNode.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-    ------------------------------------------------------------------
-
-    This file is part of the Open Ephys GUI
-    Copyright (C) 2014 Open Ephys
-
-    ------------------------------------------------------------------
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include <stdio.h>
-#include "ReferenceNode.h"
-#include "ReferenceNodeEditor.h"
-
-
-
-ReferenceNode::ReferenceNode()
-    : GenericProcessor("Digital Ref"), referenceChannel(-1), referenceBuffer(1,10000)
-{
-
-}
-
-ReferenceNode::~ReferenceNode()
-{
-
-}
-
-AudioProcessorEditor* ReferenceNode::createEditor()
-{
-    editor = new ReferenceNodeEditor(this, true);
-
-    std::cout << "Creating editor." << std::endl;
-
-    return editor;
-}
-
-
-
-void ReferenceNode::updateSettings()
-{
-
-
-
-}
-
-void ReferenceNode::setParameter(int parameterIndex, float newValue)
-{
-    editor->updateParameterButtons(parameterIndex);
-
-    referenceChannel = (int) newValue;
-
-    std::cout << "Reference set to " << referenceChannel << std::endl;
-
-}
-
-void ReferenceNode::process(AudioSampleBuffer& buffer,
-                            MidiBuffer& midiMessages,
-                            int& nSamples)
-{
-
-    if (referenceChannel > -1)
-    {
-        referenceBuffer.clear(0, 0, nSamples);
-
-        referenceBuffer.addFrom(0, // destChannel
-                                0, // destStartSample
-                                buffer, // source
-                                referenceChannel, // sourceChannel
-                                0, // sourceStartSample
-                                nSamples, // numSamples
-                                -1.0f // gain to apply to source
-                               );
-
-        for (int i = 0; i < buffer.getNumChannels(); i++)
-        {
-
-            buffer.addFrom(i, // destChannel
-                           0, // destStartSample
-                           referenceBuffer, // source
-                           0, // sourceChannel
-                           0, // sourceStartSample
-                           nSamples, // numSamples
-                           1.0f // gain to apply to source
-                          );
-        }
-
-    }
-
-}
-
diff --git a/Source/Processors/ReferenceNode/ReferenceNode.h b/Source/Processors/ReferenceNode/ReferenceNode.h
deleted file mode 100644
index 15038e72a5d824c7c2a9af0ccbbdb4c31d14f599..0000000000000000000000000000000000000000
--- a/Source/Processors/ReferenceNode/ReferenceNode.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-    ------------------------------------------------------------------
-
-    This file is part of the Open Ephys GUI
-    Copyright (C) 2014 Open Ephys
-
-    ------------------------------------------------------------------
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef __REFERENCENODE_H_786EA929__
-#define __REFERENCENODE_H_786EA929__
-
-
-#include "../../../JuceLibraryCode/JuceHeader.h"
-
-#include "../GenericProcessor/GenericProcessor.h"
-
-
-/**
-
-  Digital reference node
-
-  @see GenericProcessor
-
-*/
-
-class ReferenceNode : public GenericProcessor
-
-{
-public:
-
-    ReferenceNode();
-    ~ReferenceNode();
-
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
-    void setParameter(int parameterIndex, float newValue);
-
-    AudioProcessorEditor* createEditor();
-
-    bool hasEditor() const
-    {
-        return true;
-    }
-
-    void updateSettings();
-
-private:
-
-    int referenceChannel;
-
-    AudioSampleBuffer referenceBuffer;
-
-    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ReferenceNode);
-
-};
-
-#endif  // __REFERENCENODE_H_786EA929__
diff --git a/Source/Processors/ReferenceNode/ReferenceNodeEditor.cpp b/Source/Processors/ReferenceNode/ReferenceNodeEditor.cpp
deleted file mode 100644
index 25054001c1b7bb6746648e3911703623663aa857..0000000000000000000000000000000000000000
--- a/Source/Processors/ReferenceNode/ReferenceNodeEditor.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-    ------------------------------------------------------------------
-
-    This file is part of the Open Ephys GUI
-    Copyright (C) 2014 Open Ephys
-
-    ------------------------------------------------------------------
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-#include "ReferenceNodeEditor.h"
-#include "ReferenceNode.h"
-#include <stdio.h>
-
-
-ReferenceNodeEditor::ReferenceNodeEditor(GenericProcessor* parentNode, bool useDefaultParameterEditors=true)
-    : GenericEditor(parentNode, useDefaultParameterEditors), previousChannelCount(0)
-
-{
-    desiredWidth = 180;
-
-    referenceSelector = new ComboBox();
-    referenceSelector->setBounds(15,50,150,25);
-    referenceSelector->addListener(this);
-    referenceSelector->addItem("None", 1);
-    referenceSelector->setSelectedId(1, dontSendNotification);
-    addAndMakeVisible(referenceSelector);
-
-}
-
-ReferenceNodeEditor::~ReferenceNodeEditor()
-{
-
-}
-
-void ReferenceNodeEditor::updateSettings()
-{
-
-    if (getProcessor()->getNumInputs() != previousChannelCount)
-    {
-        referenceSelector->clear();
-
-        referenceSelector->addItem("None", 1);
-
-        for (int i = 0; i < getProcessor()->getNumInputs(); i++)
-        {
-            referenceSelector->addItem("Channel " + String(i+1), i+2);
-
-        }
-
-        previousChannelCount = getProcessor()->getNumInputs();
-
-    }
-
-    referenceSelector->setSelectedId(1, dontSendNotification);
-
-    getProcessor()->setParameter(1,-1.0f);
-}
-
-void ReferenceNodeEditor::comboBoxChanged(ComboBox* c)
-{
-    float channel;
-
-    int id = c->getSelectedId();
-
-    if (id == 1)
-    {
-        channel = -1.0f;
-    }
-    else
-    {
-        channel = float(id) - 2.0f;
-    }
-
-    getProcessor()->setParameter(1,channel);
-
-}
-
-void ReferenceNodeEditor::buttonEvent(Button* button)
-{
-
-
-}
-
-void ReferenceNodeEditor::saveEditorParameters(XmlElement* xml)
-{
-
-    xml->setAttribute("Type", "ReferenceNodeEditor");
-
-    XmlElement* selectedChannel = xml->createNewChildElement("SELECTEDID");
-
-    selectedChannel->setAttribute("ID",referenceSelector->getSelectedId());
-
-}
-
-void ReferenceNodeEditor::loadEditorParameters(XmlElement* xml)
-{
-
-    forEachXmlChildElement(*xml, xmlNode)
-    {
-        if (xmlNode->hasTagName("SELECTEDID"))
-        {
-
-            int id = xmlNode->getIntAttribute("ID");
-
-            referenceSelector->setSelectedId(id);
-
-        }
-    }
-}
\ No newline at end of file
diff --git a/Source/Processors/ReferenceNode/ReferenceNodeEditor.h b/Source/Processors/ReferenceNode/ReferenceNodeEditor.h
deleted file mode 100644
index efce3f1a014f384e3fab2a6a805c88d8b7571f6c..0000000000000000000000000000000000000000
--- a/Source/Processors/ReferenceNode/ReferenceNodeEditor.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-    ------------------------------------------------------------------
-
-    This file is part of the Open Ephys GUI
-    Copyright (C) 2014 Open Ephys
-
-    ------------------------------------------------------------------
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef __REFERENCENODEEDITOR_H_370C056D__
-#define __REFERENCENODEEDITOR_H_370C056D__
-
-#include "../../../JuceLibraryCode/JuceHeader.h"
-#include "../Editors/GenericEditor.h"
-
-/**
-
-  User interface for the ReferenceNode processor.
-
-  @see ReferenceNode
-
-*/
-
-class ReferenceNodeEditor : public GenericEditor,
-    public ComboBox::Listener
-{
-public:
-    ReferenceNodeEditor(GenericProcessor* parentNode, bool useDefaultParameterEditors);
-    virtual ~ReferenceNodeEditor();
-    void buttonEvent(Button* button);
-
-    void comboBoxChanged(ComboBox* c);
-
-    void updateSettings();
-
-    void saveEditorParameters(XmlElement* xml);
-    void loadEditorParameters(XmlElement* xml);
-
-
-private:
-
-    ScopedPointer<ComboBox> referenceSelector;
-
-    int previousChannelCount;
-
-    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ReferenceNodeEditor);
-
-};
-
-
-
-
-
-#endif  // __REFERENCENODEEDITOR_H_370C056D__
diff --git a/Source/Processors/ResamplingNode/ResamplingNode.cpp b/Source/Processors/ResamplingNode/ResamplingNode.cpp
index af68d740f32b795fe7d12dc0fc20536766e1e4ea..123a946b72133c3d030565e724b8d9c3ac1857be 100755
--- a/Source/Processors/ResamplingNode/ResamplingNode.cpp
+++ b/Source/Processors/ResamplingNode/ResamplingNode.cpp
@@ -140,8 +140,7 @@ void ResamplingNode::updateFilter()
 // }
 
 void ResamplingNode::process(AudioSampleBuffer& buffer,
-                             MidiBuffer& midiMessages,
-                             int& nSamples)
+                             MidiBuffer& midiMessages)
 {
 
     //std::cout << "Resampling node sample count: " << nSamples << std::endl; ///buffer.getNumSamples() << std::endl;
@@ -149,6 +148,7 @@ void ResamplingNode::process(AudioSampleBuffer& buffer,
     // save data at the beginning of each round of processing
     //writeContinuousBuffer(buffer.getSampleData(0), nSamples, 0);
 
+    int nSamples = 100; // SOME NUMBER
 
     int nSamps = float(nSamples);
     int valuesNeeded = int(nSamps / ratio);
diff --git a/Source/Processors/ResamplingNode/ResamplingNode.h b/Source/Processors/ResamplingNode/ResamplingNode.h
index 0b864eade577f5f8fcf20df097be62e1d84db291..cd20ce62ae503dcd6fce5025cea1c3f4acef6735 100755
--- a/Source/Processors/ResamplingNode/ResamplingNode.h
+++ b/Source/Processors/ResamplingNode/ResamplingNode.h
@@ -50,7 +50,7 @@ public:
     ResamplingNode();
     ~ResamplingNode();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
     void setParameter(int parameterIndex, float newValue);
 
     void updateSettings();
diff --git a/Source/Processors/SerialInput/SerialInput.cpp b/Source/Processors/SerialInput/SerialInput.cpp
index 3664068bd1e8dd7d479c9d913fdc65c3b7add50a..58b6955d31d609ef329160a6af918b17dde2a426 100644
--- a/Source/Processors/SerialInput/SerialInput.cpp
+++ b/Source/Processors/SerialInput/SerialInput.cpp
@@ -90,7 +90,7 @@ bool SerialInput::disable()
 }
 
 
-void SerialInput::process(AudioSampleBuffer&, MidiBuffer& events, int&)
+void SerialInput::process(AudioSampleBuffer&, MidiBuffer& events)
 {
     int bytesAvailable = serial.available();
 
diff --git a/Source/Processors/SerialInput/SerialInput.h b/Source/Processors/SerialInput/SerialInput.h
index 96f8292d47409ec5f64595db38db4813f6e2bca2..36ceda52e70544577596973e11d9ba67f252009e 100644
--- a/Source/Processors/SerialInput/SerialInput.h
+++ b/Source/Processors/SerialInput/SerialInput.h
@@ -103,7 +103,7 @@ public:
 
      Adds all the new serial data that is available to the event data buffer.
      */
-    void process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& events);
 
     /**
      Returns the Juce GUI component that should be used with this processor.
diff --git a/Source/Processors/SignalGenerator/SignalGenerator.cpp b/Source/Processors/SignalGenerator/SignalGenerator.cpp
index 43c320fbe062b94ce743ac608f46bfbb5a567ef3..c06ef91a4d218328ceff592ab709a5132975cb01 100755
--- a/Source/Processors/SignalGenerator/SignalGenerator.cpp
+++ b/Source/Processors/SignalGenerator/SignalGenerator.cpp
@@ -184,11 +184,10 @@ bool SignalGenerator::disable()
 
 
 void SignalGenerator::process(AudioSampleBuffer& buffer,
-                              MidiBuffer& midiMessages,
-                              int& nSamps)
+                              MidiBuffer& midiMessages)
 {
 
-    nSamps = int((float) buffer.getNumSamples() * sampleRateRatio);
+    int nSamps = int((float) buffer.getNumSamples() * sampleRateRatio);
 
     for (int i = 0; i < nSamps; ++i)
     {
diff --git a/Source/Processors/SignalGenerator/SignalGenerator.h b/Source/Processors/SignalGenerator/SignalGenerator.h
index eef1de4ee0e9202ab9a493196d0737a048b33fd3..97f9809185e52e9714d15ab86d5ce54cae19f722 100755
--- a/Source/Processors/SignalGenerator/SignalGenerator.h
+++ b/Source/Processors/SignalGenerator/SignalGenerator.h
@@ -45,7 +45,7 @@ public:
     SignalGenerator();
     ~SignalGenerator();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
 
     void setParameter(int parameterIndex, float newValue);
 
diff --git a/Source/Processors/SourceNode/SourceNode.cpp b/Source/Processors/SourceNode/SourceNode.cpp
index d657cbc041ab9a7ee84bf017625a3fb72cd7df7f..79964dc0e52bd54a28f64fbf00b772d56b4f3316 100755
--- a/Source/Processors/SourceNode/SourceNode.cpp
+++ b/Source/Processors/SourceNode/SourceNode.cpp
@@ -23,13 +23,9 @@
 
 #include "SourceNode.h"
 #include "../DataThreads/DataBuffer.h"
-//#include "DataThreads/IntanThread.h"
-#include "../DataThreads/FPGAThread.h"
-//#include "../DataThreads/FileReaderThread.h"
 #include "../DataThreads/RHD2000Thread.h"
 #include "../DataThreads/EcubeThread.h" // Added by Michael Borisov
 #include "../SourceNode/SourceNodeEditor.h"
-//#include "../FileReader/FileReaderEditor.h"
 #include "../DataThreads/RHD2000Editor.h"
 #include "../DataThreads/EcubeEditor.h" // Added by Michael Borisov
 #include "../Channel/Channel.h"
@@ -45,15 +41,11 @@ SourceNode::SourceNode(const String& name_)
 
     if (getName().equalsIgnoreCase("RHA2000-EVAL"))
     {
-        // dataThread = new IntanThread(this);o
+        // dataThread = new IntanThread(this); // this thread has not been updated recently
     }
-    else if (getName().equalsIgnoreCase("Custom FPGA"))
-    {
-        dataThread = new FPGAThread(this);
-    }
-    //else if (getName().equalsIgnoreCase("File Reader"))
+   // else if (getName().equalsIgnoreCase("Custom FPGA"))
    // {
-    //    dataThread = new FileReaderThread(this);
+   //     dataThread = new FPGAThread(this);
    // }
     else if (getName().equalsIgnoreCase("Rhythm FPGA"))
     {
@@ -116,13 +108,13 @@ DataThread* SourceNode::getThread()
     return dataThread;
 }
 
-int SourceNode::modifyChannelName(channelType t, int str, int ch, String newName, bool updateSignalChain)
+int SourceNode::modifyChannelName(ChannelType t, int str, int ch, String newName, bool updateSignalChain)
 {
     if (dataThread != 0) {
         int channel_index = dataThread->modifyChannelName(t, str, ch, newName);
         if (channel_index >= 0 && channel_index < channels.size())
         {
-            if (channels[channel_index]->getChannelName() != newName)
+            if (channels[channel_index]->getName() != newName)
             {
                 channels[channel_index]->setName(newName);
                 // propagate this information...
@@ -137,7 +129,7 @@ int SourceNode::modifyChannelName(channelType t, int str, int ch, String newName
     return -1;
 }
 
-int SourceNode::modifyChannelGain(int stream, int channel,channelType type, float gain, bool updateSignalChain)
+int SourceNode::modifyChannelGain(int stream, int channel, ChannelType type, float gain, bool updateSignalChain)
 {
     if (dataThread != 0) 
     {
@@ -147,9 +139,9 @@ int SourceNode::modifyChannelGain(int stream, int channel,channelType type, floa
         if (channel_index >= 0 && channel_index < channels.size())
         {
             // we now need to update the signal chain to propagate this change.....
-            if (channels[channel_index]->getChannelGain() != gain) 
+            if (channels[channel_index]->bitVolts != gain) 
             {
-                channels[channel_index]->setGain(gain);
+                channels[channel_index]->bitVolts = gain;
                 
                 if (updateSignalChain)
                     getEditorViewport()->makeEditorVisible(getEditor(), false, true);
@@ -162,7 +154,7 @@ int SourceNode::modifyChannelGain(int stream, int channel,channelType type, floa
     return -1;
 }
 
-void SourceNode::getChannelsInfo(StringArray &names, Array<channelType> &types, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains)
+void SourceNode::getChannelsInfo(StringArray &names, Array<ChannelType> &types, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains)
 {
     if (dataThread != 0)
         dataThread->getChannelsInfo(names, types,stream,originalChannelNumber,gains);
@@ -175,7 +167,7 @@ void SourceNode::setDefaultNamingScheme(int scheme)
         dataThread->setDefaultNamingScheme(scheme);
 
         StringArray names;
-        Array<channelType> types;
+        Array<ChannelType> types;
         Array<int> stream;
         Array<int> originalChannelNumber;
         Array<float> gains;
@@ -204,21 +196,7 @@ void SourceNode::updateSettings()
         std::cout << "Input buffer address is " << inputBuffer << std::endl;
     }
 
-	dataThread->updateChannelNames();
-
-    for (int i = 0; i < dataThread->getNumEventChannels(); i++)
-    {
-        Channel* ch = new Channel(this, i);
-        ch->eventType = TTL;
-        ch->getType() == EVENT_CHANNEL;
-        eventChannels.add(ch);
-    }
-
-   //for (int i = 0; i < channels.size(); i++)
-   // {
-        std::cout << "Channel: " << channels[channels.size()-1]->bitVolts << std::endl;
-    //}
-
+	//dataThread->updateChannelNames();
 
 }
 
@@ -263,15 +241,39 @@ float SourceNode::getDefaultSampleRate()
         return 44100.0;
 }
 
-int SourceNode::getDefaultNumOutputs()
+int SourceNode::getNumHeadstageOutputs()
 {
     if (dataThread != 0)
-        return dataThread->getNumChannels();
+        return dataThread->getNumHeadstageOutputs();
+    else
+        return 2;
+}
+
+int SourceNode::getNumAuxOutputs()
+{
+    if (dataThread != 0)
+        return dataThread->getNumAuxOutputs();
     else
         return 0;
 }
 
-float SourceNode::getBitVolts(int chan)
+int SourceNode::getNumAdcOutputs()
+{
+    if (dataThread != 0)
+        return dataThread->getNumAdcOutputs();
+    else
+        return 0;
+}
+
+int SourceNode::getNumEventChannels()
+{
+    if (dataThread != 0)
+        return dataThread->getNumEventChannels();
+    else
+        return 0;
+}
+
+float SourceNode::getBitVolts(Channel* chan)
 {
 	if (dataThread != 0)
 		return dataThread->getBitVolts(chan);
@@ -365,6 +367,8 @@ bool SourceNode::enable()
 
     wasDisabled = false;
 
+    stopTimer();
+
     if (dataThread != 0)
     {
         dataThread->startAcquisition();
@@ -375,8 +379,6 @@ bool SourceNode::enable()
         return false;
     }
 
-    stopTimer(); // WARN compiler warning: unreachable code (spotted by Michael Borisov). Probably needs to be removed
-
 }
 
 bool SourceNode::disable()
@@ -387,7 +389,7 @@ bool SourceNode::disable()
     if (dataThread != 0)
         dataThread->stopAcquisition();
 
-    startTimer(2000);
+    startTimer(2000); // timer to check for connected source
 
     wasDisabled = true;
 
@@ -413,8 +415,7 @@ void SourceNode::acquisitionStopped()
 
 
 void SourceNode::process(AudioSampleBuffer& buffer,
-                         MidiBuffer& events,
-                         int& nSamples)
+                         MidiBuffer& events)
 {
 
     //std::cout << "SOURCE NODE" << std::endl;
@@ -423,7 +424,10 @@ void SourceNode::process(AudioSampleBuffer& buffer,
     events.clear();
     buffer.clear();
 
-    nSamples = inputBuffer->readAllFromBuffer(buffer, &timestamp, eventCodeBuffer, buffer.getNumSamples());
+    int nSamples = inputBuffer->readAllFromBuffer(buffer, &timestamp, eventCodeBuffer, buffer.getNumSamples());
+
+    setNumSamples(events, nSamples);
+    setTimestamp(events, timestamp);
 
     //std::cout << *buffer.getReadPointer(0) << std::endl;
 
@@ -431,18 +435,8 @@ void SourceNode::process(AudioSampleBuffer& buffer,
 
     //std::cout << "Samples per buffer: " << nSamples << std::endl;
 
-    uint8 data[8];
-    memcpy(data, &timestamp, 8);
 
-    // generate timestamp
-    addEvent(events,    // MidiBuffer
-             TIMESTAMP, // eventType
-             0,         // sampleNum
-             nodeId,    // eventID
-             0,		 // eventChannel
-             8,         // numBytes
-             data   // data
-            );
+    
 
     // std::cout << (int) *(data + 7) << " " <<
     //                 (int) *(data + 6) << " " <<
@@ -506,7 +500,7 @@ void SourceNode::saveCustomParametersToXml(XmlElement* parentElement)
 {
 
     StringArray names;
-    Array<channelType> types;
+    Array<ChannelType> types;
     Array<int> stream;
     Array<int> originalChannelNumber;
     Array<float> gains;
@@ -540,7 +534,7 @@ void SourceNode::loadCustomParametersFromXml()
 					String name = chan->getStringAttribute("name");
 					int stream = chan->getIntAttribute("stream");
 					int number = chan->getIntAttribute("number");
-					channelType type = static_cast<channelType>(chan->getIntAttribute("type"));
+					ChannelType type = static_cast<ChannelType>(chan->getIntAttribute("type"));
 					float gain = chan->getDoubleAttribute("gain");
 					modifyChannelName(type,stream,number,name,false);
 					modifyChannelGain(stream,number,type,gain,false);					
diff --git a/Source/Processors/SourceNode/SourceNode.h b/Source/Processors/SourceNode/SourceNode.h
index 494481fb282cd88320020662319fbd722e00b612..1b2f1f18a3cf4a8622ed894fe37517019f0747e3 100755
--- a/Source/Processors/SourceNode/SourceNode.h
+++ b/Source/Processors/SourceNode/SourceNode.h
@@ -51,19 +51,24 @@ public:
 
     void enabledState(bool t);
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
 
     void setParameter(int parameterIndex, float newValue);
 
     float getSampleRate();
     float getDefaultSampleRate();
-    int getDefaultNumOutputs();
-    float getBitVolts(int chan);
+    int getNumHeadstageOutputs();
 
-    int modifyChannelGain(int stream, int channel,channelType type, float gain, bool updateSignalChain);
-    int modifyChannelName(channelType t, int str, int ch, String newName, bool updateSignalChain);
+    int getNumAuxOutputs();
+    int getNumAdcOutputs();
 
-    void getChannelsInfo(StringArray &Names, Array<channelType> &type, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains);
+    int getNumEventChannels();
+    float getBitVolts(Channel* chan);
+
+    int modifyChannelGain(int stream, int channel,ChannelType type, float gain, bool updateSignalChain);
+    int modifyChannelName(ChannelType t, int str, int ch, String newName, bool updateSignalChain);
+
+    void getChannelsInfo(StringArray &Names, Array<ChannelType> &type, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains);
     void setDefaultNamingScheme(int scheme);
     void getEventChannelNames(StringArray &names);
 
@@ -113,12 +118,10 @@ private:
     uint64* eventCodeBuffer;
     int* eventChannelState;
 
-
     int ttlState;
 
     void updateSettings();
 
-
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SourceNode);
 
 };
diff --git a/Source/Processors/SpikeDetector/SpikeDetector.cpp b/Source/Processors/SpikeDetector/SpikeDetector.cpp
index 3a6456dad22fe0d477caf4312ff518193547e326..f181a44eb6c6ec33f073b668b4b8f07ccaada2f6 100755
--- a/Source/Processors/SpikeDetector/SpikeDetector.cpp
+++ b/Source/Processors/SpikeDetector/SpikeDetector.cpp
@@ -88,10 +88,20 @@ void SpikeDetector::updateSettings()
     for (int i = 0; i < electrodes.size(); i++)
     {
 
-        Channel* ch = new Channel(this, i);
-        //ch->isEventChannel = true;
-        ch->eventType = SPIKE_BASE_CODE + electrodes[i]->numChannels;
-        ch->name = electrodes[i]->name;
+        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;
+        }
 
         eventChannels.add(ch);
     }
@@ -156,6 +166,8 @@ bool SpikeDetector::addElectrode(int nChans)
         *(newElectrode->isActive+i) = true;
     }
 
+    newElectrode->sourceNodeId = channels[*newElectrode->channels]->sourceNodeId;
+
     resetElectrode(newElectrode);
 
     electrodes.add(newElectrode);
@@ -305,7 +317,13 @@ bool SpikeDetector::enable()
 {
 
     sampleRateForElectrode = (uint16_t) getSampleRate();
-    useOverflowBuffer = false;
+
+
+    useOverflowBuffer.clear();
+
+    for (int i = 0; i < electrodes.size(); i++)
+        useOverflowBuffer.add(false);
+
     return true;
 }
 
@@ -424,8 +442,7 @@ void SpikeDetector::handleEvent(int eventType, MidiMessage& event, int sampleNum
 }
 
 void SpikeDetector::process(AudioSampleBuffer& buffer,
-                            MidiBuffer& events,
-                            int& nSamples)
+                            MidiBuffer& events)
 {
 
     // cycle through electrodes
@@ -447,9 +464,12 @@ void SpikeDetector::process(AudioSampleBuffer& buffer,
         sampleIndex = electrode->lastBufferIndex - 1; // subtract 1 to account for
         // increment at start of getNextSample()
 
+        int nSamples = getNumSamples(*electrode->channels);
+
         // cycle through samples
         while (samplesAvailable(nSamples))
         {
+
             sampleIndex++;
             // cycle through channels
             for (int chan = 0; chan < electrode->numChannels; chan++)
@@ -543,6 +563,27 @@ void SpikeDetector::process(AudioSampleBuffer& buffer,
 
         //jassert(electrode->lastBufferIndex < 0);
 
+        if (nSamples > overflowBufferSize)
+        {
+
+            for (int j = 0; j < electrode->numChannels; j++)
+            {
+
+                overflowBuffer.copyFrom(*electrode->channels+i, 0,
+                                        buffer, *electrode->channels+i,
+                                        nSamples-overflowBufferSize,
+                                        overflowBufferSize);
+                
+            }
+
+            useOverflowBuffer.set(i, true);
+
+        }
+        else
+        {
+            useOverflowBuffer.set(i, false);
+        }
+
     } // end cycle through electrodes
 
     // copy end of this buffer into the overflow buffer
@@ -555,26 +596,7 @@ void SpikeDetector::process(AudioSampleBuffer& buffer,
     // std::cout << "numSamples = " << overflowBufferSize << std::endl;
     // std::cout << "buffer size = " << buffer.getNumSamples() << std::endl;
 
-    if (nSamples > overflowBufferSize)
-    {
-
-        for (int i = 0; i < overflowBuffer.getNumChannels(); i++)
-        {
-
-            overflowBuffer.copyFrom(i, 0,
-                                    buffer, i,
-                                    nSamples-overflowBufferSize,
-                                    overflowBufferSize);
-
-            useOverflowBuffer = true;
-        }
-
-    }
-    else
-    {
-
-        useOverflowBuffer = false;
-    }
+    
 
 
 
@@ -641,7 +663,7 @@ float SpikeDetector::getCurrentSample(int& chan)
 }
 
 
-bool SpikeDetector::samplesAvailable(int& nSamples)
+bool SpikeDetector::samplesAvailable(int nSamples)
 {
 
     if (sampleIndex > nSamples - overflowBufferSize/2)
diff --git a/Source/Processors/SpikeDetector/SpikeDetector.h b/Source/Processors/SpikeDetector/SpikeDetector.h
index 8c5292c999f0a475ef3ac5e9b001a866aa0e34bf..829ad60302c9766f74ae6bf5414ad31e5e2d1571 100755
--- a/Source/Processors/SpikeDetector/SpikeDetector.h
+++ b/Source/Processors/SpikeDetector/SpikeDetector.h
@@ -40,6 +40,7 @@ struct SimpleElectrode
     int prePeakSamples, postPeakSamples;
     int lastBufferIndex;
     bool isMonitored;
+    int sourceNodeId;
 
     int* channels;
     double* thresholds;
@@ -75,7 +76,7 @@ public:
 
     /** Processes an incoming continuous buffer and places new
         spikes into the event buffer. */
-    void process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& events);
 
     /** Used to alter parameters of data acquisition. */
     void setParameter(int parameterIndex, float newValue);
@@ -168,9 +169,9 @@ private:
 
     float getNextSample(int& chan);
     float getCurrentSample(int& chan);
-    bool samplesAvailable(int& nSamples);
+    bool samplesAvailable(int nSamples);
 
-    bool useOverflowBuffer;
+    Array<bool> useOverflowBuffer;
 
     int currentElectrode;
     int currentChannelIndex;
diff --git a/Source/Processors/SpikeDisplayNode/SpikeDisplayCanvas.cpp b/Source/Processors/SpikeDisplayNode/SpikeDisplayCanvas.cpp
index 14233600abafe3c209f0251f9be80a82d809cc3f..6b254dcc5875da4809af8991719bb12b4c5562f6 100755
--- a/Source/Processors/SpikeDisplayNode/SpikeDisplayCanvas.cpp
+++ b/Source/Processors/SpikeDisplayNode/SpikeDisplayCanvas.cpp
@@ -934,7 +934,7 @@ void WaveAxes::paint(Graphics& g)
 
     }
 
-    g.setColour(Colours::white);
+    
     plotSpike(spikeBuffer[spikeIndex], g);
 
 
@@ -950,6 +950,11 @@ void WaveAxes::plotSpike(const SpikeObject& s, Graphics& g)
     //compute the spatial width for each waveform sample
     float dx = getWidth()/float(spikeBuffer[0].nSamples);
 
+    if (s.sortedId > 0)
+       g.setColour(Colour(s.color[0],s.color[1],s.color[2]));
+    else
+       g.setColour(Colours::white);
+
     // type corresponds to channel so we need to calculate the starting
     // sample based upon which channel is getting plotted
     int sampIdx = 40*type; //spikeBuffer[0].nSamples * type; //
@@ -1273,13 +1278,19 @@ bool ProjectionAxes::updateSpikeData(const SpikeObject& s)
     calcWaveformPeakIdx(s, ampDim1, ampDim2, &idx1, &idx2);
 
     // add peaks to image
+    Colour col;
+
+    if (s.sortedId > 0)
+        col = Colour(s.color[0], s.color[1], s.color[2]);
+    else
+        col = Colours::white;
 
-    updateProjectionImage(s.data[idx1], s.data[idx2], *s.gain);
+    updateProjectionImage(s.data[idx1], s.data[idx2], *s.gain, col);
 
     return true;
 }
 
-void ProjectionAxes::updateProjectionImage(uint16_t x, uint16_t y, uint16_t gain)
+void ProjectionAxes::updateProjectionImage(uint16_t x, uint16_t y, uint16_t gain, Colour col)
 {
     Graphics g(projectionImage);
 
@@ -1290,7 +1301,7 @@ void ProjectionAxes::updateProjectionImage(uint16_t x, uint16_t y, uint16_t gain
         float xf = float(x-32768)/float(gain)*1000.0f; // in microvolts
         float yf = float(imageDim) - float(y-32768)/float(gain)*1000.0f; // in microvolts
 
-        g.setColour(Colours::white);
+        g.setColour(col);
         g.fillEllipse(xf,yf,2.0f,2.0f);
     }
 
diff --git a/Source/Processors/SpikeDisplayNode/SpikeDisplayCanvas.h b/Source/Processors/SpikeDisplayNode/SpikeDisplayCanvas.h
index 78bfc189978b29bf065db5f74f53b020da0af19a..bacf46e08c8b9c60911b0aeacbc1060cc511eb64 100755
--- a/Source/Processors/SpikeDisplayNode/SpikeDisplayCanvas.h
+++ b/Source/Processors/SpikeDisplayNode/SpikeDisplayCanvas.h
@@ -425,7 +425,7 @@ public:
 
 private:
 
-    void updateProjectionImage(uint16_t, uint16_t, uint16_t);
+    void updateProjectionImage(uint16_t, uint16_t, uint16_t, Colour);
 
     void calcWaveformPeakIdx(const SpikeObject&, int, int, int*, int*);
 
diff --git a/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.cpp b/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.cpp
index 4502ea5fae2bdfe396d75662833e774c2c69f895..fa1c2f702f5173f36be76fe578f0b6290e78d9c1 100755
--- a/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.cpp
+++ b/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.cpp
@@ -58,12 +58,27 @@ void SpikeDisplayNode::updateSettings()
     electrodes.clear();
     for (int i = 0; i < eventChannels.size(); i++)
     {
-        if ((eventChannels[i]->eventType < 999) && (eventChannels[i]->eventType > SPIKE_BASE_CODE))
+        ChannelType type = eventChannels[i]->getType();
+
+        if (type == SINGLE_ELECTRODE || type == STEREOTRODE || type == TETRODE)
         {
 
             Electrode elec;
-            elec.numChannels = eventChannels[i]->eventType - 100;
-            elec.name = eventChannels[i]->name;
+
+            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);
 
@@ -197,7 +212,7 @@ void SpikeDisplayNode::setParameter(int param, float val)
 
 
 
-void SpikeDisplayNode::process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSamples)
+void SpikeDisplayNode::process(AudioSampleBuffer& buffer, MidiBuffer& events)
 {
 
     checkForEvents(events); // automatically calls 'handleEvent
diff --git a/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.h b/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.h
index 2b630f7cd528e69656aa4eda757d92423435ef66..56f776aafb1ef0c97ea1a27893566286e1cc3e81 100755
--- a/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.h
+++ b/Source/Processors/SpikeDisplayNode/SpikeDisplayNode.h
@@ -56,7 +56,7 @@ public:
         return true;
     }
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
 
     void setParameter(int, float);
 
diff --git a/Source/Processors/SpikeSorter/SpikeSorter.cpp b/Source/Processors/SpikeSorter/SpikeSorter.cpp
index 6ca986f06f2d9d030cd31766d5f28518ae83230f..7e5205efb05a636635c0bbe1904141e3382739a5 100644
--- a/Source/Processors/SpikeSorter/SpikeSorter.cpp
+++ b/Source/Processors/SpikeSorter/SpikeSorter.cpp
@@ -188,20 +188,27 @@ void SpikeSorter::updateSettings()
 	double ContinuousBufferLengthSec = 5;
 	channelBuffers = new ContinuousCircularBuffer(numChannels,SamplingRate,1, ContinuousBufferLengthSec);
 	 
-	for (int i = 0; i < electrodes.size(); i++)
-	{
+	
+    for (int i = 0; i < electrodes.size(); i++)
+    {
 
-		Channel* ch = new Channel(this, i);
-        //ch->isEventChannel = true;
-        ch->eventType = SPIKE_BASE_CODE + electrodes[i]->numChannels;
-        ch->name = electrodes[i]->name;
+        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;
+        }
 
         eventChannels.add(ch);
-		// String eventlog = "NewElectrode "+String(electrodes[k]->electrodeID) + " "+String(electrodes[k]->numChannels)+" ";
-		// for (int j=0;j<electrodes[k]->numChannels;j++)
-		// 	eventlog += String(electrodes[k]->channels[j])+ " "+electrodes[k]->name;
-		// //addNetworkEventToQueue(StringTS(eventlog));
-	}
+    }
 	
 	mut.exit();
 }
@@ -216,7 +223,7 @@ Electrode::~Electrode()
 	delete spikeSort;
 }
 
-Electrode::Electrode(int ID, UniqueIDgenerator *uniqueIDgenerator_, PCAcomputingThread *pth, String _name, int _numChannels, int *_channels, float default_threshold, int pre, int post, float samplingRate )
+Electrode::Electrode(int ID, UniqueIDgenerator *uniqueIDgenerator_, PCAcomputingThread *pth, String _name, int _numChannels, int *_channels, float default_threshold, int pre, int post, float samplingRate , int sourceNodeId)
 {
 	electrodeID = ID;
 	computingThread = pth;
@@ -400,7 +407,7 @@ void SpikeSorter::assignDACtoChannel(int dacOutput, int channel)
 	RHD2000Thread* th = getRhythmAccess();
 	if (th != nullptr)
 	{
-		th->setDACchannel(dacOutput, channels[channel]->originalStream, channels[channel]->originalChannel);
+		th->setDACchannel(dacOutput, channels[channel]->sourceNodeId, channels[channel]->index); // this is probably wrong (JHS)
 	}
 }
 
@@ -436,19 +443,19 @@ bool SpikeSorter::addElectrode(int nChans, String name, double Depth)
         return false;
     }
 	
-	int *channels = new int[nChans];
+	int *chans = new int[nChans];
 	for (int k = 0; k < nChans; k++)
-		channels[k] = firstChan + k;
+		chans[k] = firstChan + k;
 
-	Electrode* newElectrode = new Electrode(++uniqueID, &uniqueIDgenerator, &computingThread, name, nChans, channels, getDefaultThreshold(), 
-		numPreSamples, numPostSamples, getSampleRate());
+	Electrode* newElectrode = new Electrode(++uniqueID, &uniqueIDgenerator, &computingThread, name, nChans, chans, getDefaultThreshold(), 
+		numPreSamples, numPostSamples, getSampleRate(), channels[chans[0]]->sourceNodeId);
 
 	newElectrode->depthOffsetMM = Depth;
 	String log = "Added electrode (ID "+ String(uniqueID)+") with " + String(nChans) + " channels." ;
     std::cout << log << std::endl;
 	String eventlog = "NewElectrode "+ String(uniqueID) + " " + String(nChans) + " ";
 	for (int k = 0; k < nChans; k++)
-		eventlog += String(channels[k])+ " " + name;
+		eventlog += String(chans[k])+ " " + name;
 
 	//addNetworkEventToQueue(StringTS(eventlog));
 
@@ -635,7 +642,12 @@ void SpikeSorter::setParameter(int parameterIndex, float newValue)
 bool SpikeSorter::enable()
 {
 
-    useOverflowBuffer = false;
+    useOverflowBuffer.clear();
+
+    for (int i = 0; i < electrodes.size(); i++)
+        useOverflowBuffer.add(false);
+
+
 	SpikeSorterEditor* editor = (SpikeSorterEditor*) getEditor();
 	 editor->enable();
 	
@@ -705,7 +717,7 @@ void SpikeSorter::addWaveformToSpikeObject(SpikeObject* s,
 
     int chan = *(electrodes[electrodeNumber]->channels+currentChannel);
 
-	s->gain[currentChannel] = (1.0f / channels[chan]->getChannelGain())*1000;
+	s->gain[currentChannel] = (1.0f / channels[chan]->bitVolts)*1000;
     s->threshold[currentChannel] = (int) electrodes[electrodeNumber]->thresholds[currentChannel]; 
 
     // cycle through buffer
@@ -719,7 +731,7 @@ void SpikeSorter::addWaveformToSpikeObject(SpikeObject* s,
             // warning -- be careful of bitvolts conversion
 			// do not flip signal (!).
 			float value = getNextSample(electrodes[electrodeNumber]->channels[currentChannel]);
-			s->data[currentIndex] = uint16(jmin(65535,jmax(0, int(value / channels[chan]->getChannelGain()) + 32768)));
+			s->data[currentIndex] = uint16(jmin(65535,jmax(0, int(value / channels[chan]->bitVolts) + 32768)));
  			// recovered data
 			//float value2 = (s->data[currentIndex]-32768) /float(s->gain[currentChannel])*1000.0f;
 
@@ -845,8 +857,7 @@ void SpikeSorter::handleEvent(int eventType, MidiMessage& event, int sampleNum)
 // }
 
 void SpikeSorter::process(AudioSampleBuffer& buffer,
-                            MidiBuffer& events,
-                            int& nSamples)
+                            MidiBuffer& events)
 {
 	
 	//printf("Entering Spike Detector::process\n");
@@ -858,9 +869,7 @@ void SpikeSorter::process(AudioSampleBuffer& buffer,
 	
     checkForEvents(events); // find latest's packet timestamps
 	
-	//postEventsInQueue(events);
-
-	channelBuffers->update(buffer,  hardware_timestamp,software_timestamp,nSamples);
+	//channelBuffers->update(buffer, hardware_timestamp,software_timestamp, nSamples);
 
     for (int i = 0; i < electrodes.size(); i++)
     {
@@ -873,6 +882,8 @@ void SpikeSorter::process(AudioSampleBuffer& buffer,
         sampleIndex = electrode->lastBufferIndex - 1; // subtract 1 to account for
         // increment at start of getNextSample()
 
+        int nSamples = getNumSamples(*electrode->channels); // get the number of samples for this buffer
+
         // cycle through samples
         while (samplesAvailable(nSamples))
         {
@@ -1003,39 +1014,28 @@ void SpikeSorter::process(AudioSampleBuffer& buffer,
 
         //jassert(electrode->lastBufferIndex < 0);
 
-    } // end cycle through electrodes
-
-    // copy end of this buffer into the overflow buffer
+        if (nSamples > overflowBufferSize)
+        {
 
-    //std::cout << "Copying buffer" << std::endl;
-    // std::cout << "nSamples: " << nSamples;
-    //std::cout << "overflowBufferSize:" << overflowBufferSize;
+            for (int j = 0; j < electrode->numChannels; j++)
+            {
 
-    //std::cout << "sourceStartSample = " << nSamples-overflowBufferSize << std::endl;
-    // std::cout << "numSamples = " << overflowBufferSize << std::endl;
-    // std::cout << "buffer size = " << buffer.getNumSamples() << std::endl;
+                overflowBuffer.copyFrom(*electrode->channels+i, 0,
+                                        buffer, *electrode->channels+i,
+                                        nSamples-overflowBufferSize,
+                                        overflowBufferSize);
+                
+            }
 
-    if (nSamples > overflowBufferSize)
-    {
+            useOverflowBuffer.set(i, true);
 
-        for (int i = 0; i < overflowBuffer.getNumChannels(); i++)
+        }
+        else
         {
-
-            overflowBuffer.copyFrom(i, 0,
-                                    buffer, i,
-                                    nSamples-overflowBufferSize,
-                                    overflowBufferSize);
-
-
-            useOverflowBuffer = true;
+            useOverflowBuffer.set(i, false);
         }
 
-    }
-    else
-    {
-
-        useOverflowBuffer = false;
-    }
+    } // end cycle through electrodes
 
 
 	mut.exit();
@@ -1103,7 +1103,7 @@ float SpikeSorter::getCurrentSample(int& chan)
 }
 
 
-bool SpikeSorter::samplesAvailable(int& nSamples)
+bool SpikeSorter::samplesAvailable(int nSamples)
 {
 
     if (sampleIndex > nSamples - overflowBufferSize/2)
@@ -1328,8 +1328,11 @@ void SpikeSorter::loadCustomParametersFromXml()
 								isActive[channelIndex] = channelNode->getBoolAttribute("isActive");
 							}
 						}
+
+						int sourceNodeId = 102010; // some number
+
 						Electrode* newElectrode = new Electrode(electrodeID, &uniqueIDgenerator,&computingThread, electrodeName, channelsPerElectrode, channels,getDefaultThreshold(),
-							numPreSamples,numPostSamples, getSampleRate());
+							numPreSamples,numPostSamples, getSampleRate(), sourceNodeId);
 						for (int k=0;k<channelsPerElectrode;k++)
 						{
 							newElectrode->thresholds[k] = thres[k];
diff --git a/Source/Processors/SpikeSorter/SpikeSorter.h b/Source/Processors/SpikeSorter/SpikeSorter.h
index d5dff6e048d433b4644164982534f4650e5d08b4..bb520b868bc464251a657df3025aa9c8c03f8af9 100644
--- a/Source/Processors/SpikeSorter/SpikeSorter.h
+++ b/Source/Processors/SpikeSorter/SpikeSorter.h
@@ -84,7 +84,7 @@ private:
 class Electrode
 {
 	public:
-		Electrode(int electrodeID, UniqueIDgenerator *uniqueIDgenerator_, PCAcomputingThread *pth,String _name, int _numChannels, int *_channels, float default_threshold, int pre, int post, float samplingRate );
+		Electrode(int electrodeID, UniqueIDgenerator *uniqueIDgenerator_, PCAcomputingThread *pth,String _name, int _numChannels, int *_channels, float default_threshold, int pre, int post, float samplingRate , int sourceNodeId);
         ~Electrode();
 
 		void resizeWaveform(int numPre, int numPost);
@@ -99,6 +99,7 @@ class Electrode
 		float depthOffsetMM;
 
 		int electrodeID;
+		int sourceNodeId;
         int* channels;
 	    double* thresholds;
         bool* isActive;
@@ -161,7 +162,7 @@ public:
 
     /** Processes an incoming continuous buffer and places new
         spikes into the event buffer. */
-    void process(AudioSampleBuffer& buffer, MidiBuffer& events, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& events);
 
     /** Used to alter parameters of data acquisition. */
     void setParameter(int parameterIndex, float newValue);
@@ -338,9 +339,9 @@ private:
     std::vector<int> electrodeCounter;
     float getNextSample(int& chan);
     float getCurrentSample(int& chan);
-    bool samplesAvailable(int& nSamples);
+    bool samplesAvailable(int nSamples);
 
-    bool useOverflowBuffer;
+    Array<bool> useOverflowBuffer;
 
     int currentElectrode;
     int currentChannelIndex;
diff --git a/Source/Processors/Splitter/Splitter.h b/Source/Processors/Splitter/Splitter.h
index 12a6f80bbd87a62a9678b8d2f80c97cd9e8e62b2..76a18a6dff84607ccf7062cad19f421cff080fc1 100755
--- a/Source/Processors/Splitter/Splitter.h
+++ b/Source/Processors/Splitter/Splitter.h
@@ -53,7 +53,7 @@ public:
     AudioProcessorEditor* createEditor();
 
     /** Nothing happens here, because Splitters are not part of the ProcessorGraph. */
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples) {}
+    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages) {}
 
     bool isSplitter()
     {
diff --git a/Source/Processors/WiFiOutput/WiFiOutput.cpp b/Source/Processors/WiFiOutput/WiFiOutput.cpp
index cf52d9091b5601fa19203942704b571b474ff1d0..9e56b84293e795d8ef57766ec61051b6991a6cae 100755
--- a/Source/Processors/WiFiOutput/WiFiOutput.cpp
+++ b/Source/Processors/WiFiOutput/WiFiOutput.cpp
@@ -56,8 +56,7 @@ void WiFiOutput::setParameter(int parameterIndex, float newValue)
 }
 
 void WiFiOutput::process(AudioSampleBuffer& buffer,
-                         MidiBuffer& events,
-                         int& nSamples)
+                         MidiBuffer& events)
 {
 
 
diff --git a/Source/Processors/WiFiOutput/WiFiOutput.h b/Source/Processors/WiFiOutput/WiFiOutput.h
index b2d35d436249bd967b18406c9c58341c6cf52cfe..bf6a7dbc3660f86a79a25cd0d306a52c66e7b742 100755
--- a/Source/Processors/WiFiOutput/WiFiOutput.h
+++ b/Source/Processors/WiFiOutput/WiFiOutput.h
@@ -51,7 +51,7 @@ public:
     WiFiOutput();
     ~WiFiOutput();
 
-    void process(AudioSampleBuffer& buffer, MidiBuffer& midiMessages, int& nSamples);
+    void process(AudioSampleBuffer& buffer, MidiBuffer& events);
     void setParameter(int parameterIndex, float newValue);
 
     void handleEvent(int eventType, MidiMessage& event, int sampleNum);
diff --git a/Source/UI/EditorViewport.cpp b/Source/UI/EditorViewport.cpp
index cae581e6d70475cd50832179937a61863d7a1795..ff2724befd9b58c892eb3005f6ca54d0fa05f1e7 100755
--- a/Source/UI/EditorViewport.cpp
+++ b/Source/UI/EditorViewport.cpp
@@ -1379,6 +1379,7 @@ const String EditorViewport::saveState(File fileToUse)
 
     getControlPanel()->saveStateToXml(xml); // save the control panel settings
     getProcessorList()->saveStateToXml(xml);
+	getMessageCenter()->saveStateToXml(xml);
     getUIComponent()->saveStateToXml(xml);  // save the UI settings
 
     if (! xml->writeToFile(currentFile, String::empty))
@@ -1586,6 +1587,7 @@ const String EditorViewport::loadState(File fileToLoad)
 
     getControlPanel()->loadStateFromXml(xml); // save the control panel settings
     getProcessorList()->loadStateFromXml(xml);
+	getMessageCenter()->loadStateFromXml(xml);
     getUIComponent()->loadStateFromXml(xml);  // save the UI settings
 
     if (editorArray.size() > 0)
diff --git a/open-ephys.jucer b/open-ephys.jucer
index 448f83415e12b6bd01c0afc4d883b30593b3821f..b432a75a756fb9126161eb3948a24a5a656c643e 100644
--- a/open-ephys.jucer
+++ b/open-ephys.jucer
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<JUCERPROJECT id="ynSYIrr" name="open-ephys" projectType="guiapp" version="0.3.3"
+<JUCERPROJECT id="ynSYIrr" name="open-ephys" projectType="guiapp" version="0.3.4"
               juceLinkage="amalg_multi" buildVST="1" buildRTAS="0" buildAU="1"
               pluginName="Juce Project" pluginDesc="Juce Project" pluginManufacturer="yourcompany"
               pluginManufacturerCode="Manu" pluginCode="Plug" pluginChannelConfigs="{1, 1}, {2, 2}"
@@ -296,12 +296,6 @@
           <FILE id="jClaJf" name="AudioNode.cpp" compile="1" resource="0" file="Source/Processors/AudioNode/AudioNode.cpp"/>
           <FILE id="LHkdoG" name="AudioNode.h" compile="0" resource="0" file="Source/Processors/AudioNode/AudioNode.h"/>
         </GROUP>
-        <GROUP id="{ED1C2AFE-2ED9-D835-532A-4D6C558C73E7}" name="AudioResamplingNode">
-          <FILE id="YStaN1" name="AudioResamplingNode.cpp" compile="1" resource="0"
-                file="Source/Processors/AudioResamplingNode/AudioResamplingNode.cpp"/>
-          <FILE id="pnFZDY" name="AudioResamplingNode.h" compile="0" resource="0"
-                file="Source/Processors/AudioResamplingNode/AudioResamplingNode.h"/>
-        </GROUP>
         <GROUP id="{46016F19-8F25-F540-AA1C-D6E87E8D7D31}" name="Channel">
           <FILE id="X3I3e9" name="Channel.cpp" compile="1" resource="0" file="Source/Processors/Channel/Channel.cpp"/>
           <FILE id="IEZGF3" name="Channel.h" compile="0" resource="0" file="Source/Processors/Channel/Channel.h"/>
@@ -346,12 +340,6 @@
                 file="Source/Processors/DataThreads/RHD2000Thread.cpp"/>
           <FILE id="BbYdtBN" name="RHD2000Thread.h" compile="0" resource="0"
                 file="Source/Processors/DataThreads/RHD2000Thread.h"/>
-          <FILE id="xWMgZ8D" name="FileReaderThread.cpp" compile="1" resource="0"
-                file="Source/Processors/DataThreads/FileReaderThread.cpp"/>
-          <FILE id="muolub6" name="FileReaderThread.h" compile="0" resource="0"
-                file="Source/Processors/DataThreads/FileReaderThread.h"/>
-          <FILE id="KEzbFux" name="FPGAThread.cpp" compile="1" resource="0" file="Source/Processors/DataThreads/FPGAThread.cpp"/>
-          <FILE id="6iEndcT" name="FPGAThread.h" compile="0" resource="0" file="Source/Processors/DataThreads/FPGAThread.h"/>
           <FILE id="Qfe0ygk" name="DataBuffer.cpp" compile="1" resource="0" file="Source/Processors/DataThreads/DataBuffer.cpp"/>
           <FILE id="VCRMcQP" name="DataBuffer.h" compile="0" resource="0" file="Source/Processors/DataThreads/DataBuffer.h"/>
           <FILE id="9JbVKlA" name="DataThread.cpp" compile="1" resource="0" file="Source/Processors/DataThreads/DataThread.cpp"/>
@@ -463,14 +451,6 @@
           <FILE id="usXu7Q" name="FilterNode.cpp" compile="1" resource="0" file="Source/Processors/FilterNode/FilterNode.cpp"/>
           <FILE id="qnkW8d" name="FilterNode.h" compile="0" resource="0" file="Source/Processors/FilterNode/FilterNode.h"/>
         </GROUP>
-        <GROUP id="{C47ABFBD-BC30-F6F2-B445-67B11DC5594F}" name="FPGAOutput">
-          <FILE id="DY6GL1" name="FPGAOutput.cpp" compile="1" resource="0" file="Source/Processors/FPGAOutput/FPGAOutput.cpp"/>
-          <FILE id="CdbTqf" name="FPGAOutput.h" compile="0" resource="0" file="Source/Processors/FPGAOutput/FPGAOutput.h"/>
-          <FILE id="tH5H69" name="FPGAOutputEditor.cpp" compile="1" resource="0"
-                file="Source/Processors/FPGAOutput/FPGAOutputEditor.cpp"/>
-          <FILE id="e1ivPs" name="FPGAOutputEditor.h" compile="0" resource="0"
-                file="Source/Processors/FPGAOutput/FPGAOutputEditor.h"/>
-        </GROUP>
         <GROUP id="{95FA3CAF-7BFA-AFF7-4480-EADCCA5FBA66}" name="GenericProcessor">
           <FILE id="l24v5k" name="GenericProcessor.cpp" compile="1" resource="0"
                 file="Source/Processors/GenericProcessor/GenericProcessor.cpp"/>
@@ -491,20 +471,6 @@
           <FILE id="rKu45v" name="LfpDisplayNode.h" compile="0" resource="0"
                 file="Source/Processors/LfpDisplayNode/LfpDisplayNode.h"/>
         </GROUP>
-        <GROUP id="{D20DFFFD-08E8-5CC6-479A-07CECDE9BC86}" name="LfpTriggeredAverageNode">
-          <FILE id="dxKyFx" name="LfpTriggeredAverageCanvas.cpp" compile="1"
-                resource="0" file="Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageCanvas.cpp"/>
-          <FILE id="CMxAvm" name="LfpTriggeredAverageCanvas.h" compile="0" resource="0"
-                file="Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageCanvas.h"/>
-          <FILE id="VhsonN" name="LfpTriggeredAverageEditor.cpp" compile="1"
-                resource="0" file="Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageEditor.cpp"/>
-          <FILE id="jVc0dD" name="LfpTriggeredAverageEditor.h" compile="0" resource="0"
-                file="Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageEditor.h"/>
-          <FILE id="ADrDsi" name="LfpTriggeredAverageNode.cpp" compile="1" resource="0"
-                file="Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.cpp"/>
-          <FILE id="wEt96B" name="LfpTriggeredAverageNode.h" compile="0" resource="0"
-                file="Source/Processors/LfpTriggeredAverageNode/LfpTriggeredAverageNode.h"/>
-        </GROUP>
         <GROUP id="{4B40CAAE-49C7-509A-B7E7-0C7EF011FBA1}" name="Merger">
           <FILE id="gZxAmt" name="Merger.cpp" compile="1" resource="0" file="Source/Processors/Merger/Merger.cpp"/>
           <FILE id="w8qwHK" name="Merger.h" compile="0" resource="0" file="Source/Processors/Merger/Merger.h"/>
@@ -602,15 +568,6 @@
           <FILE id="fDpocU" name="TrialCircularBuffer.h" compile="0" resource="0"
                 file="Source/Processors/PSTH/TrialCircularBuffer.h"/>
         </GROUP>
-        <GROUP id="{B0C14DBE-8CC1-F242-3534-1DFBEAC5E43B}" name="ReferenceNode">
-          <FILE id="F7WTBV" name="ReferenceNode.cpp" compile="1" resource="0"
-                file="Source/Processors/ReferenceNode/ReferenceNode.cpp"/>
-          <FILE id="XyYPUn" name="ReferenceNode.h" compile="0" resource="0" file="Source/Processors/ReferenceNode/ReferenceNode.h"/>
-          <FILE id="tsfK4e" name="ReferenceNodeEditor.cpp" compile="1" resource="0"
-                file="Source/Processors/ReferenceNode/ReferenceNodeEditor.cpp"/>
-          <FILE id="virGvM" name="ReferenceNodeEditor.h" compile="0" resource="0"
-                file="Source/Processors/ReferenceNode/ReferenceNodeEditor.h"/>
-        </GROUP>
         <GROUP id="{C6F1F354-C97E-128E-9C4E-2376E039F233}" name="ResamplingNode">
           <FILE id="yIwQ4b" name="ResamplingNode.cpp" compile="1" resource="0"
                 file="Source/Processors/ResamplingNode/ResamplingNode.cpp"/>
@@ -714,14 +671,6 @@
           <FILE id="EH2pAq" name="MatlabLikePlot.h" compile="0" resource="0"
                 file="Source/Processors/Visualization/MatlabLikePlot.h"/>
         </GROUP>
-        <GROUP id="{3FCFBFDA-848D-6B59-5F37-E3D1F43D54DF}" name="WiFiOutput">
-          <FILE id="OmOeLf" name="WiFiOutput.cpp" compile="1" resource="0" file="Source/Processors/WiFiOutput/WiFiOutput.cpp"/>
-          <FILE id="o3arNv" name="WiFiOutput.h" compile="0" resource="0" file="Source/Processors/WiFiOutput/WiFiOutput.h"/>
-          <FILE id="XSiAk6" name="WiFiOutputEditor.cpp" compile="1" resource="0"
-                file="Source/Processors/WiFiOutput/WiFiOutputEditor.cpp"/>
-          <FILE id="QdKqgJ" name="WiFiOutputEditor.h" compile="0" resource="0"
-                file="Source/Processors/WiFiOutput/WiFiOutputEditor.h"/>
-        </GROUP>
       </GROUP>
       <GROUP id="RNGb1yR" name="UI">
         <FILE id="PBkkUW" name="EcubeDialogComponent.cpp" compile="1" resource="0"