annotate data/fileio/test/EncodingTest.h @ 1365:3382d914e110

Merge from branch 3.0-integration
author Chris Cannam
date Fri, 13 Jan 2017 10:29:44 +0000
parents 8eddb528ef0c
children aadfb395e933
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@1359 110 }
Chris@1359 111
Chris@1359 112 void readMetadata_data() {
Chris@1359 113 addAudioFiles();
Chris@1359 114 }
Chris@1359 115
Chris@1359 116 void readMetadata() {
Chris@1359 117
Chris@1359 118 // All files other than WAVs should have title metadata; check
Chris@1359 119 // that the title matches whatever is in our mapping structure
Chris@1359 120 // defined at the top
Chris@1359 121
Chris@1345 122 QFETCH(QString, audiofile);
Chris@1345 123
Chris@1345 124 AudioFileReaderFactory::Parameters params;
Chris@1346 125 AudioFileReader *reader =
Chris@1346 126 AudioFileReaderFactory::createReader
Chris@1346 127 (encodingDir + "/" + audiofile, params);
Chris@1345 128
Chris@1345 129 QVERIFY(reader != nullptr);
Chris@1345 130
Chris@1345 131 QStringList fileAndExt = audiofile.split(".");
Chris@1345 132 QString file = fileAndExt[0];
Chris@1345 133 QString extension = fileAndExt[1];
Chris@1345 134
Chris@1359 135 if (extension != "wav") {
Chris@1345 136
cannam@1360 137 #if (!defined (HAVE_OGGZ) || !defined(HAVE_FISHSOUND))
cannam@1360 138 if (extension == "ogg") {
cannam@1360 139 QSKIP("Lack native Ogg Vorbis reader, so won't be getting metadata");
cannam@1360 140 }
cannam@1360 141 #endif
cannam@1360 142
Chris@1359 143 auto blah = reader->getInterleavedFrames(0, 10);
Chris@1359 144
Chris@1345 145 QString title = reader->getTitle();
Chris@1345 146 QVERIFY(title != QString());
Chris@1345 147
Chris@1345 148 bool found = false;
Chris@1345 149 for (int m = 0; m < mappingCount; ++m) {
Chris@1345 150 if (file == QString::fromUtf8(mapping[m][0])) {
Chris@1345 151 found = true;
Chris@1346 152 QString expected = QString::fromUtf8(mapping[m][1]);
Chris@1346 153 if (title != expected) {
Chris@1346 154 cerr << "Title does not match expected: codepoints are" << endl;
Chris@1346 155 cerr << "Title (" << title.length() << "ch): ";
Chris@1346 156 for (int i = 0; i < title.length(); ++i) {
Chris@1346 157 cerr << title[i].unicode() << " ";
Chris@1346 158 }
Chris@1346 159 cerr << endl;
Chris@1346 160 cerr << "Expected (" << expected.length() << "ch): ";
Chris@1346 161 for (int i = 0; i < expected.length(); ++i) {
Chris@1346 162 cerr << expected[i].unicode() << " ";
Chris@1346 163 }
Chris@1346 164 cerr << endl;
Chris@1346 165 }
Chris@1346 166 QCOMPARE(title, expected);
Chris@1345 167 break;
Chris@1345 168 }
Chris@1345 169 }
Chris@1345 170
Chris@1345 171 if (!found) {
Chris@1359 172 // Note that this can happen legitimately on Windows,
Chris@1359 173 // where (for annoying VCS-related reasons) the test
Chris@1359 174 // files may have a different filename encoding from
Chris@1359 175 // the expected UTF-16. We check this properly in
Chris@1359 176 // readWriteAudio below, by saving out the file to a
Chris@1359 177 // name matching the metadata
Chris@1346 178 cerr << "Couldn't find filename \""
Chris@1345 179 << file << "\" in title mapping array" << endl;
Chris@1346 180 QSKIP("Couldn't find filename in title mapping array");
Chris@1345 181 }
Chris@1345 182 }
Chris@1345 183 }
Chris@1359 184
Chris@1359 185 void readWriteAudio_data() {
Chris@1359 186 addAudioFiles();
Chris@1359 187 }
Chris@1359 188
Chris@1359 189 void readWriteAudio()
Chris@1359 190 {
Chris@1359 191 // For those files that have title metadata (i.e. all of them
Chris@1359 192 // except the WAVs), read the title metadata and write a wav
Chris@1359 193 // file (of arbitrary content) whose name matches that. Then
Chris@1359 194 // check that we can re-read it. This is intended to exercise
Chris@1359 195 // systems on which the original test filename is miscoded (as
Chris@1359 196 // can happen on Windows).
Chris@1359 197
Chris@1359 198 QFETCH(QString, audiofile);
Chris@1359 199
Chris@1359 200 QStringList fileAndExt = audiofile.split(".");
Chris@1359 201 QString file = fileAndExt[0];
Chris@1359 202 QString extension = fileAndExt[1];
Chris@1359 203
Chris@1359 204 if (extension == "wav") {
Chris@1359 205 return;
Chris@1359 206 }
Chris@1359 207
cannam@1360 208 #if (!defined (HAVE_OGGZ) || !defined(HAVE_FISHSOUND))
cannam@1360 209 if (extension == "ogg") {
cannam@1360 210 QSKIP("Lack native Ogg Vorbis reader, so won't be getting metadata");
cannam@1360 211 }
cannam@1360 212 #endif
cannam@1360 213
Chris@1359 214 AudioFileReaderFactory::Parameters params;
Chris@1359 215 AudioFileReader *reader =
Chris@1359 216 AudioFileReaderFactory::createReader
Chris@1359 217 (encodingDir + "/" + audiofile, params);
Chris@1359 218 QVERIFY(reader != nullptr);
Chris@1359 219
Chris@1359 220 QString title = reader->getTitle();
Chris@1359 221 QVERIFY(title != QString());
Chris@1359 222
Chris@1359 223 for (int useTemporary = 0; useTemporary <= 1; ++useTemporary) {
Chris@1359 224
Chris@1359 225 QString outfile = outDir + "/" + file + ".wav";
Chris@1359 226 WavFileWriter writer(outfile,
Chris@1359 227 reader->getSampleRate(),
Chris@1359 228 1,
Chris@1359 229 useTemporary ?
Chris@1359 230 WavFileWriter::WriteToTemporary :
Chris@1359 231 WavFileWriter::WriteToTarget);
Chris@1359 232
Chris@1359 233 QVERIFY(writer.isOK());
Chris@1359 234
Chris@1359 235 floatvec_t data { 0.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0, -1.0 };
Chris@1359 236 const float *samples = data.data();
Chris@1359 237 bool ok = writer.writeSamples(&samples, 8);
Chris@1359 238 QVERIFY(ok);
Chris@1359 239
Chris@1359 240 ok = writer.close();
Chris@1359 241 QVERIFY(ok);
Chris@1359 242
Chris@1359 243 AudioFileReader *rereader =
Chris@1359 244 AudioFileReaderFactory::createReader(outfile, params);
Chris@1359 245 QVERIFY(rereader != nullptr);
Chris@1359 246
Chris@1359 247 floatvec_t readFrames = rereader->getInterleavedFrames(0, 8);
Chris@1359 248 QCOMPARE(readFrames, data);
Chris@1359 249
Chris@1359 250 delete rereader;
Chris@1359 251 }
Chris@1359 252
Chris@1359 253 delete reader;
Chris@1359 254 }
Chris@1345 255 };
Chris@1345 256
Chris@1345 257 #endif