comparison data/fileio/test/EncodingTest.h @ 1527:710e6250a401 zoom

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