diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,6 +62,7 @@ add_executable(${PROGRAM_NAME} WIN32
   plot.cpp
   zoomer.cpp
   hidabletabwidget.cpp
+  framebuffer.cpp
   ${UI_FILES}
   misc/windows_icon.rc
   )
diff --git a/framebuffer.cpp b/framebuffer.cpp
new file mode 100644
--- /dev/null
+++ b/framebuffer.cpp
@@ -0,0 +1,98 @@
+/*
+  Copyright © 2015 Hasan Yavuz Özderya
+
+  This file is part of serialplot.
+
+  serialplot 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.
+
+  serialplot 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 serialplot.  If not, see .
+*/
+
+#include "framebuffer.h"
+
+FrameBuffer::FrameBuffer(size_t size) :
+    data(size, 0.)
+{
+
+}
+
+void FrameBuffer::resize(size_t size)
+{
+    size_t old_size = this->size();
+    size_t new_size = size;
+
+    if (new_size < old_size)
+    {
+        data.remove(0, old_size - new_size);
+    }
+    else if (new_size > old_size)
+    {
+        // This is seriously inefficient!
+        for (size_t i = old_size; i < new_size; i++)
+        {
+            data.prepend(0);
+        }
+    }
+}
+
+void FrameBuffer::addSamples(QVector samples)
+{
+    int offset = size() - samples.size();
+
+    if (offset < 0)
+    {
+        // new samples exceed the size of frame buffer
+        // excess part (from beginning) of the input will be ignored
+        for (unsigned int i = 0; i < size(); i++)
+        {
+            data[i] = samples[i - offset];
+        }
+    }
+    else if (offset == 0) // input is the same size as the framebuffer
+    {
+        data = samples;
+    }
+    else // regular case; input is smaller than framebuffer
+    {
+        // shift old samples
+        int shift = samples.size();
+        for (int i = 0; i < offset; i++)
+        {
+            data[i] = data[i + shift];
+        }
+        // place new samples
+        for (int i = 0; i < samples.size(); i++)
+        {
+            data[offset + i] = samples[i];
+        }
+    }
+}
+
+void FrameBuffer::clear()
+{
+    data.fill(0);
+}
+
+size_t FrameBuffer::size() const
+{
+    return (size_t) data.size();
+}
+
+QPointF FrameBuffer::sample(size_t i) const
+{
+    return QPointF(i, data[i]);
+}
+
+QRectF FrameBuffer::boundingRect() const
+{
+    return qwtBoundingRect(*this);
+}
diff --git a/framebuffer.h b/framebuffer.h
new file mode 100644
--- /dev/null
+++ b/framebuffer.h
@@ -0,0 +1,45 @@
+/*
+  Copyright © 2015 Hasan Yavuz Özderya
+
+  This file is part of serialplot.
+
+  serialplot 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.
+
+  serialplot 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 serialplot.  If not, see .
+*/
+
+#ifndef FRAMEBUFFER_H
+#define FRAMEBUFFER_H
+
+#include 
+#include 
+#include 
+
+class FrameBuffer : public QwtSeriesData
+{
+public:
+    FrameBuffer(size_t size);
+
+    void resize(size_t size);
+    void addSamples(QVector samples);
+    void clear(); // fill 0
+
+    // QwtSeriesData implementations
+    size_t size() const;
+    QPointF sample(size_t i) const;
+    QRectF boundingRect() const;
+
+private:
+    QVector data;
+};
+
+#endif // FRAMEBUFFER_H
diff --git a/main.cpp b/main.cpp
--- a/main.cpp
+++ b/main.cpp
@@ -23,6 +23,12 @@
 
 #include "version.h"
 
+// TEST CODE
+#include "framebuffer.h"
+// #include 
+#include 
+#include 
+
 MainWindow* pMainWindow;
 
 void messageHandler(QtMsgType type, const QMessageLogContext &context,
@@ -45,5 +51,33 @@ int main(int argc, char *argv[])
     qDebug() << "Revision" << VERSION_REVISION;
 
     w.show();
+
+    // test framebuffer
+    FrameBuffer buffer(10);
+    QVector s(3,15.);
+    s.append(1.0);
+    s.append(2.0);
+    s.append(3.0);
+    buffer.addSamples(s);
+    // buffer.addSamples(s);
+    // buffer.resize(5);
+    QwtPlot plot;
+    QwtPlotCurve curve;
+    curve.setSamples(&buffer);
+    curve.attach(&plot);
+    plot.show();
+    qDebug() << buffer.sample(0);
+    qDebug() << buffer.sample(1);
+    qDebug() << "size:" << buffer.size();
+    buffer.addSamples(s);
+    // curve.setSamples(&buffer);
+    plot.replot();
+    // qDebug() << buffer.sample(5);
+    // qDebug() << buffer.sample(7);
+    // qDebug() << buffer.sample(8);
+    // qDebug() << buffer.sample(9);
+    // qDebug() << buffer.sample(15);
+    // qDebug() << buffer.sample(19);
+
     return a.exec();
 }
diff --git a/mainwindow.cpp b/mainwindow.cpp
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -137,18 +137,12 @@ MainWindow::MainWindow(QWidget *parent) 
     numOfSamples = ui->spNumOfSamples->value();
     numOfChannels = 1;
 
-    dataX.resize(numOfSamples);
-    for (int i = 0; i < dataX.size(); i++)
-    {
-        dataX[i] = i;
-    }
-
     // init channel data and curve list
     for (unsigned int i = 0; i < numOfChannels; i++)
     {
-        channelsData.append(DataArray(numOfSamples, 0.0));
+        channelBuffers.append(new FrameBuffer(numOfSamples));
         curves.append(new QwtPlotCurve());
-        curves[i]->setSamples(dataX, channelsData[i]);
+        curves[i]->setSamples(channelBuffers[i]);
         curves[i]->setPen(makeColor(i));
         curves[i]->attach(ui->plot);
     }
@@ -205,6 +199,7 @@ MainWindow::~MainWindow()
 {
     for (auto curve : curves)
     {
+        // also deletes respective FrameBuffer
         delete curve;
     }
 
@@ -396,39 +391,8 @@ void MainWindow::skipByte()
 
 void MainWindow::addChannelData(unsigned int channel, DataArray data)
 {
-    DataArray* channelDataArray = &(channelsData[channel]);
-    int offset = numOfSamples - data.size();
-
-    if (offset < 0)
-    {
-        for (unsigned int i = 0; i < numOfSamples; i++)
-        {
-            (*channelDataArray)[i] = data[i - offset];
-        }
-    }
-    else if (offset == 0)
-    {
-        (*channelDataArray) = data;
-    }
-    else
-    {
-        // shift old samples
-        int shift = data.size();
-        for (int i = 0; i < offset; i++)
-        {
-            (*channelDataArray)[i] = (*channelDataArray)[i + shift];
-        }
-        // place new samples
-        for (int i = 0; i < data.size(); i++)
-        {
-            (*channelDataArray)[offset + i] = data[i];
-        }
-    }
-
-    // update plot
-    curves[channel]->setSamples(dataX, (*channelDataArray));
+    channelBuffers[channel]->addSamples(data);
     ui->plot->replot(); // TODO: replot after all channel data updated
-
     sampleCount += data.size();
 }
 
@@ -436,51 +400,21 @@ void MainWindow::clearPlot()
 {
     for (unsigned int ci = 0; ci < numOfChannels; ci++)
     {
-        channelsData[ci].fill(0.0);
-        curves[ci]->setSamples(dataX, channelsData[ci]);
+        channelBuffers[ci]->clear();
     }
-
-    // update plot
     ui->plot->replot();
 }
 
 void MainWindow::onNumOfSamplesChanged(int value)
 {
-    unsigned int oldNum = this->numOfSamples;
     numOfSamples = value;
 
-    // resize data arrays
-    if (numOfSamples < oldNum)
-    {
-        dataX.resize(numOfSamples);
-        for (unsigned int ci = 0; ci < numOfChannels; ci++)
-        {
-            channelsData[ci].remove(0, oldNum - numOfSamples);
-            curves[ci]->setSamples(dataX, channelsData[ci]);
-        }
-        ui->plot->replot();
-    }
-    else if(numOfSamples > oldNum)
+    for (unsigned int ci = 0; ci < numOfChannels; ci++)
     {
-        // update data arrays
-        dataX.resize(numOfSamples);
-        for (unsigned int i = oldNum; i < numOfSamples; i++)
-        {
-            dataX[i] = i;
-            for (unsigned int ci = 0; ci < numOfChannels; ci++)
-            {
-                // TODO: opportunity of major optimization here
-                //       let's hope nobody sees this
-                channelsData[ci].prepend(0);
-            }
-        }
-        // update curves
-        for (unsigned int ci = 0; ci < numOfChannels; ci++)
-        {
-            curves[ci]->setSamples(dataX, channelsData[ci]);
-        }
-        ui->plot->replot();
+        channelBuffers[ci]->resize(numOfSamples);
     }
+
+    ui->plot->replot();
 }
 
 void MainWindow::onNumOfChannelsChanged(int value)
@@ -493,9 +427,9 @@ void MainWindow::onNumOfChannelsChanged(
         // add new channels
         for (unsigned int i = 0; i < numOfChannels - oldNum; i++)
         {
-            channelsData.append(DataArray(numOfSamples, 0.0));
+            channelBuffers.append(new FrameBuffer(numOfSamples));
             curves.append(new QwtPlotCurve());
-            curves.last()->setSamples(dataX, channelsData.last());
+            curves.last()->setSamples(channelBuffers.last());
             curves.last()->setPen(makeColor(curves.length()-1));
             curves.last()->attach(ui->plot);
         }
@@ -505,10 +439,9 @@ void MainWindow::onNumOfChannelsChanged(
         // remove channels
         for (unsigned int i = 0; i < oldNum - numOfChannels; i++)
         {
-            channelsData.removeLast();
-            auto curve = curves.takeLast();
-            curve->detach();
-            delete curve;
+            // also deletes owned FrameBuffer
+            delete curves.takeLast();
+            channelBuffers.removeLast();
         }
     }
 }
@@ -732,7 +665,7 @@ void MainWindow::onExportCsv()
             {
                 for (unsigned int ci = 0; ci < numOfChannels; ci++)
                 {
-                    fileStream << channelsData[ci][i];
+                    fileStream << channelBuffers[ci]->sample(i).y();
                     if (ci != numOfChannels-1) fileStream << ",";
                 }
                 fileStream << '\n';
diff --git a/mainwindow.h b/mainwindow.h
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -36,6 +36,7 @@
 
 #include "portcontrol.h"
 #include "ui_about_dialog.h"
+#include "framebuffer.h"
 
 namespace Ui {
 class MainWindow;
@@ -79,8 +80,8 @@ private:
 
     QList curves;
     typedef QVector DataArray;
-    DataArray dataX;   // array that simply contains numbers 0..numberOfSamples
-    QList channelsData;
+    // Note: FrameBuffer s are owned by their respective QwtPlotCurve s.
+    QList channelBuffers;
 
     // `data` contains i th channels data
     void addChannelData(unsigned int channel, DataArray data);
diff --git a/serialplot.pro b/serialplot.pro
--- a/serialplot.pro
+++ b/serialplot.pro
@@ -39,7 +39,8 @@ SOURCES += main.cpp\
     portcontrol.cpp \
     plot.cpp \
     zoomer.cpp \
-    hidabletabwidget.cpp
+    hidabletabwidget.cpp \
+    framebuffer.cpp
 
 HEADERS  += mainwindow.h \
     utils.h \
@@ -48,7 +49,8 @@ HEADERS  += mainwindow.h \
     floatswap.h \
     plot.h \
     zoomer.h \
-    hidabletabwidget.h
+    hidabletabwidget.h \
+    framebuffer.h
 
 FORMS    += mainwindow.ui \
     about_dialog.ui \