Chris@1359: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@1359: 
Chris@1359: /*
Chris@1359:     Sonic Visualiser
Chris@1359:     An audio file viewer and annotation editor.
Chris@1359:     Centre for Digital Music, Queen Mary, University of London.
Chris@1359:     
Chris@1359:     This program is free software; you can redistribute it and/or
Chris@1359:     modify it under the terms of the GNU General Public License as
Chris@1359:     published by the Free Software Foundation; either version 2 of the
Chris@1359:     License, or (at your option) any later version.  See the file
Chris@1359:     COPYING included with this distribution for more information.
Chris@1359: */
Chris@1359: 
Chris@1359: #ifndef TEST_AUDIO_FILE_WRITER_H
Chris@1359: #define TEST_AUDIO_FILE_WRITER_H
Chris@1359: 
Chris@1359: #include "../AudioFileReaderFactory.h"
Chris@1359: #include "../AudioFileReader.h"
Chris@1359: #include "../WavFileWriter.h"
Chris@1359: 
Chris@1359: #include "AudioTestData.h"
Chris@1359: 
Chris@1359: #include "bqvec/VectorOps.h"
Chris@1359: #include "bqvec/Allocators.h"
Chris@1359: 
Chris@1359: #include <cmath>
Chris@1359: 
Chris@1359: #include <QObject>
Chris@1359: #include <QtTest>
Chris@1359: #include <QDir>
Chris@1359: 
Chris@1359: #include <iostream>
Chris@1359: 
Chris@1359: using namespace std;
Chris@1359: using namespace breakfastquay;
Chris@1359: 
Chris@1359: class AudioFileWriterTest : public QObject
Chris@1359: {
Chris@1359:     Q_OBJECT
Chris@1359: 
Chris@1359: private:
Chris@1359:     QString testDirBase;
Chris@1359:     QString outDir;
Chris@1359: 
Chris@1359:     static const int rate = 44100;
Chris@1359:     
Chris@1359: public:
Chris@1359:     AudioFileWriterTest(QString base) {
Chris@1359:         if (base == "") {
Chris@1359:             base = "svcore/data/fileio/test";
Chris@1359:         }
Chris@1359:         testDirBase = base;
Chris@1359:         outDir = base + "/outfiles";
Chris@1359:     }
Chris@1359: 
Chris@1359:     const char *strOf(QString s) {
Chris@1359:         return strdup(s.toLocal8Bit().data());
Chris@1359:     }
Chris@1359:     
Chris@1359:     QString testName(bool direct, int channels) {
Chris@1359:         return QString("%1 %2 %3")
Chris@1359:             .arg(channels)
Chris@1359:             .arg(channels > 1 ? "channels" : "channel")
Chris@1359:             .arg(direct ? "direct" : "via temporary");
Chris@1359:     }
Chris@1359: 
Chris@1359: private slots:
Chris@1359:     void init()
Chris@1359:     {
Chris@1359:         if (!QDir(outDir).exists() && !QDir().mkpath(outDir)) {
Chris@1428:             SVCERR << "ERROR: Audio out directory \"" << outDir << "\" does not exist and could not be created" << endl;
Chris@1359:             QVERIFY2(QDir(outDir).exists(), "Audio out directory not found and could not be created");
Chris@1359:         }
Chris@1359:     }
Chris@1359: 
Chris@1359:     void write_data()
Chris@1359:     {
Chris@1359:         QTest::addColumn<bool>("direct");
Chris@1359:         QTest::addColumn<int>("channels");
Chris@1359:         for (int direct = 0; direct <= 1; ++direct) {
Chris@1359:             for (int channels = 1; channels < 8; ++channels) {
Chris@1359:                 if (channels == 1 || channels == 2 ||
Chris@1359:                     channels == 5 || channels == 8) {
Chris@1359:                     QString desc = testName(direct, channels);
Chris@1359:                     QTest::newRow(strOf(desc)) << (bool)direct << channels;
Chris@1359:                 }
Chris@1359:             }
Chris@1359:         }
Chris@1359:     }
Chris@1359:     
Chris@1359:     void write()
Chris@1359:     {
Chris@1359:         QFETCH(bool, direct);
Chris@1359:         QFETCH(int, channels);
Chris@1359: 
Chris@1359:         QString outfile = QString("%1/out-%2ch-%3.wav")
Chris@1359:             .arg(outDir).arg(channels).arg(direct ? "direct" : "via-temporary");
Chris@1359:         
Chris@1359:         WavFileWriter writer(outfile,
Chris@1359:                              rate,
Chris@1359:                              channels,
Chris@1359:                              direct ?
Chris@1359:                              WavFileWriter::WriteToTarget :
Chris@1359:                              WavFileWriter::WriteToTemporary);
Chris@1359:         QVERIFY(writer.isOK());
Chris@1359: 
Chris@1359:         AudioTestData data(rate, channels);
Chris@1359:         data.generate();
Chris@1359: 
Chris@1359:         sv_frame_t frameCount = data.getFrameCount();
Chris@1359:         float *interleaved = data.getInterleavedData();
Chris@1359:         float **nonInterleaved = allocate_channels<float>(channels, frameCount);
Chris@1359:         v_deinterleave(nonInterleaved, interleaved, channels, int(frameCount));
Chris@1359:         bool ok = writer.writeSamples(nonInterleaved, frameCount);
Chris@1359:         deallocate_channels(nonInterleaved, channels);
Chris@1359:         QVERIFY(ok);
Chris@1359:         
Chris@1359:         ok = writer.close();
Chris@1359:         QVERIFY(ok);
Chris@1359: 
Chris@1359:         AudioFileReaderFactory::Parameters params;
Chris@1359:         AudioFileReader *rereader =
Chris@1359:             AudioFileReaderFactory::createReader(outfile, params);
Chris@1359:         QVERIFY(rereader != nullptr);
Chris@1359:         
Chris@1359:         floatvec_t readFrames = rereader->getInterleavedFrames(0, frameCount);
Chris@1359:         floatvec_t expected(interleaved, interleaved + frameCount * channels);
Chris@1359:         QCOMPARE(readFrames, expected);
Chris@1359: 
Chris@1359:         delete rereader;
Chris@1359:     }
Chris@1359: };
Chris@1359: 
Chris@1359: #endif