diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile
index 6587f6c05e60cd222c5305ce55f29164a4bb6e98..7539a54cbe22c65f43327e4bcc37832f369c7a1f 100644
--- a/Builds/Linux/Makefile
+++ b/Builds/Linux/Makefile
@@ -57,6 +57,7 @@ OBJECTS := \
   $(OBJDIR)/AudioComponent_521bd9c9.o \
   $(OBJDIR)/PlaceholderProcessorEditor_7b4cbcf7.o \
   $(OBJDIR)/PlaceholderProcessor_167f09aa.o \
+  $(OBJDIR)/LinearSmoothedValueAtomic_df1e5b97.o \
   $(OBJDIR)/Bessel_7e54cb27.o \
   $(OBJDIR)/Biquad_622c856b.o \
   $(OBJDIR)/Butterworth_6aca939b.o \
@@ -196,6 +197,11 @@ $(OBJDIR)/PlaceholderProcessor_167f09aa.o: ../../Source/Processors/PlaceholderPr
 	@echo "Compiling PlaceholderProcessor.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
+$(OBJDIR)/LinearSmoothedValueAtomic_df1e5b97.o: ../../Source/Processors/Dsp/LinearSmoothedValueAtomic.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling LinearSmoothedValueAtomic.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
 $(OBJDIR)/Bessel_7e54cb27.o: ../../Source/Processors/Dsp/Bessel.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling Bessel.cpp"
diff --git a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
index 4fce25d6e65a6274c9707f75a8ce98d24242dd03..8148ac75fb577e2847e0998d1e749734ff36eb37 100644
--- a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
+++ b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
@@ -26,6 +26,7 @@
 		0AE243437B40602D35435C32 = {isa = PBXBuildFile; fileRef = B04D87ED6AA4897B6CD3CCF6; };
 		B04B9CA1E59D544793808F25 = {isa = PBXBuildFile; fileRef = 524466E331502DEC89862D66; };
 		28B77947820CAE30A5E2DE22 = {isa = PBXBuildFile; fileRef = 9AD7314174B2AB01FBF7E1E1; };
+		CB568964BDF3E65207B81CCA = {isa = PBXBuildFile; fileRef = 72D50E371901970C428D9E8B; };
 		9252537C12447F047243DEE9 = {isa = PBXBuildFile; fileRef = 041038F6E67FE0409D8ECC74; };
 		B081F3F4FA6D8C35E2EEE778 = {isa = PBXBuildFile; fileRef = CB5C14E82DE06F767EAD62F9; };
 		7398C5E00B9093F78C697706 = {isa = PBXBuildFile; fileRef = 777D9B0FE3C110ADA980BD09; };
@@ -202,6 +203,7 @@
 		13D9DC48F19699485F9888A4 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_PathIterator.h"; path = "../../JuceLibraryCode/modules/juce_graphics/geometry/juce_PathIterator.h"; sourceTree = "SOURCE_ROOT"; };
 		1463D2DAB3A1D8CEE825056A = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioCDReader.h"; path = "../../JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.h"; sourceTree = "SOURCE_ROOT"; };
 		146C6A6E3C6B17F2AF475B50 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_OpenGLFrameBuffer.cpp"; path = "../../JuceLibraryCode/modules/juce_opengl/opengl/juce_OpenGLFrameBuffer.cpp"; sourceTree = "SOURCE_ROOT"; };
+		148FE750B55B2F7EA3899408 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LinearSmoothedValueAtomic.h; path = ../../Source/Processors/Dsp/LinearSmoothedValueAtomic.h; sourceTree = "SOURCE_ROOT"; };
 		14DD0220B41F74C01A9DC676 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_GlyphArrangement.h"; path = "../../JuceLibraryCode/modules/juce_graphics/fonts/juce_GlyphArrangement.h"; sourceTree = "SOURCE_ROOT"; };
 		14FE601229C9A40C6E182F28 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_MouseCursor.mm"; path = "../../JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"; sourceTree = "SOURCE_ROOT"; };
 		1518D2BA7FCAF267EF1F02E6 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_Windowing.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_Windowing.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -604,6 +606,7 @@
 		71CF8F6995DF1BA2038C21D6 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AlertWindow.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_AlertWindow.h"; sourceTree = "SOURCE_ROOT"; };
 		7291F19253205B1A5138908E = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DynamicObject.cpp"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.cpp"; sourceTree = "SOURCE_ROOT"; };
 		72C33BA70B9EE82E39F1EC6C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MP3AudioFormat.h"; path = "../../JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.h"; sourceTree = "SOURCE_ROOT"; };
+		72D50E371901970C428D9E8B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LinearSmoothedValueAtomic.cpp; path = ../../Source/Processors/Dsp/LinearSmoothedValueAtomic.cpp; sourceTree = "SOURCE_ROOT"; };
 		72FCE41894123FC5DB01566B = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_OpenGL_win32.h"; path = "../../JuceLibraryCode/modules/juce_opengl/native/juce_OpenGL_win32.h"; sourceTree = "SOURCE_ROOT"; };
 		7346D1276C3289FD68C8592B = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileFilter.h"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_FileFilter.h"; sourceTree = "SOURCE_ROOT"; };
 		7387114E34496F4606550863 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_HyperlinkButton.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/buttons/juce_HyperlinkButton.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -1140,19 +1143,16 @@
 		E835BEB3C42E4B241804BE13 = {isa = PBXFileReference; lastKnownFileType = file; name = "cpmono-light-serialized"; path = "../../Resources/Fonts/cpmono-light-serialized"; 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"; };
 		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"; };
-		EA354D7D8E48D461415D52D8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_JPEGLoader.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp"; sourceTree = "SOURCE_ROOT"; };
-		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"; };
-		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"; };
+		E97684DCE824DEDA6683C6CD = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Synthesiser.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.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"; };
 		E39CC410838072043E3C30DC = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = OriginalRecording.cpp; path = ../../Source/Processors/RecordNode/OriginalRecording.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"; };
-		E91A272EF06892937CB4B9CE = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentDragger.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.cpp"; 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"; };
+		EA2FC92CECD1EDA1F07DC59C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TooltipWindow.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_TooltipWindow.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"; };
 		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"; };
@@ -1164,6 +1164,8 @@
 		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"; };
+		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"; };
 		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"; };
@@ -1177,6 +1179,7 @@
 		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"; };
 		EFC21F3CD0EB87D67E044E06 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MenuBarComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.h"; sourceTree = "SOURCE_ROOT"; };
 		F06884C6399CB102B1E8A24E = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = rhd2000registers.cpp; path = "../../Source/Processors/DataThreads/RhythmNode/rhythm-api/rhd2000registers.cpp"; sourceTree = "SOURCE_ROOT"; };
@@ -1326,6 +1329,8 @@
 					9AD7314174B2AB01FBF7E1E1,
 					E46FFF196BAA78472FF1C0B4, ); name = PlaceholderProcessor; sourceTree = "<group>"; };
 		F74BE11F6446ACF243895BFF = {isa = PBXGroup; children = (
+					72D50E371901970C428D9E8B,
+					148FE750B55B2F7EA3899408,
 					041038F6E67FE0409D8ECC74,
 					AAF5C27D2EEDD254A3652717,
 					CB5C14E82DE06F767EAD62F9,
@@ -2733,6 +2738,7 @@
 					0AE243437B40602D35435C32,
 					B04B9CA1E59D544793808F25,
 					28B77947820CAE30A5E2DE22,
+					CB568964BDF3E65207B81CCA,
 					9252537C12447F047243DEE9,
 					B081F3F4FA6D8C35E2EEE778,
 					7398C5E00B9093F78C697706,
diff --git a/Builds/VisualStudio2012/open-ephys.vcxproj b/Builds/VisualStudio2012/open-ephys.vcxproj
index 116af7cdf3ca1e497f3bc5f5e2bab01f444d6fc2..21120f81f9ae23dee120e30d3037f692793da0f2 100644
--- a/Builds/VisualStudio2012/open-ephys.vcxproj
+++ b/Builds/VisualStudio2012/open-ephys.vcxproj
@@ -261,6 +261,7 @@
     <ClCompile Include="..\..\Source\Audio\AudioComponent.cpp"/>
     <ClCompile Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessorEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessor.cpp"/>
+    <ClCompile Include="..\..\Source\Processors\Dsp\LinearSmoothedValueAtomic.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Dsp\Bessel.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Dsp\Biquad.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Dsp\Butterworth.cpp"/>
@@ -1467,6 +1468,7 @@
     <ClInclude Include="..\..\Source\Audio\AudioComponent.h"/>
     <ClInclude Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessorEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessor.h"/>
+    <ClInclude Include="..\..\Source\Processors\Dsp\LinearSmoothedValueAtomic.h"/>
     <ClInclude Include="..\..\Source\Processors\Dsp\Bessel.h"/>
     <ClInclude Include="..\..\Source\Processors\Dsp\Biquad.h"/>
     <ClInclude Include="..\..\Source\Processors\Dsp\Butterworth.h"/>
diff --git a/Builds/VisualStudio2012/open-ephys.vcxproj.filters b/Builds/VisualStudio2012/open-ephys.vcxproj.filters
index 3a234111ebc4f18d1ca0106d81073daa1807fe57..9f5e369706d10c0c1c72d226cb21e42df7ef4281 100644
--- a/Builds/VisualStudio2012/open-ephys.vcxproj.filters
+++ b/Builds/VisualStudio2012/open-ephys.vcxproj.filters
@@ -421,6 +421,9 @@
     <ClCompile Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessor.cpp">
       <Filter>open-ephys\Source\Processors\PlaceholderProcessor</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\Source\Processors\Dsp\LinearSmoothedValueAtomic.cpp">
+      <Filter>open-ephys\Source\Processors\Dsp</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\Dsp\Bessel.cpp">
       <Filter>open-ephys\Source\Processors\Dsp</Filter>
     </ClCompile>
@@ -1896,6 +1899,9 @@
     <ClInclude Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessor.h">
       <Filter>open-ephys\Source\Processors\PlaceholderProcessor</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\Source\Processors\Dsp\LinearSmoothedValueAtomic.h">
+      <Filter>open-ephys\Source\Processors\Dsp</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\Dsp\Bessel.h">
       <Filter>open-ephys\Source\Processors\Dsp</Filter>
     </ClInclude>
diff --git a/Builds/VisualStudio2013/open-ephys.sln b/Builds/VisualStudio2013/open-ephys.sln
index 8387e176d9e8917b8d6ef6c803d976565310eab1..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.40629.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 0d8d454711255926ab5335f62676b23ff78865ea..1e3e07d24e5a2e0ca590a404aa0f00b9f85e5c67 100644
--- a/Builds/VisualStudio2013/open-ephys.vcxproj
+++ b/Builds/VisualStudio2013/open-ephys.vcxproj
@@ -265,6 +265,7 @@
     <ClCompile Include="..\..\Source\Audio\AudioComponent.cpp"/>
     <ClCompile Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessorEditor.cpp"/>
     <ClCompile Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessor.cpp"/>
+    <ClCompile Include="..\..\Source\Processors\Dsp\LinearSmoothedValueAtomic.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Dsp\Bessel.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Dsp\Biquad.cpp"/>
     <ClCompile Include="..\..\Source\Processors\Dsp\Butterworth.cpp"/>
@@ -1471,6 +1472,7 @@
     <ClInclude Include="..\..\Source\Audio\AudioComponent.h"/>
     <ClInclude Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessorEditor.h"/>
     <ClInclude Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessor.h"/>
+    <ClInclude Include="..\..\Source\Processors\Dsp\LinearSmoothedValueAtomic.h"/>
     <ClInclude Include="..\..\Source\Processors\Dsp\Bessel.h"/>
     <ClInclude Include="..\..\Source\Processors\Dsp\Biquad.h"/>
     <ClInclude Include="..\..\Source\Processors\Dsp\Butterworth.h"/>
diff --git a/Builds/VisualStudio2013/open-ephys.vcxproj.filters b/Builds/VisualStudio2013/open-ephys.vcxproj.filters
index 4bc39ecd8007e5e3545ea6c32c901ab00a86316b..27f4b1d4849dc1443d4b9d1b3836e75f85a47ee1 100644
--- a/Builds/VisualStudio2013/open-ephys.vcxproj.filters
+++ b/Builds/VisualStudio2013/open-ephys.vcxproj.filters
@@ -421,6 +421,9 @@
     <ClCompile Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessor.cpp">
       <Filter>open-ephys\Source\Processors\PlaceholderProcessor</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\Source\Processors\Dsp\LinearSmoothedValueAtomic.cpp">
+      <Filter>open-ephys\Source\Processors\Dsp</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\Source\Processors\Dsp\Bessel.cpp">
       <Filter>open-ephys\Source\Processors\Dsp</Filter>
     </ClCompile>
@@ -1896,6 +1899,9 @@
     <ClInclude Include="..\..\Source\Processors\PlaceholderProcessor\PlaceholderProcessor.h">
       <Filter>open-ephys\Source\Processors\PlaceholderProcessor</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\Source\Processors\Dsp\LinearSmoothedValueAtomic.h">
+      <Filter>open-ephys\Source\Processors\Dsp</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\Source\Processors\Dsp\Bessel.h">
       <Filter>open-ephys\Source\Processors\Dsp</Filter>
     </ClInclude>
diff --git a/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetectorEditor.cpp b/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetectorEditor.cpp
index 34723c468a78725da659ebe889e6fe440da1a06b..50100748ae1862ae74ec306f33bd89d059ee7d2f 100644
--- a/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetectorEditor.cpp
+++ b/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetectorEditor.cpp
@@ -383,7 +383,7 @@ void SpikeDetectorEditor::buttonEvent(Button* button)
 
 }
 
-void SpikeDetectorEditor::channelChanged(int chan)
+void SpikeDetectorEditor::channelChanged (int channel, bool /*newState*/)
 {
 
     if (electrodeEditorButtons[0]->getToggleState()) // editing is active
@@ -394,13 +394,13 @@ void SpikeDetectorEditor::channelChanged(int chan)
         {
             if (electrodeButtons[i]->getToggleState())
             {
-                electrodeButtons[i]->setChannelNum(chan);
+                electrodeButtons[i]->setChannelNum (channel);
                 electrodeButtons[i]->repaint();
 
                 SpikeDetector* processor = (SpikeDetector*) getProcessor();
                 processor->setChannel(electrodeList->getSelectedItemIndex(),
                                       i,
-                                      chan-1);
+                                      channel - 1);
             }
         }
     }
diff --git a/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetectorEditor.h b/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetectorEditor.h
index 086129d380ae20853eae9a694ae3ab31ea1d631b..07162cd7787d7a516038b5b1a9130f9e0f480cf0 100644
--- a/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetectorEditor.h
+++ b/Source/Plugins/BasicSpikeDisplay/SpikeDetector/SpikeDetectorEditor.h
@@ -58,7 +58,7 @@ public:
     void comboBoxChanged(ComboBox* comboBox);
     void sliderEvent(Slider* slider);
 
-    void channelChanged(int chan);
+    void channelChanged (int channel, bool newState) override;
 
     bool addElectrode(int nChans, int electrodeID = 0);
     void removeElectrode(int index);
diff --git a/Source/Plugins/CAR/CAR.cpp b/Source/Plugins/CAR/CAR.cpp
index 8222d224114329803b0ebbe6ce9e0dc3db34eeae..bb65bf868b07e66241b357a37699a1393210218c 100644
--- a/Source/Plugins/CAR/CAR.cpp
+++ b/Source/Plugins/CAR/CAR.cpp
@@ -46,9 +46,16 @@ AudioProcessorEditor* CAR::createEditor()
 }
 
 
+float CAR::getGainLevel()
+{
+    m_gainLevel.updateTarget();
+    return m_gainLevel.getNextValue();
+}
+
+
 void CAR::setGainLevel (float newGain)
 {
-    m_gainLevel = newGain;
+    m_gainLevel.setValue (newGain);
 }
 
 
@@ -80,7 +87,8 @@ void CAR::process (AudioSampleBuffer& buffer, MidiBuffer& events)
 
     m_avgBuffer.applyGain (1.0f / float (numReferenceChannels));
 
-    const float gain = -1.0f * m_gainLevel / 100.f;
+    m_gainLevel.updateTarget();
+    const float gain = -1.0f * m_gainLevel.getNextValue() / 100.f;
 
     for (int i = 0; i < numAffectedChannels; ++i)
     {
diff --git a/Source/Plugins/CAR/CAR.h b/Source/Plugins/CAR/CAR.h
index ca1929de20cc91e1ccba834743c7d994b346d11b..8f86eb0ce9076e47ae9f7085d2ac6e2ae0d89502 100644
--- a/Source/Plugins/CAR/CAR.h
+++ b/Source/Plugins/CAR/CAR.h
@@ -73,7 +73,7 @@ public:
     void process (AudioSampleBuffer& buffer, MidiBuffer& events) override;
 
     /** Returns the current gain level that is set in the processor */
-    float getGainLevel() const { return m_gainLevel; }
+    float getGainLevel();
 
     /** Sets the new gain level that will be used in the processor */
     void setGainLevel (float newGain);
@@ -92,7 +92,7 @@ public:
 
 
 private:
-    float m_gainLevel;
+    LinearSmoothedValueAtomic<float> m_gainLevel;
 
     AudioSampleBuffer m_avgBuffer;
 
diff --git a/Source/Plugins/CAR/CAREditor.cpp b/Source/Plugins/CAR/CAREditor.cpp
index 59c24025479c5f992af4ea421b8e128c7e679072..8de479043533ded95e2171eabfc8794d18b3029f 100644
--- a/Source/Plugins/CAR/CAREditor.cpp
+++ b/Source/Plugins/CAR/CAREditor.cpp
@@ -68,7 +68,6 @@ CAREditor::CAREditor (GenericProcessor* parentProcessor, bool useDefaultParamete
     addAndMakeVisible (m_gainSlider);
 
     channelSelector->paramButtonsToggledByDefault (false);
-    channelSelector->addListener (this);
 
     setDesiredWidth (280);
 }
@@ -126,7 +125,7 @@ void CAREditor::buttonClicked (Button* buttonThatWasClicked)
 }
 
 
-void CAREditor::channelSelectionChanged (int channel, bool newState)
+void CAREditor::channelChanged (int channel, bool newState)
 {
     auto processor = static_cast<CAR*> (getProcessor());
     if (m_currentChannelsView == REFERENCE_CHANNELS)
diff --git a/Source/Plugins/CAR/CAREditor.h b/Source/Plugins/CAR/CAREditor.h
index 5b66ff13565c9bf59dc9e6a818eeeb3c77789276..f17ca1c0a319cb954d1a6dc935a7eb80c3154864 100644
--- a/Source/Plugins/CAR/CAREditor.h
+++ b/Source/Plugins/CAR/CAREditor.h
@@ -35,7 +35,6 @@ class ParameterSlider;
    @see CAR
 */
 class CAREditor : public GenericEditor
-                , private ChannelSelector::Listener
 {
 public:
     CAREditor (GenericProcessor* parentProcessor, bool useDefaultParameterEditors);
@@ -49,14 +48,11 @@ public:
     // ==========================================================
     void buttonClicked (Button* buttonThatWasClicked) override;
 
-    // ChannelSelector::Listener methods
-    // =========================================================
-    void channelSelectionChanged (int channel, bool newState) override;
-
     // GenericEditor methods
     // =========================================================
     /** This methods is called when any sliders that we are listen for change their values */
     void sliderEvent (Slider* sliderWhichValueHasChanged) override;
+    void channelChanged (int channel, bool newState) override;
 
 
 private:
diff --git a/Source/Plugins/ChannelMappingNode/ChannelMappingEditor.cpp b/Source/Plugins/ChannelMappingNode/ChannelMappingEditor.cpp
index ac4fcbc04094aa967e022b7b72cf48a1bbd6ba10..9835bb378167da213e81dfa802f6dbf7023586de 100644
--- a/Source/Plugins/ChannelMappingNode/ChannelMappingEditor.cpp
+++ b/Source/Plugins/ChannelMappingNode/ChannelMappingEditor.cpp
@@ -612,14 +612,14 @@ void ChannelMappingEditor::setChannelReference(ElectrodeButton* button)
 
 }
 
-void ChannelMappingEditor::channelChanged(int chan)
+void ChannelMappingEditor::channelChanged (int channel, bool /*newState*/)
 {
-    if (!reorderActive)
+    if (! reorderActive)
     {
-        setConfigured(true);
-        getProcessor()->setCurrentChannel(chan-1);
-        getProcessor()->setParameter(2,selectedReference);
-        referenceChannels.set(selectedReference,chan-1);
+        setConfigured (true);
+        getProcessor()->setCurrentChannel (channel - 1);
+        getProcessor()->setParameter (2, selectedReference);
+        referenceChannels.set (selectedReference, channel - 1);
     }
 }
 
diff --git a/Source/Plugins/ChannelMappingNode/ChannelMappingEditor.h b/Source/Plugins/ChannelMappingNode/ChannelMappingEditor.h
index be25bf7c68afd02b3f4d7ada4a06e521296ad890..e2b2408b451440d8902ea021f4d17a499b279338 100644
--- a/Source/Plugins/ChannelMappingNode/ChannelMappingEditor.h
+++ b/Source/Plugins/ChannelMappingNode/ChannelMappingEditor.h
@@ -55,7 +55,7 @@ public:
     void saveCustomParameters(XmlElement* xml);
     void loadCustomParameters(XmlElement* xml);
 
-    void channelChanged(int chan);
+    void channelChanged (int channel, bool newState) override;
 
     void mouseDrag(const MouseEvent& e);
 
diff --git a/Source/Plugins/FilterNode/FilterEditor.cpp b/Source/Plugins/FilterNode/FilterEditor.cpp
index 29a777f869a680ba7eb6a2825669f34da3f0af63..4983f530ce402900b133799b83b893cee6c21fa5 100644
--- a/Source/Plugins/FilterNode/FilterEditor.cpp
+++ b/Source/Plugins/FilterNode/FilterEditor.cpp
@@ -162,13 +162,13 @@ void FilterEditor::labelTextChanged(Label* label)
 
 }
 
-void FilterEditor::channelChanged(int chan)
+void FilterEditor::channelChanged (int channel, bool /*newState*/)
 {
     FilterNode* fn = (FilterNode*) getProcessor();
 
-    highCutValue->setText(String(fn->getHighCutValueForChannel(chan)), dontSendNotification);
-    lowCutValue->setText(String(fn->getLowCutValueForChannel(chan)), dontSendNotification);
-    applyFilterOnChan->setToggleState(fn->getBypassStatusForChannel(chan), dontSendNotification);
+    highCutValue->setText (String (fn->getHighCutValueForChannel (channel)), dontSendNotification);
+    lowCutValue->setText  (String (fn->getLowCutValueForChannel  (channel)), dontSendNotification);
+    applyFilterOnChan->setToggleState (fn->getBypassStatusForChannel (channel), dontSendNotification);
 
 }
 
diff --git a/Source/Plugins/FilterNode/FilterEditor.h b/Source/Plugins/FilterNode/FilterEditor.h
index 2ab56711c588adecabb9acb835709300871ca3d6..79f5df09581ca4773b55429440a03b714201eac4 100644
--- a/Source/Plugins/FilterNode/FilterEditor.h
+++ b/Source/Plugins/FilterNode/FilterEditor.h
@@ -52,7 +52,7 @@ public:
 
     void setDefaults(double lowCut, double highCut);
 
-    void channelChanged(int chan);
+    void channelChanged (int chan, bool newState);
 
 private:
 
diff --git a/Source/Plugins/SpikeSorter/SpikeSorterEditor.cpp b/Source/Plugins/SpikeSorter/SpikeSorterEditor.cpp
index 9bd835626f9d742d5df2d804b15cb3b65c0844c3..bf4bff7e8ac50b7c7878c46919eaf6ecdad37086 100644
--- a/Source/Plugins/SpikeSorter/SpikeSorterEditor.cpp
+++ b/Source/Plugins/SpikeSorter/SpikeSorterEditor.cpp
@@ -494,42 +494,43 @@ void SpikeSorterEditor::setThresholdValue(int channel, double threshold)
     repaint();
 }
 
-void SpikeSorterEditor::channelChanged(int chan)
+void SpikeSorterEditor::channelChanged (int channel, bool newState)
 {
     //std::cout << "New channel: " << chan << std::endl;
-    if (chan <=0)
+    if (channel <= 0)
         return;
 
-    for (int i = 0; i < electrodeButtons.size(); i++)
+    const int numElectrodeButtons = electrodeButtons.size();
+    for (int i = 0; i < numElectrodeButtons; ++i)
     {
         if (electrodeButtons[i]->getToggleState())
         {
-            electrodeButtons[i]->setChannelNum(chan);
+            electrodeButtons[i]->setChannelNum (channel);
             electrodeButtons[i]->repaint();
+
             Array<int> a;
-            a.add(chan-1);
-            channelSelector->setActiveChannels(a);
+            a.add (channel - 1);
+            channelSelector->setActiveChannels (a);
+
             SpikeSorter* processor = (SpikeSorter*) getProcessor();
             processor->setChannel(electrodeList->getSelectedItemIndex(),
                                   i,
-                                  chan-1);
+                                  channel - 1);
 
             // if DAC is selected, update the mapping.
-            int dacchannel = dacCombo->getSelectedId()-2;
+            int dacchannel = dacCombo->getSelectedId() - 2;
             if (dacchannel >=0)
             {
-                processor->assignDACtoChannel(dacchannel, chan-1);
+                processor->assignDACtoChannel (dacchannel, channel - 1);
             }
             if (processor->getAutoDacAssignmentStatus())
             {
-                processor->assignDACtoChannel(0,chan-1);
-                processor->assignDACtoChannel(1,chan-1);
+                processor->assignDACtoChannel (0, channel - 1);
+                processor->assignDACtoChannel (1, channel - 1);
                 break;
             }
-
         }
     }
-
 }
 
 int SpikeSorterEditor::getSelectedElectrode()
diff --git a/Source/Plugins/SpikeSorter/SpikeSorterEditor.h b/Source/Plugins/SpikeSorter/SpikeSorterEditor.h
index 08c51458a3aef0092bc4b2b0d3bc6d7730f02670..b0213feb07963ff5eb7e6ab118df78471e5829c3 100644
--- a/Source/Plugins/SpikeSorter/SpikeSorterEditor.h
+++ b/Source/Plugins/SpikeSorter/SpikeSorterEditor.h
@@ -54,7 +54,7 @@ public:
     void comboBoxChanged(ComboBox* comboBox);
     void sliderEvent(Slider* slider);
 
-    void channelChanged(int chan);
+    void channelChanged (int chan, bool newState) override;
 
     Visualizer* createNewCanvas();
     void checkSettings();
diff --git a/Source/Processors/DataThreads/RhythmNode/RHD2000Editor.cpp b/Source/Processors/DataThreads/RhythmNode/RHD2000Editor.cpp
index 5de38bd7ab3f88297f1dfffbb103066f124014e2..ccf6b80ac99b70457042170d23d7041bf3754c58 100644
--- a/Source/Processors/DataThreads/RhythmNode/RHD2000Editor.cpp
+++ b/Source/Processors/DataThreads/RhythmNode/RHD2000Editor.cpp
@@ -867,16 +867,15 @@ void RHD2000Editor::buttonEvent(Button* button)
 
 }
 
-void RHD2000Editor::channelChanged(int chan)
+void RHD2000Editor::channelChanged (int channel, bool /*newState*/)
 {
     for (int i = 0; i < 2; i++)
     {
         if (electrodeButtons[i]->getToggleState())
         {
-            electrodeButtons[i]->setChannelNum(chan);
+            electrodeButtons[i]->setChannelNum (channel);
             electrodeButtons[i]->repaint();
-            board->setDACchannel(i, chan);
-
+            board->setDACchannel (i, channel);
         }
     }
 }
diff --git a/Source/Processors/DataThreads/RhythmNode/RHD2000Editor.h b/Source/Processors/DataThreads/RhythmNode/RHD2000Editor.h
index ab18fab07484bb46e280b1c8784c546dd9e74f6d..2d784906dd7d0e3cb11a801b009b17d2f72fdfd1 100644
--- a/Source/Processors/DataThreads/RhythmNode/RHD2000Editor.h
+++ b/Source/Processors/DataThreads/RhythmNode/RHD2000Editor.h
@@ -176,7 +176,7 @@ public:
     void startAcquisition();
     void stopAcquisition();
 
-    void channelChanged(int chan);
+    void channelChanged (int channel, bool newState) override;
 
     void saveCustomParameters(XmlElement* xml);
     void loadCustomParameters(XmlElement* xml);
diff --git a/Source/Processors/Dsp/LinearSmoothedValueAtomic.cpp b/Source/Processors/Dsp/LinearSmoothedValueAtomic.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d9b83e757650e8c270f36904760524967d384b15
--- /dev/null
+++ b/Source/Processors/Dsp/LinearSmoothedValueAtomic.cpp
@@ -0,0 +1,99 @@
+/*
+  ==============================================================================
+
+   This file is part of the JUCE library.
+   Copyright (c) 2015 - ROLI Ltd.
+
+   Permission is granted to use this software under the terms of either:
+   a) the GPL v2 (or any later version)
+   b) the Affero GPL v3
+
+   Details of these licenses can be found at: www.gnu.org/licenses
+
+   JUCE 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.
+
+   ------------------------------------------------------------------------------
+
+   To release a closed-source product which uses JUCE, commercial licenses are
+   available: visit www.juce.com for more information.
+
+  ==============================================================================
+*/
+
+#include "LinearSmoothedValueAtomic.h"
+
+
+// Explicit instantiations
+template class LinearSmoothedValueAtomic<float>;
+template class LinearSmoothedValueAtomic<double>;
+
+
+template <typename FloatType>
+LinearSmoothedValueAtomic<FloatType>::LinearSmoothedValueAtomic() noexcept
+    : currentValue  (0)
+    , target        (0)
+    , step          (0)
+    , countdown     (0)
+    , stepsToTarget (0)
+{
+}
+
+
+template <typename FloatType>
+LinearSmoothedValueAtomic<FloatType>::LinearSmoothedValueAtomic (FloatType initialValue) noexcept
+
+    : currentValue  (initialValue)
+    , target        (initialValue)
+    , step          (0)
+    , countdown     (0)
+    , stepsToTarget (0)
+{
+}
+
+
+template<typename FloatType>
+void LinearSmoothedValueAtomic<FloatType>::reset (double sampleRate, double rampLengthInSeconds) noexcept
+{
+    jassert (sampleRate > 0 && rampLengthInSeconds >= 0);
+    stepsToTarget = (int) std::floor (rampLengthInSeconds * sampleRate);
+    currentValue = target;
+    countdown = 0;
+}
+
+
+template<typename FloatType>
+void LinearSmoothedValueAtomic<FloatType>::setValue (FloatType newValue) noexcept
+{
+    target.store (newValue);
+}
+
+
+template<typename FloatType>
+void LinearSmoothedValueAtomic<FloatType>::updateTarget() noexcept
+{
+    FloatType newTarget = target.load();
+    if (newTarget != currentTarget)
+    {
+        currentTarget = newTarget;
+        countdown = stepsToTarget;
+
+        if (countdown <= 0)
+            currentValue = currentTarget;
+        else
+            step = (currentTarget - currentValue) / (FloatType) countdown;
+    }
+}
+
+
+template<typename FloatType>
+FloatType LinearSmoothedValueAtomic<FloatType>::getNextValue() noexcept
+{
+    if (countdown <= 0)
+        return currentTarget;
+
+    --countdown;
+    currentValue += step;
+    return currentValue;
+}
diff --git a/Source/Processors/Dsp/LinearSmoothedValueAtomic.h b/Source/Processors/Dsp/LinearSmoothedValueAtomic.h
new file mode 100644
index 0000000000000000000000000000000000000000..adf81b478c6528601e98ef7bf55c4e1e94ff3fe3
--- /dev/null
+++ b/Source/Processors/Dsp/LinearSmoothedValueAtomic.h
@@ -0,0 +1,89 @@
+/*
+  ==============================================================================
+
+   This file is part of the JUCE library.
+   Copyright (c) 2015 - ROLI Ltd.
+
+   Permission is granted to use this software under the terms of either:
+   a) the GPL v2 (or any later version)
+   b) the Affero GPL v3
+
+   Details of these licenses can be found at: www.gnu.org/licenses
+
+   JUCE 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.
+
+   ------------------------------------------------------------------------------
+
+   To release a closed-source product which uses JUCE, commercial licenses are
+   available: visit www.juce.com for more information.
+
+  ==============================================================================
+*/
+
+#ifndef JUCE_LINEARSMOOTHEDVALUE_H_INCLUDED
+#define JUCE_LINEARSMOOTHEDVALUE_H_INCLUDED
+
+#include "../PluginManager/OpenEphysPlugin.h"
+#include <atomic>
+
+//==============================================================================
+/**
+    Utility class for linearly smoothed values like volume etc. that should
+    not change abruptly but as a linear ramp, to avoid audio glitches.
+
+    This class was modified by Open Ephys and just an improvement of LinearSmoothedValue
+    class from the JUCE 4.0 library, but with some features made that were suggested
+    by Timur Doumler during his JUCE Summit 2015 talk, to make it lock-free and guarantee
+    that no race conditions will ever occur using it.
+
+    Usage:
+    - set value by calling setValue() method;
+
+    - get value by calling updateTarget() and then getNextValue() method.
+      We need to call updateTarget() because we should suppose the value could be changed before
+      so we need to update it smoothly and then use it.
+*/
+
+//==============================================================================
+template<typename FloatType>
+class PLUGIN_API  LinearSmoothedValueAtomic
+{
+public:
+    /** Constructor. */
+    LinearSmoothedValueAtomic() noexcept;
+
+    /** Constructor. */
+    LinearSmoothedValueAtomic (FloatType initialValue) noexcept;
+
+    //==========================================================================
+    /** Reset to a new sample rate and ramp length. */
+    void reset (double sampleRate, double rampLengthInSeconds) noexcept;
+
+    //==========================================================================
+    /** Set a new target value. */
+    void setValue (FloatType newValue) noexcept;
+
+    //==========================================================================
+    void updateTarget() noexcept;
+
+    //==========================================================================
+    /** Compute the next value. */
+    FloatType getNextValue() noexcept;
+
+
+private:
+    //==========================================================================
+    std::atomic<FloatType> target;
+
+    FloatType currentValue;
+    FloatType currentTarget;
+    FloatType step;
+
+    int countdown;
+    int stepsToTarget;
+};
+
+
+#endif   // JUCE_LINEARSMOOTHEDVALUE_H_INCLUDED
diff --git a/Source/Processors/Editors/ChannelSelector.cpp b/Source/Processors/Editors/ChannelSelector.cpp
index 53c02c8fb533f5de0242613167bac85071128bf1..f9fca0de3223322ca88133c2b873a6b1e4eb2c3d 100755
--- a/Source/Processors/Editors/ChannelSelector.cpp
+++ b/Source/Processors/Editors/ChannelSelector.cpp
@@ -610,7 +610,7 @@ void ChannelSelector::buttonClicked(Button* button)
         {
             // send a message to parent
             GenericEditor* editor = (GenericEditor*) getParentComponent();
-            editor->channelChanged(-1);
+            editor->channelChanged (-1, false);
         }
     }
     else
@@ -668,18 +668,15 @@ void ChannelSelector::buttonClicked(Button* button)
         else // parameter type
         {
             GenericEditor* editor = (GenericEditor*) getParentComponent();
-            editor->channelChanged(b->getChannel()-1);
+            editor->channelChanged (b->getChannel() - 1, b->getToggleState());
 
             // do nothing
             if (radioStatus) // if radio buttons are active
             {
                 // send a message to parent
                 GenericEditor* editor = (GenericEditor*) getParentComponent();
-                editor->channelChanged(b->getChannel());
+                editor->channelChanged (b->getChannel(), b->getToggleState());
             }
-
-            m_listeners.call (&ChannelSelector::Listener::channelSelectionChanged,
-                              b->getChannel() - 1, b->getToggleState());
         }
     }
     refreshParameterColors();
diff --git a/Source/Processors/Editors/ChannelSelector.h b/Source/Processors/Editors/ChannelSelector.h
index 77b8af339f3c9972ab1f7ca9c65695d5abea6dd5..ad7bd399220ac3ee47901128944c664413506cc3 100644
--- a/Source/Processors/Editors/ChannelSelector.h
+++ b/Source/Processors/Editors/ChannelSelector.h
@@ -52,19 +52,9 @@ class PLUGIN_API ChannelSelector : public Component
                                  , public Timer
 {
 public:
-    class PLUGIN_API Listener
-    {
-    public:
-        virtual ~Listener() { }
-        virtual void channelSelectionChanged (int channel, bool newState) = 0;
-    };
-
     ChannelSelector(bool createButtons, Font& titleFont);
     ~ChannelSelector();
 
-    void addListener    (Listener* listener) { m_listeners.add (listener); }
-    void removeListener (Listener* listener) { m_listeners.remove (listener); }
-
     /** button callback */
     void buttonClicked(Button* button);
     
@@ -158,8 +148,6 @@ private:
      will be written to disk when the record button is pressed. */
     Array<ChannelSelectorButton*> recordButtons;
 
-    ListenerList<Listener> m_listeners;
-
     bool paramsToggled;
     bool paramsActive;
     bool recActive;
diff --git a/Source/Processors/Editors/GenericEditor.cpp b/Source/Processors/Editors/GenericEditor.cpp
index 96543c97aeb37d5447d2a51839d9de340424ebcb..c41d7caf49077be3cc8ce870543870b42660eb9e 100755
--- a/Source/Processors/Editors/GenericEditor.cpp
+++ b/Source/Processors/Editors/GenericEditor.cpp
@@ -1158,7 +1158,7 @@ void GenericEditor::updateSettings() {}
 
 void GenericEditor::updateVisualizer() {}
 
-void GenericEditor::channelChanged(int chan) {}
+void GenericEditor::channelChanged (int channel, bool newState) {}
 
 void GenericEditor::saveCustomParameters(XmlElement* xml) { }
 
diff --git a/Source/Processors/Editors/GenericEditor.h b/Source/Processors/Editors/GenericEditor.h
index b98f7103eacbebe8f304df816a84067f54d98954..d6481971a04019b4b63d9de3e72678523211a719 100755
--- a/Source/Processors/Editors/GenericEditor.h
+++ b/Source/Processors/Editors/GenericEditor.h
@@ -234,7 +234,7 @@ public:
     virtual void updateVisualizer();
 
     /** Used by SpikeDetectorEditor. */
-    virtual void channelChanged(int chan);
+    virtual void channelChanged (int channel, bool newState);
 
     /** Returns all selected channels from the ChannelSelector. */
     Array<int> getActiveChannels();
diff --git a/Source/Processors/GenericProcessor/GenericProcessor.h b/Source/Processors/GenericProcessor/GenericProcessor.h
index d9aa51173e8c67e3108c8602bb6d5cc49a485cc1..dddaaa25110c86c85a28ef306b44f1004709bc9c 100755
--- a/Source/Processors/GenericProcessor/GenericProcessor.h
+++ b/Source/Processors/GenericProcessor/GenericProcessor.h
@@ -37,6 +37,7 @@ enum ChannelType {HEADSTAGE_CHANNEL = 0, AUX_CHANNEL = 1, ADC_CHANNEL = 2, EVENT
 #include "../Channel/Channel.h"
 #include "../../CoreServices.h"
 #include "../PluginManager/PluginClass.h"
+#include "../../Processors/Dsp/LinearSmoothedValueAtomic.h"
 
 #include <time.h>
 #include <stdio.h>
diff --git a/Source/UI/LookAndFeel/MaterialSliderLookAndFeel.cpp b/Source/UI/LookAndFeel/MaterialSliderLookAndFeel.cpp
index 1915e832ab0722844d5dee84afdd314c79cf3da4..43d422c96f153682b36a41386ee444f63402887b 100644
--- a/Source/UI/LookAndFeel/MaterialSliderLookAndFeel.cpp
+++ b/Source/UI/LookAndFeel/MaterialSliderLookAndFeel.cpp
@@ -2,7 +2,7 @@
     ------------------------------------------------------------------
 
     This file is part of the Open Ephys GUI
-    Copyright (C) 2014 Open Ephys
+    Copyright (C) 2016 Open Ephys
 
     ------------------------------------------------------------------
 
diff --git a/open-ephys.jucer b/open-ephys.jucer
index 4eac922d0c6124f59b736a654009b72ee0bc99f9..c1e548218e6c49a49e4eddf2da6cef85515ada96 100644
--- a/open-ephys.jucer
+++ b/open-ephys.jucer
@@ -292,6 +292,10 @@
                 file="Source/Processors/PlaceholderProcessor/PlaceholderProcessor.h"/>
         </GROUP>
         <GROUP id="{9F37E2FD-6871-8370-4C11-5C97DF132390}" name="Dsp">
+          <FILE id="g34Roi" name="LinearSmoothedValueAtomic.cpp" compile="1"
+                resource="0" file="Source/Processors/Dsp/LinearSmoothedValueAtomic.cpp"/>
+          <FILE id="mwFwwT" name="LinearSmoothedValueAtomic.h" compile="0" resource="0"
+                file="Source/Processors/Dsp/LinearSmoothedValueAtomic.h"/>
           <FILE id="qWmKwI" name="Bessel.cpp" compile="1" resource="0" file="Source/Processors/Dsp/Bessel.cpp"/>
           <FILE id="bRbpDP" name="Bessel.h" compile="0" resource="0" file="Source/Processors/Dsp/Bessel.h"/>
           <FILE id="olRf2q" name="Biquad.cpp" compile="1" resource="0" file="Source/Processors/Dsp/Biquad.cpp"/>