diff --git a/Source/Plugins/LfpDisplayNode/LfpDisplayCanvas.cpp b/Source/Plugins/LfpDisplayNode/LfpDisplayCanvas.cpp
index 87b9778be62e780b8f7c57b9aa3e9b14920e65fa..4e3066c066f2e4d153708b85b0d3c149a63bd28c 100644
--- a/Source/Plugins/LfpDisplayNode/LfpDisplayCanvas.cpp
+++ b/Source/Plugins/LfpDisplayNode/LfpDisplayCanvas.cpp
@@ -230,6 +230,19 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) :
     drawMethodButton->setClickingTogglesState(true);
     drawMethodButton->setToggleState(false, sendNotification);
     addAndMakeVisible(drawMethodButton);
+    
+    // two sliders for the two histogram components of the supersampled plotting mode
+    histogramSlider = new Slider;
+    histogramSlider->setRange (0, 1);
+    histogramSlider->addListener(this);
+    addAndMakeVisible (histogramSlider);
+    
+    supersampleSlider = new Slider;
+    supersampleSlider->setRange (0, 1);
+    supersampleSlider->addListener(this);
+    addAndMakeVisible (supersampleSlider);
+    
+    
 
     //button for pausing the display - works by skipping buffer updates. This way scrolling etc still works
     pauseButton = new UtilityButton("Pause", Font("Small Text", 13, Font::plain));
@@ -262,6 +275,17 @@ LfpDisplayCanvas::LfpDisplayCanvas(LfpDisplayNode* processor_) :
         lfpDisplay->setEventDisplayState(i,true);
 
     }
+    
+    // allocate samplesPerPixel, behaves like float samplesPerPixel[nChans][MAX_N_SAMP][MAX_N_SAMP_PER_PIXEL]
+    samplesPerPixel = (float***)malloc(nChans * sizeof(float **));
+    for(int i=0;i<nChans;i++)
+    {
+        samplesPerPixel[i] = (float**)malloc(MAX_N_SAMP * sizeof(float*));
+        for(int j=0;j<MAX_N_SAMP;j++)
+        {
+            samplesPerPixel[i][j] = (float*)malloc(MAX_N_SAMP_PER_PIXEL*sizeof(float));
+        }
+    }
 
     TopLevelWindow::getTopLevelWindow(0)->addKeyListener(this);
 }
@@ -274,6 +298,19 @@ LfpDisplayCanvas::~LfpDisplayCanvas()
     deleteAndZero(screenBufferMean);
     deleteAndZero(screenBufferMax);
 
+    // de-allocate 3d-array samplesPerPixel [nChans][MAX_N_SAMP][MAX_N_SAMP_PER_PIXEL];
+
+    for(int i=0;i<nChans;i++)
+    {
+        for(int j=0;j<MAX_N_SAMP;j++)
+        {
+            free(samplesPerPixel[i][j]);
+        }
+        free(samplesPerPixel[i]);
+    }
+    free(samplesPerPixel);
+    
+    
     TopLevelWindow::getTopLevelWindow(0)->removeKeyListener(this);
 }
 
@@ -302,7 +339,10 @@ void LfpDisplayCanvas::resized()
         eventDisplayInterfaces[i]->setBounds(500+(floor(i/2)*20), getHeight()-40+(i%2)*20, 40, 20); // arrange event channel buttons in two rows
         eventDisplayInterfaces[i]->repaint();
     }
-
+    
+    histogramSlider->setBounds(1000,getHeight()-50,200,22);
+    supersampleSlider->setBounds(1000,getHeight()-25,200,22);
+    
     int bh = 25/typeButtons.size();
     for (int i = 0; i < typeButtons.size(); i++)
     {
@@ -574,6 +614,15 @@ void LfpDisplayCanvas::comboBoxChanged(ComboBox* cb)
 }
 
 
+void sliderValueChanged (Slider* slider)
+{
+   // if (slider == &frequencySlider)
+    //    durationSlider.setValue (1.0 / frequencySlider.getValue(), dontSendNotification);
+   // else if (slider == &durationSlider)
+   //     frequencySlider.setValue (1.0 / durationSlider.getValue(), dontSendNotification);
+}
+
+
 int LfpDisplayCanvas::getChannelHeight()
 {
     return spreads[spreadSelection->getSelectedId()-1].getIntValue();
@@ -753,9 +802,10 @@ void LfpDisplayCanvas::updateScreenBuffer()
                     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
                     
+                    int c = 0;
                     for (int j = dbi; j < nextpix; j++)
                     {
                         float sample_current = displayBuffer->getSample(channel, j);
@@ -771,14 +821,30 @@ void LfpDisplayCanvas::updateScreenBuffer()
                             sample_max=sample_current;
                         }
                         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);
-                
+                    
+                    // similarly, for each pixel on the screen, we want a list of all values so we can draw a histogram later
+                    // for simplicity, we'll just do this as 2d array, samplesPerPixel[px][samples]
+                    // with an additional array sampleCountPerPixel[px] that holds the N samples per pixel
+                    if (channel < nChans) // we're looping over one 'extra' channel for events above, so make sure not to loop over that one here
+                        {
+                            c = 0;
+                            for (int j = dbi; j < nextpix & c < MAX_N_SAMP_PER_PIXEL; j++)
+                            {
+                                float sample_current = displayBuffer->getSample(channel, j);
+                                samplesPerPixel[channel][sbi][c]=sample_current;
+                                c++;
+                            }
+                            if (c>0){
+                                sampleCountPerPixel[sbi]=c-1; // save count of samples for this pixel
+                            }else{
+                                sampleCountPerPixel[sbi]=0;
+                            }
+                            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++;
                 }
             
@@ -832,6 +898,16 @@ const float LfpDisplayCanvas::getYCoordMax(int chan, int samp)
     return *screenBufferMax->getReadPointer(chan, samp);
 }
 
+const float* LfpDisplayCanvas::getSamplesPerPixel(int chan, int px)
+{
+    return samplesPerPixel[chan][px];
+}
+const int LfpDisplayCanvas::getSampleCountPerPixel(int px)
+{
+    return sampleCountPerPixel[px];
+}
+
+
 
 bool LfpDisplayCanvas::getInputInvertedState()
 {
@@ -1078,6 +1154,14 @@ int LfpDisplayCanvas::getRangeStep(ChannelType type)
     return rangeSteps[type];
 }
 
+void LfpDisplayCanvas::sliderValueChanged(Slider* slider)
+{
+    
+    sliderEvent(slider);
+}
+
+void LfpDisplayCanvas::sliderEvent(Slider* slider) {}
+
 // -------------------------------------------------------------
 
 LfpTimescale::LfpTimescale(LfpDisplayCanvas* c) : canvas(c)
@@ -1785,37 +1869,118 @@ void LfpChannelDisplay::paint(Graphics& g)
             }
 
             //std::cout << "e " << canvas->getYCoord(canvas->getNumChannels()-1, i) << std::endl;
-            g.setColour(lineColour);
-
-            if (drawMethod) // switched between to line drawing and pixel wise drawing
+            
+            
+            // set max-min range for plotting, used in all methods
+            double a = (canvas->getYCoordMax(chan, i)/range*channelHeightFloat)+getHeight()/2;
+            double b = (canvas->getYCoordMin(chan, i)/range*channelHeightFloat)+getHeight()/2;
+            //double m = (canvas->getYCoordMean(chan, i)/range*channelHeightFloat)+getHeight()/2;
+            if (a<b)
             {
-
-                // drawLine makes for ok anti-aliased plots, but is pretty slow
-                g.drawLine(i,
-                           (canvas->getYCoord(chan, i)/range*channelHeightFloat)+getHeight()/2,
-                           i+stepSize,
-                           (canvas->getYCoord(chan, i+stepSize)/range*channelHeightFloat)+getHeight()/2);
-
-
+                from = (a);
+                to = (b);
             }
             else
             {
+                from = (b);
+                to = (a);
+            }
+            int samplerange=to-from;
 
-                // // pixel wise line plot has no anti-aliasing, but runs much faster
-                double a = (canvas->getYCoordMax(chan, i)/range*channelHeightFloat)+getHeight()/2;
-                double b = (canvas->getYCoordMin(chan, i)/range*channelHeightFloat)+getHeight()/2;
-                //double m = (canvas->getYCoordMean(chan, i)/range*channelHeightFloat)+getHeight()/2;
-                if (a<b)
-                {
-                    from = (a);
-                    to = (b);
-                }
-                else
+            if (drawMethod) // switched between 'supersampled' drawing and simple pixel wise drawing
+            { // histogram based supersampling method
+
+                const float *samplesThisPixel = canvas->getSamplesPerPixel(chan, i);
+                int sampleCountThisPixel = canvas->getSampleCountPerPixel(i);
+
+                if (samplerange>0 & sampleCountThisPixel>1)
                 {
-                    from = (b);
-                    to = (a);
+                    // drawLine makes for ok anti-aliased plots, but is pretty slow
+                    //g.drawLine(i,
+                    //           (canvas->getYCoord(chan, i)/range*channelHeightFloat)+getHeight()/2,
+                    //           i+stepSize,
+                    //           (canvas->getYCoord(chan, i+stepSize)/range*channelHeightFloat)+getHeight()/2);
+                    
+                    
+                    //double a = (samplesThisPixel[sampleCountThisPixel]/range*channelHeightFloat)+getHeight()/2;
+                    //g.setPixel(i,a);
+                    float localHist[samplerange]; // simple histogram
+                    float rangeHist[samplerange]; // paired range histogram, same as plotting at higher res. and subsampling
+                    
+                    for (int k=0; k<samplerange; k++)
+                    {
+                        localHist[k]=0;
+                        rangeHist[k]=0;
+                    }
+                    
+                    /*
+                    for (int k=0; k<=sampleCountThisPixel; k++) // add up simple histogram
+                    {
+                        int cs = (((samplesThisPixel[k]/range*channelHeightFloat)+getHeight()/2)-from);
+                        if (cs<0) {cs=0;};
+                        if (cs>samplerange) {cs=samplerange;};
+                        localHist[cs]++;
+                    }
+                    */
+                    
+                    for (int k=0; k<=sampleCountThisPixel; k++) // add up simple paired-range histogram - for each pair fill intermediate with uniform distr.
+                    {
+                        int cs_this      = (((samplesThisPixel[k]/range*channelHeightFloat)+getHeight()/2)-from);
+                        int cs_next = (((samplesThisPixel[k+1]/range*channelHeightFloat)+getHeight()/2)-from);
+                        
+                        if (cs_this<0) {cs_this=0;};
+                        if (cs_this>samplerange) {cs_this=samplerange;};
+                        if (cs_next<0) {cs_next=0;};
+                        if (cs_next>samplerange) {cs_next=samplerange;};
+
+                        int hfrom=0;
+                        int hto=0;
+                        
+                        if (cs_this<cs_next)
+                        {
+                             hfrom = (cs_this);  hto = (cs_next);
+                        }
+                        else
+                        {
+                             hfrom = (cs_next);  hto = (cs_this);
+                        }
+                        int hrange=hto-hfrom;
+                        float ha=1;
+                        for (int l=hfrom; l<=hto; l++)
+                        {
+                            rangeHist[l]+=ha;
+                        }
+                    }
+                    
+                    
+                    for (int s = 0; s < samplerange; s ++)
+                    {
+                        float a=(rangeHist[s])/(sampleCountThisPixel/2);
+                        if (a>1.0f) {a=1.0f;};
+                        if (a<0.0f) {a=0.0f;};
+                        
+                        
+                        //g.setColour( lineColour.interpolatedWith(Colour(255,255,255),0.5f).withAlpha(a) ); // mix in 50% white, alpha from histogram
+                        g.setColour( lineColour.withMultipliedBrightness(2.0f).interpolatedWith(lineColour.withSaturation(0.1f).withMultipliedBrightness(0.4f),1-a) );
+                        
+                        g.setPixel(i,from+s);
+                    }
+                    
+                } else {
+                    g.setColour(lineColour);
+                    g.setPixel(i,from);
+                    
+                
                 }
-
+                
+                
+                
+            }
+            else
+            { // simple per-pixel min-max drawing
+                // pixel wise line plot has no anti-aliasing, but runs much faster
+                
+                g.setColour(lineColour);
                 //g.setColour(lineColour.withMultipliedBrightness( 1+(((((float)(to-from)*range)/getHeight())-0.01)*2)  )); // make spikes etc slightly brighter
 
 
@@ -2059,6 +2224,7 @@ void LfpChannelDisplayInfo::resized()
 }
 
 
+
 // Event display Options --------------------------------------------------------------------
 
 EventDisplayInterface::EventDisplayInterface(LfpDisplay* display_, LfpDisplayCanvas* canvas_, int chNum):
diff --git a/Source/Plugins/LfpDisplayNode/LfpDisplayCanvas.h b/Source/Plugins/LfpDisplayNode/LfpDisplayCanvas.h
index 0e99bf01dc1058ee1001a2f3a05a262c373e6648..d78670c5ea0942755f1aa53d073f75d7d095cda9 100644
--- a/Source/Plugins/LfpDisplayNode/LfpDisplayCanvas.h
+++ b/Source/Plugins/LfpDisplayNode/LfpDisplayCanvas.h
@@ -46,10 +46,10 @@ class LfpViewport;
 */
 
 class LfpDisplayCanvas : public Visualizer,
+    public Slider::Listener,
     public ComboBox::Listener,
     public Button::Listener,
     public KeyListener
-
 {
 public:
     LfpDisplayCanvas(LfpDisplayNode* n);
@@ -81,7 +81,10 @@ public:
 
     const float getXCoord(int chan, int samp);
     const float getYCoord(int chan, int samp);
-
+    
+    const float *getSamplesPerPixel(int chan, int px);
+    const int getSampleCountPerPixel(int px);
+    
     const float getYCoordMin(int chan, int samp);
     const float getYCoordMean(int chan, int samp);
     const float getYCoordMax(int chan, int samp);
@@ -91,7 +94,14 @@ public:
 
     void comboBoxChanged(ComboBox* cb);
     void buttonClicked(Button* button);
-
+    
+    /** Handles slider events for all editors. */
+    void sliderValueChanged(Slider* slider);
+    
+    /** Called by sliderValueChanged(). Deals with clicks on custom sliders. Subclasses
+     of GenericEditor should modify this method only.*/
+    void sliderEvent(Slider* slider);
+    
     void saveVisualizerParameters(XmlElement* xml);
     void loadVisualizerParameters(XmlElement* xml);
 
@@ -125,6 +135,7 @@ private:
 
     static const int MAX_N_CHAN = 2048;  // maximum number of channels
     static const int MAX_N_SAMP = 5000; // maximum display size in pixels
+    static const int MAX_N_SAMP_PER_PIXEL = 1000; // maximum samples considered for dreawing each pixel
     //float waves[MAX_N_CHAN][MAX_N_SAMP*2]; // we need an x and y point for each sample
 
     LfpDisplayNode* processor;
@@ -151,6 +162,10 @@ private:
     ScopedPointer<UtilityButton> drawMethodButton;
     ScopedPointer<UtilityButton> pauseButton;
     OwnedArray<UtilityButton> typeButtons;
+    
+    
+    ScopedPointer<Slider> histogramSlider;
+    ScopedPointer<Slider> supersampleSlider;
 
     StringArray voltageRanges[CHANNEL_TYPES];
     StringArray timebases;
@@ -180,6 +195,10 @@ private:
     int displayBufferSize;
 
     int scrollBarThickness;
+    
+    //float samplesPerPixel[MAX_N_SAMP][MAX_N_SAMP_PER_PIXEL];
+    float*** samplesPerPixel;
+    int sampleCountPerPixel[MAX_N_SAMP];
 
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LfpDisplayCanvas);