annotate data/fileio/test/EncodingTest.h @ 1394:9ef1cc26024c

Add Range01 normalisation method to ColumnOp. This is the normalisation that is actually used in the Colour 3D Plot layer historically when column normalisation is enabled (not Max1 after all).
author Chris Cannam
date Tue, 28 Feb 2017 14:04:16 +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