annotate data/fileio/test/EncodingTest.h @ 1593:d3f068153546 bqaudiostream

QDir::entryList on Mac ignores all of our files with non-ASCII filenames, I think because of variant normalisations (https://bugreports.qt.io/browse/QTBUG-70732). Hard code the file list instead.
author Chris Cannam
date Mon, 21 Jan 2019 15:49:04 +0000
parents f8e3dcbafb4d
children afa75922fe0f
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@1593 49 static const char *testFiles[][2] = {
Chris@1593 50 { "id3v2-iso-8859-1", "mp3" },
Chris@1593 51 { "id3v2-ucs-2", "mp3" },
Chris@1593 52 { utf8_name_tsprk, "flac" },
Chris@1593 53 { utf8_name_tsprk, "m4a" },
Chris@1593 54 { utf8_name_tsprk, "mp3" },
Chris@1593 55 { utf8_name_tsprk, "ogg" },
Chris@1593 56 { utf8_name_sprkt, "mp3" },
Chris@1593 57 { utf8_name_sprkt, "ogg" },
Chris@1593 58 };
Chris@1593 59 static const int testFileCount = 8;
Chris@1593 60
Chris@1345 61 class EncodingTest : public QObject
Chris@1345 62 {
Chris@1345 63 Q_OBJECT
Chris@1345 64
Chris@1346 65 private:
Chris@1346 66 QString testDirBase;
Chris@1346 67 QString encodingDir;
Chris@1359 68 QString outDir;
Chris@1346 69
Chris@1346 70 public:
Chris@1346 71 EncodingTest(QString base) {
Chris@1346 72 if (base == "") {
Chris@1346 73 base = "svcore/data/fileio/test";
Chris@1346 74 }
Chris@1346 75 testDirBase = base;
Chris@1346 76 encodingDir = base + "/encodings";
Chris@1359 77 outDir = base + "/outfiles";
Chris@1346 78 }
Chris@1346 79
Chris@1346 80 private:
Chris@1359 81 void addAudioFiles() {
Chris@1359 82 QTest::addColumn<QString>("audiofile");
Chris@1593 83 for (int i = 0; i < testFileCount; ++i) {
Chris@1593 84 std::string s = testFiles[i][0];
Chris@1593 85 s += ".";
Chris@1593 86 s += testFiles[i][1];
Chris@1593 87 QTest::newRow(strdup(s.c_str())) << QString::fromStdString(s);
Chris@1359 88 }
Chris@1359 89 }
Chris@1359 90
Chris@1345 91 private slots:
Chris@1345 92 void init()
Chris@1345 93 {
Chris@1345 94 if (!QDir(encodingDir).exists()) {
Chris@1428 95 SVCERR << "ERROR: Audio encoding file directory \"" << encodingDir << "\" does not exist" << endl;
Chris@1345 96 QVERIFY2(QDir(encodingDir).exists(), "Audio encoding file directory not found");
Chris@1593 97 }
Chris@1359 98 if (!QDir(outDir).exists() && !QDir().mkpath(outDir)) {
Chris@1428 99 SVCERR << "ERROR: Audio out directory \"" << outDir << "\" does not exist and could not be created" << endl;
Chris@1359 100 QVERIFY2(QDir(outDir).exists(), "Audio out directory not found and could not be created");
Chris@1345 101 }
Chris@1345 102 }
Chris@1345 103
Chris@1359 104 void readAudio_data() {
Chris@1359 105 addAudioFiles();
Chris@1359 106 }
Chris@1359 107
Chris@1359 108 void readAudio() {
Chris@1359 109
Chris@1359 110 // Ensure that we can open all the files
Chris@1359 111
Chris@1359 112 QFETCH(QString, audiofile);
Chris@1359 113
Chris@1592 114 if (!AudioFileReaderFactory::isSupported(encodingDir + "/" +
Chris@1592 115 audiofile)) {
Chris@1592 116 #if ( QT_VERSION >= 0x050000 )
Chris@1592 117 QSKIP("Known unsupported file, skipping");
Chris@1592 118 #else
Chris@1592 119 QSKIP("Known unsupported file, skipping", SkipSingle);
Chris@1592 120 #endif
Chris@1592 121 }
Chris@1592 122
Chris@1359 123 AudioFileReaderFactory::Parameters params;
Chris@1359 124 AudioFileReader *reader =
Chris@1359 125 AudioFileReaderFactory::createReader
Chris@1359 126 (encodingDir + "/" + audiofile, params);
Chris@1359 127
Chris@1359 128 QVERIFY(reader != nullptr);
Chris@1402 129
Chris@1402 130 delete reader;
Chris@1359 131 }
Chris@1359 132
Chris@1359 133 void readMetadata_data() {
Chris@1359 134 addAudioFiles();
Chris@1359 135 }
Chris@1359 136
Chris@1359 137 void readMetadata() {
Chris@1359 138
Chris@1359 139 // All files other than WAVs should have title metadata; check
Chris@1359 140 // that the title matches whatever is in our mapping structure
Chris@1359 141 // defined at the top
Chris@1359 142
Chris@1345 143 QFETCH(QString, audiofile);
Chris@1345 144
Chris@1345 145 AudioFileReaderFactory::Parameters params;
Chris@1346 146 AudioFileReader *reader =
Chris@1346 147 AudioFileReaderFactory::createReader
Chris@1346 148 (encodingDir + "/" + audiofile, params);
Chris@1345 149
Chris@1592 150 if (!reader) {
Chris@1592 151 #if ( QT_VERSION >= 0x050000 )
Chris@1592 152 QSKIP("Unsupported file, skipping");
Chris@1592 153 #else
Chris@1592 154 QSKIP("Unsupported file, skipping", SkipSingle);
Chris@1592 155 #endif
Chris@1592 156 }
Chris@1345 157
Chris@1345 158 QStringList fileAndExt = audiofile.split(".");
Chris@1345 159 QString file = fileAndExt[0];
Chris@1345 160 QString extension = fileAndExt[1];
Chris@1345 161
Chris@1402 162 if (extension == "wav") {
Chris@1402 163
Chris@1402 164 // Nothing
Chris@1402 165
Chris@1402 166 delete reader;
Chris@1402 167
Chris@1402 168 } else {
Chris@1345 169
Chris@1588 170 //#if (!defined (HAVE_OGGZ) || !defined(HAVE_FISHSOUND))
Chris@1588 171 // if (extension == "ogg") {
Chris@1588 172 // QSKIP("Lack native Ogg Vorbis reader, so won't be getting metadata");
Chris@1588 173 // }
Chris@1588 174 //#endif
cannam@1360 175
Chris@1359 176 auto blah = reader->getInterleavedFrames(0, 10);
Chris@1359 177
Chris@1345 178 QString title = reader->getTitle();
Chris@1345 179 QVERIFY(title != QString());
Chris@1345 180
Chris@1402 181 delete reader;
Chris@1402 182
Chris@1345 183 bool found = false;
Chris@1345 184 for (int m = 0; m < mappingCount; ++m) {
Chris@1345 185 if (file == QString::fromUtf8(mapping[m][0])) {
Chris@1345 186 found = true;
Chris@1346 187 QString expected = QString::fromUtf8(mapping[m][1]);
Chris@1346 188 if (title != expected) {
Chris@1428 189 SVCERR << "Title does not match expected: codepoints are" << endl;
Chris@1428 190 SVCERR << "Title (" << title.length() << "ch): ";
Chris@1346 191 for (int i = 0; i < title.length(); ++i) {
Chris@1428 192 SVCERR << title[i].unicode() << " ";
Chris@1346 193 }
Chris@1428 194 SVCERR << endl;
Chris@1428 195 SVCERR << "Expected (" << expected.length() << "ch): ";
Chris@1346 196 for (int i = 0; i < expected.length(); ++i) {
Chris@1428 197 SVCERR << expected[i].unicode() << " ";
Chris@1346 198 }
Chris@1428 199 SVCERR << endl;
Chris@1346 200 }
Chris@1346 201 QCOMPARE(title, expected);
Chris@1345 202 break;
Chris@1345 203 }
Chris@1345 204 }
Chris@1345 205
Chris@1345 206 if (!found) {
Chris@1359 207 // Note that this can happen legitimately on Windows,
Chris@1359 208 // where (for annoying VCS-related reasons) the test
Chris@1359 209 // files may have a different filename encoding from
Chris@1359 210 // the expected UTF-16. We check this properly in
Chris@1359 211 // readWriteAudio below, by saving out the file to a
Chris@1359 212 // name matching the metadata
Chris@1428 213 SVCERR << "Couldn't find filename \""
Chris@1345 214 << file << "\" in title mapping array" << endl;
Chris@1346 215 QSKIP("Couldn't find filename in title mapping array");
Chris@1345 216 }
Chris@1345 217 }
Chris@1345 218 }
Chris@1359 219
Chris@1359 220 void readWriteAudio_data() {
Chris@1359 221 addAudioFiles();
Chris@1359 222 }
Chris@1359 223
Chris@1359 224 void readWriteAudio()
Chris@1359 225 {
Chris@1359 226 // For those files that have title metadata (i.e. all of them
Chris@1359 227 // except the WAVs), read the title metadata and write a wav
Chris@1359 228 // file (of arbitrary content) whose name matches that. Then
Chris@1359 229 // check that we can re-read it. This is intended to exercise
Chris@1359 230 // systems on which the original test filename is miscoded (as
Chris@1359 231 // can happen on Windows).
Chris@1359 232
Chris@1359 233 QFETCH(QString, audiofile);
Chris@1359 234
Chris@1359 235 QStringList fileAndExt = audiofile.split(".");
Chris@1359 236 QString file = fileAndExt[0];
Chris@1359 237 QString extension = fileAndExt[1];
Chris@1359 238
Chris@1359 239 if (extension == "wav") {
Chris@1359 240 return;
Chris@1359 241 }
Chris@1359 242
Chris@1588 243 //#if (!defined (HAVE_OGGZ) || !defined(HAVE_FISHSOUND))
Chris@1588 244 // if (extension == "ogg") {
Chris@1588 245 // QSKIP("Lack native Ogg Vorbis reader, so won't be getting metadata");
Chris@1588 246 // }
Chris@1588 247 //#endif
cannam@1360 248
Chris@1359 249 AudioFileReaderFactory::Parameters params;
Chris@1359 250 AudioFileReader *reader =
Chris@1359 251 AudioFileReaderFactory::createReader
Chris@1359 252 (encodingDir + "/" + audiofile, params);
Chris@1592 253
Chris@1592 254 if (!reader) {
Chris@1592 255 #if ( QT_VERSION >= 0x050000 )
Chris@1592 256 QSKIP("Unsupported file, skipping");
Chris@1592 257 #else
Chris@1592 258 QSKIP("Unsupported file, skipping", SkipSingle);
Chris@1592 259 #endif
Chris@1592 260 }
Chris@1359 261
Chris@1359 262 QString title = reader->getTitle();
Chris@1359 263 QVERIFY(title != QString());
Chris@1359 264
Chris@1359 265 for (int useTemporary = 0; useTemporary <= 1; ++useTemporary) {
Chris@1359 266
Chris@1359 267 QString outfile = outDir + "/" + file + ".wav";
Chris@1359 268 WavFileWriter writer(outfile,
Chris@1359 269 reader->getSampleRate(),
Chris@1359 270 1,
Chris@1359 271 useTemporary ?
Chris@1359 272 WavFileWriter::WriteToTemporary :
Chris@1359 273 WavFileWriter::WriteToTarget);
Chris@1359 274
Chris@1359 275 QVERIFY(writer.isOK());
Chris@1359 276
Chris@1359 277 floatvec_t data { 0.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0, -1.0 };
Chris@1359 278 const float *samples = data.data();
Chris@1359 279 bool ok = writer.writeSamples(&samples, 8);
Chris@1359 280 QVERIFY(ok);
Chris@1359 281
Chris@1359 282 ok = writer.close();
Chris@1359 283 QVERIFY(ok);
Chris@1359 284
Chris@1359 285 AudioFileReader *rereader =
Chris@1359 286 AudioFileReaderFactory::createReader(outfile, params);
Chris@1359 287 QVERIFY(rereader != nullptr);
Chris@1359 288
Chris@1359 289 floatvec_t readFrames = rereader->getInterleavedFrames(0, 8);
Chris@1359 290 QCOMPARE(readFrames, data);
Chris@1359 291
Chris@1359 292 delete rereader;
Chris@1359 293 }
Chris@1359 294
Chris@1359 295 delete reader;
Chris@1359 296 }
Chris@1345 297 };
Chris@1345 298
Chris@1345 299 #endif