/*
 *
 *    soniK digital audio editor
 *    Copyright (C) 2003-2006  Robert Walker <rob@tenfoot.org.uk>
 *
 *    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 2 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, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */
#include "sonik_sigproc.h"
#include "sonik_types.h"

#include <cppunit/extensions/HelperMacros.h>

#include "test.h"

#include <cstdio>
#include <iterator>
#include <fstream>
#include <iostream>

namespace Sonik
{
  class WindowTest : public CppUnit::TestFixture
  {
    CPPUNIT_TEST_SUITE( WindowTest );
    CPPUNIT_TEST( testRectangular );
    CPPUNIT_TEST( testTriangular );
    CPPUNIT_TEST( testBartlett );
    CPPUNIT_TEST( testBlackman );
    CPPUNIT_TEST( testChebyshev );
    CPPUNIT_TEST( testHamming );
    CPPUNIT_TEST( testHann );
    CPPUNIT_TEST( testKaiser );
    CPPUNIT_TEST_SUITE_END();

  public:
    void testRectangular();
    void testTriangular();
    void testBartlett();
    void testBlackman();
    void testChebyshev();
    void testHamming();
    void testHann();
    void testKaiser();

  private:
    void checkWindowData(Sonik::WindowFunction f, size_t sz);
    void checkWindow(Sonik::WindowFunction f);
  };
}

CPPUNIT_TEST_SUITE_REGISTRATION(Sonik::WindowTest);

void Sonik::WindowTest::checkWindowData(Sonik::WindowFunction f, size_t sz)
{
  QString windowName = windowToString(f);
  Sonik::SampleBuffer w(sz);

  std::cout << f << ", " << sz << std::endl;

  makeWindow(w.data(), w.size(), f);

  Sonik::SampleBuffer exp(sz);

  QString expFile = QString("data/twindow.%1.%2.dat").arg(windowName).arg(sz);
  FILE* expFd = std::fopen(expFile.latin1(), "rb");
  if (expFd == 0)
    CPPUNIT_FAIL("Failed to open expected data file");

  size_t r = fread(exp.data(), sizeof(Sonik::Sample), exp.size(), expFd);
  CPPUNIT_ASSERT_EQUAL(r, sz);
  fclose(expFd);

  CHECK_BUFFER_EQ(w, exp);
}

void Sonik::WindowTest::checkWindow(Sonik::WindowFunction w)
{
  std::vector<size_t> sizes;

  std::ifstream in("twindow.dat");
  CPPUNIT_ASSERT(in.is_open());
  std::copy(std::istream_iterator<size_t>(in), std::istream_iterator<size_t>(),
            std::back_inserter(sizes));

  for (std::vector<size_t>::const_iterator s = sizes.begin();
       s != sizes.end();
       ++s)
  {
    checkWindowData(w, *s);
  }
}


void Sonik::WindowTest::testRectangular()
{
  checkWindow(Sonik::RECTANGULAR);
}


void Sonik::WindowTest::testTriangular()
{
  checkWindow(Sonik::TRIANGULAR);
}


void Sonik::WindowTest::testBartlett()
{
  checkWindow(Sonik::BARTLETT);
}


void Sonik::WindowTest::testBlackman()
{
  checkWindow(Sonik::BLACKMAN);
}


void Sonik::WindowTest::testChebyshev()
{
  checkWindow(Sonik::CHEBYSHEV);
}


void Sonik::WindowTest::testHamming()
{
  checkWindow(Sonik::HAMMING);
}


void Sonik::WindowTest::testHann()
{
  checkWindow(Sonik::HANN);
}


void Sonik::WindowTest::testKaiser()
{
  checkWindow(Sonik::KAISER);
}
