annotate data/fileio/test/EncodingTest.h @ 1412:b7a9edee85e0 scale-ticks

Change loop to something that feels more correct, though it makes no difference to the tests here. More tests, one failing.
author Chris Cannam
date Thu, 04 May 2017 08:32:41 +0100
parents aadfb395e933
children 87ae75da6527
rev   line source
Chris@1345 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1345 2
Chris@1345 3 /*
Chris@1345 4 Sonic Visualiser
Chris@1345 5 An audio file viewer and annotation editor.
Chris@1345 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1345 7
Chris@1345 8 This program is free software; you can redistribute it and/or
Chris@1345 9 modify it under the terms of the GNU General Public License as
Chris@1345 10 published by the Free Software Foundation; either version 2 of the
Chris@1345 11 License, or (at your option) any later version. See the file
Chris@1345 12 COPYING included with this distribution for more information.
Chris@1345 13 */
Chris@1345 14
Chris@1345 15 #ifndef TEST_AUDIO_ENCODINGS_H
Chris@1345 16 #define TEST_AUDIO_ENCODINGS_H
Chris@1345 17
Chris@1345 18 // Quick tests for filename encodings and encoding of ID3 data. Not a
Chris@1345 19 // test of audio codecs.
Chris@1345 20
Chris@1345 21 #include "../AudioFileReaderFactory.h"
Chris@1345 22 #include "../AudioFileReader.h"
Chris@1359 23 #include "../WavFileWriter.h"
Chris@1345 24
Chris@1345 25 #include <cmath>
Chris@1345 26
Chris@1345 27 #include <QObject>
Chris@1345 28 #include <QtTest>
Chris@1345 29 #include <QDir>
Chris@1345 30
Chris@1345 31 #include <iostream>
Chris@1345 32
Chris@1345 33 using namespace std;
Chris@1345 34
Chris@1346 35 const char utf8_name_cdp_1[] = "Caf\303\251 de Paris";
Chris@1346 36 const char utf8_name_cdp_2[] = "Caf\303\251 de \351\207\215\345\272\206";
Chris@1347 37 const char utf8_name_tsprk[] = "T\303\253mple of Sp\303\266rks";
Chris@1346 38 const char utf8_name_sprkt[] = "\343\202\271\343\203\235\343\203\274\343\202\257\343\201\256\345\257\272\351\231\242";
Chris@1345 39
Chris@1359 40 // Mapping between filename and expected title metadata field
Chris@1345 41 static const char *mapping[][2] = {
Chris@1346 42 { "id3v2-iso-8859-1", utf8_name_cdp_1 },
Chris@1346 43 { "id3v2-ucs-2", utf8_name_cdp_2 },
Chris@1346 44 { utf8_name_tsprk, utf8_name_tsprk },
Chris@1346 45 { utf8_name_sprkt, utf8_name_sprkt },
Chris@1345 46 };
Chris@1345 47 static const int mappingCount = 4;
Chris@1345 48
Chris@1345 49 class EncodingTest : public QObject
Chris@1345 50 {
Chris@1345 51 Q_OBJECT
Chris@1345 52
Chris@1346 53 private:
Chris@1346 54 QString testDirBase;
Chris@1346 55 QString encodingDir;
Chris@1359 56 QString outDir;
Chris@1346 57
Chris@1346 58 public:
Chris@1346 59 EncodingTest(QString base) {
Chris@1346 60 if (base == "") {
Chris@1346 61 base = "svcore/data/fileio/test";
Chris@1346 62 }
Chris@1346 63 testDirBase = base;
Chris@1346 64 encodingDir = base + "/encodings";
Chris@1359 65 outDir = base + "/outfiles";
Chris@1346 66 }
Chris@1346 67
Chris@1346 68 private:
Chris@1345 69 const char *strOf(QString s) {
Chris@1345 70 return strdup(s.toLocal8Bit().data());
Chris@1345 71 }
Chris@1345 72
Chris@1359 73 void addAudioFiles() {
Chris@1359 74 QTest::addColumn<QString>("audiofile");
Chris@1359 75 QStringList files = QDir(encodingDir).entryList(QDir::Files);
Chris@1359 76 foreach (QString filename, files) {
Chris@1359 77 QTest::newRow(strOf(filename)) << filename;
Chris@1359 78 }
Chris@1359 79 }
Chris@1359 80
Chris@1345 81 private slots:
Chris@1345 82 void init()
Chris@1345 83 {
Chris@1345 84 if (!QDir(encodingDir).exists()) {
Chris@1345 85 cerr << "ERROR: Audio encoding file directory \"" << encodingDir << "\" does not exist" << endl;
Chris@1345 86 QVERIFY2(QDir(encodingDir).exists(), "Audio encoding file directory not found");
Chris@1345 87 }
Chris@1359 88 if (!QDir(outDir).exists() && !QDir().mkpath(outDir)) {
Chris@1359 89 cerr << "ERROR: Audio out directory \"" << outDir << "\" does not exist and could not be created" << endl;
Chris@1359 90 QVERIFY2(QDir(outDir).exists(), "Audio out directory not found and could not be created");
Chris@1345 91 }
Chris@1345 92 }
Chris@1345 93
Chris@1359 94 void readAudio_data() {
Chris@1359 95 addAudioFiles();
Chris@1359 96 }
Chris@1359 97
Chris@1359 98 void readAudio() {
Chris@1359 99
Chris@1359 100 // Ensure that we can open all the files
Chris@1359 101
Chris@1359 102 QFETCH(QString, audiofile);
Chris@1359 103
Chris@1359 104 AudioFileReaderFactory::Parameters params;
Chris@1359 105 AudioFileReader *reader =
Chris@1359 106 AudioFileReaderFactory::createReader
Chris@1359 107 (encodingDir + "/" + audiofile, params);
Chris@1359 108
Chris@1359 109 QVERIFY(reader != nullptr);
Chris@1402 110
Chris@1402 111 delete reader;
Chris@1359 112 }
Chris@1359 113
Chris@1359 114 void readMetadata_data() {
Chris@1359 115 addAudioFiles();
Chris@1359 116 }
Chris@1359 117
Chris@1359 118 void readMetadata() {
Chris@1359 119
Chris@1359 120 // All files other than WAVs should have title metadata; check
Chris@1359 121 // that the title matches whatever is in our mapping structure
Chris@1359 122 // defined at the top
Chris@1359 123
Chris@1345 124 QFETCH(QString, audiofile);
Chris@1345 125
Chris@1345 126 AudioFileReaderFactory::Parameters params;
Chris@1346 127 AudioFileReader *reader =
Chris@1346 128 AudioFileReaderFactory::createReader
Chris@1346 129 (encodingDir + "/" + audiofile, params);
Chris@1345 130
Chris@1345 131 QVERIFY(reader != nullptr);
Chris@1345 132
Chris@1345 133 QStringList fileAndExt = audiofile.split(".");
Chris@1345 134 QString file = fileAndExt[0];
Chris@1345 135 QString extension = fileAndExt[1];
Chris@1345 136
Chris@1402 137 if (extension == "wav") {
Chris@1402 138
Chris@1402 139 // Nothing
Chris@1402 140
Chris@1402 141 delete reader;
Chris@1402 142
Chris@1402 143 } else {
Chris@1345 144
cannam@1360 145 #if (!defined (HAVE_OGGZ) || !defined(HAVE_FISHSOUND))
cannam@1360 146 if (extension == "ogg") {
cannam@1360 147 QSKIP("Lack native Ogg Vorbis reader, so won't be getting metadata");
cannam@1360 148 }
cannam@1360 149 #endif
cannam@1360 150
Chris@1359 151 auto blah = reader->getInterleavedFrames(0, 10);
Chris@1359 152
Chris@1345 153 QString title = reader->getTitle();
Chris@1345 154 QVERIFY(title != QString());
Chris@1345 155
Chris@1402 156 delete reader;
Chris@1402 157
Chris@1345 158 bool found = false;
Chris@1345 159 for (int m = 0; m < mappingCount; ++m) {
Chris@1345 160 if (file == QString::fromUtf8(mapping[m][0])) {
Chris@1345 161 found = true;
Chris@1346 162 QString expected = QString::fromUtf8(mapping[m][1]);
Chris@1346 163 if (title != expected) {
Chris@1346 164 cerr << "Title does not match expected: codepoints are" << endl;
Chris@1346 165 cerr << "Title (" << title.length() << "ch): ";
Chris@1346 166 for (int i = 0; i < title.length(); ++i) {
Chris@1346 167 cerr << title[i].unicode() << " ";
Chris@1346 168 }
Chris@1346 169 cerr << endl;
Chris@1346 170 cerr << "Expected (" << expected.length() << "ch): ";
Chris@1346 171 for (int i = 0; i < expected.length(); ++i) {
Chris@1346 172 cerr << expected[i].unicode() << " ";
Chris@1346 173 }
Chris@1346 174 cerr << endl;
Chris@1346 175 }
Chris@1346 176 QCOMPARE(title, expected);
Chris@1345 177 break;
Chris@1345 178 }
Chris@1345 179 }
Chris@1345 180
Chris@1345 181 if (!found) {
Chris@1359 182 // Note that this can happen legitimately on Windows,
Chris@1359 183 // where (for annoying VCS-related reasons) the test
Chris@1359 184 // files may have a different filename encoding from
Chris@1359 185 // the expected UTF-16. We check this properly in
Chris@1359 186 // readWriteAudio below, by saving out the file to a
Chris@1359 187 // name matching the metadata
Chris@1346 188 cerr << "Couldn't find filename \""
Chris@1345 189 << file << "\" in title mapping array" << endl;
Chris@1346 190 QSKIP("Couldn't find filename in title mapping array");
Chris@1345 191 }
Chris@1345 192 }
Chris@1345 193 }
Chris@1359 194
Chris@1359 195 void readWriteAudio_data() {
Chris@1359 196 addAudioFiles();
Chris@1359 197 }
Chris@1359 198
Chris@1359 199 void readWriteAudio()
Chris@1359 200 {
Chris@1359 201 // For those files that have title metadata (i.e. all of them
Chris@1359 202 // except the WAVs), read the title metadata and write a wav
Chris@1359 203 // file (of arbitrary content) whose name matches that. Then
Chris@1359 204 // check that we can re-read it. This is intended to exercise
Chris@1359 205 // systems on which the original test filename is miscoded (as
Chris@1359 206 // can happen on Windows).
Chris@1359 207
Chris@1359 208 QFETCH(QString, audiofile);
Chris@1359 209
Chris@1359 210 QStringList fileAndExt = audiofile.split(".");
Chris@1359 211 QString file = fileAndExt[0];
Chris@1359 212 QString extension = fileAndExt[1];
Chris@1359 213
Chris@1359 214 if (extension == "wav") {
Chris@1359 215 return;
Chris@1359 216 }
Chris@1359 217
cannam@1360 218 #if (!defined (HAVE_OGGZ) || !defined(HAVE_FISHSOUND))
cannam@1360 219 if (extension == "ogg") {
cannam@1360 220 QSKIP("Lack native Ogg Vorbis reader, so won't be getting metadata");
cannam@1360 221 }
cannam@1360 222 #endif
cannam@1360 223
Chris@1359 224 AudioFileReaderFactory::Parameters params;
Chris@1359 225 AudioFileReader *reader =
Chris@1359 226 AudioFileReaderFactory::createReader
Chris@1359 227 (encodingDir + "/" + audiofile, params);
Chris@1359 228 QVERIFY(reader != nullptr);
Chris@1359 229
Chris@1359 230 QString title = reader->getTitle();
Chris@1359 231 QVERIFY(title != QString());
Chris@1359 232
Chris@1359 233 for (int useTemporary = 0; useTemporary <= 1; ++useTemporary) {
Chris@1359 234
Chris@1359 235 QString outfile = outDir + "/" + file + ".wav";
Chris@1359 236 WavFileWriter writer(outfile,
Chris@1359 237 reader->getSampleRate(),
Chris@1359 238 1,
Chris@1359 239 useTemporary ?
Chris@1359 240 WavFileWriter::WriteToTemporary :
Chris@1359 241 WavFileWriter::WriteToTarget);
Chris@1359 242
Chris@1359 243 QVERIFY(writer.isOK());
Chris@1359 244
Chris@1359 245 floatvec_t data { 0.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0, -1.0 };
Chris@1359 246 const float *samples = data.data();
Chris@1359 247 bool ok = writer.writeSamples(&samples, 8);
Chris@1359 248 QVERIFY(ok);
Chris@1359 249
Chris@1359 250 ok = writer.close();
Chris@1359 251 QVERIFY(ok);
Chris@1359 252
Chris@1359 253 AudioFileReader *rereader =
Chris@1359 254 AudioFileReaderFactory::createReader(outfile, params);
Chris@1359 255 QVERIFY(rereader != nullptr);
Chris@1359 256
Chris@1359 257 floatvec_t readFrames = rereader->getInterleavedFrames(0, 8);
Chris@1359 258 QCOMPARE(readFrames, data);
Chris@1359 259
Chris@1359 260 delete rereader;
Chris@1359 261 }
Chris@1359 262
Chris@1359 263 delete reader;
Chris@1359 264 }
Chris@1345 265 };
Chris@1345 266
Chris@1345 267 #endif