1 /* -*- Mode: c++ -*- */ 2 /*************************************************************************** 3 * domloadertest.cc 4 * 5 * Sun Jun 10 17:48:04 CEST 2018 6 * Copyright 2018 Bent Bisballe Nyeng 7 * deva@aasimon.org 8 ****************************************************************************/ 9 10 /* 11 * This file is part of DrumGizmo. 12 * 13 * DrumGizmo is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU Lesser General Public License as published by 15 * the Free Software Foundation; either version 3 of the License, or 16 * (at your option) any later version. 17 * 18 * DrumGizmo is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU Lesser General Public License for more details. 22 * 23 * You should have received a copy of the GNU Lesser General Public License 24 * along with DrumGizmo; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 26 */ 27 #include <uunit.h> 28 29 #include <DGDOM.h> 30 #include <domloader.h> 31 #include <dgxmlparser.h> 32 #include <drumkit.h> 33 #include <settings.h> 34 #include <random.h> 35 36 #include "scopedfile.h" 37 #include "path.h" 38 39 class DOMLoaderTest 40 : public uUnit 41 { 42 public: DOMLoaderTest()43 DOMLoaderTest() 44 { 45 uUNIT_TEST(DOMLoaderTest::testTest); 46 } 47 48 Settings settings; 49 Random random; 50 51 //! This just creates some drumkit. testTest()52 void testTest() 53 { 54 ScopedFile scoped_instrument_file1( 55 "<?xml version='1.0' encoding='UTF-8'?>\n" \ 56 "<instrument version=\"2.0\" name=\"Snare1\">\n" \ 57 " <samples>\n" \ 58 " <sample name=\"Snare-1\" power=\"0.00985718\">\n" \ 59 " <audiofile channel=\"AmbLeft\" file=\"1-Snare.wav\" filechannel=\"1\"/>\n" \ 60 " <audiofile channel=\"AmbRight\" file=\"1-Snare.wav\" filechannel=\"2\"/>\n" \ 61 " <audiofile channel=\"SnareBottom\" file=\"1-Snare.wav\" filechannel=\"12\"/>\n" \ 62 " <audiofile channel=\"SnareTop\" file=\"1-Snare.wav\" filechannel=\"13\"/>\n" \ 63 " </sample>\n" \ 64 " <sample name=\"Snare-2\" power=\"0.0124808\">\n" \ 65 " <audiofile channel=\"AmbLeft\" file=\"2-Snare.wav\" filechannel=\"1\"/>\n" \ 66 " <audiofile channel=\"AmbRight\" file=\"2-Snare.wav\" filechannel=\"2\"/>\n" \ 67 " <audiofile channel=\"SnareBottom\" file=\"2-Snare.wav\" filechannel=\"12\"/>\n" \ 68 " <audiofile channel=\"SnareTop\" file=\"2-Snare.wav\" filechannel=\"13\"/>\n" \ 69 " </sample>\n" \ 70 " </samples>\n" \ 71 "</instrument>"); 72 73 // Version 1.0 format 74 ScopedFile scoped_instrument_file2( 75 "<?xml version='1.0' encoding='UTF-8'?>\n" \ 76 "<instrument name=\"Snare2\">\n" \ 77 " <samples>\n" \ 78 " <sample name=\"Snare-1\">\n" \ 79 " <audiofile channel=\"AmbLeft2\" file=\"1-Snare-1.wav\"/>\n" \ 80 " <audiofile channel=\"AmbRight2\" file=\"1-Snare-2.wav\"/>\n" \ 81 " <audiofile channel=\"SnareBottom2\" file=\"1-Snare-3.wav\"/>\n" \ 82 " <audiofile channel=\"SnareTop2\" file=\"1-Snare-4.wav\"/>\n" \ 83 " </sample>\n" \ 84 " <sample name=\"Snare-2\">\n" \ 85 " <audiofile channel=\"AmbLeft2\" file=\"2-Snare-1.wav\"/>\n" \ 86 " <audiofile channel=\"AmbRight2\" file=\"2-Snare-2.wav\"/>\n" \ 87 " <audiofile channel=\"SnareBottom2\" file=\"2-Snare-3.wav\"/>\n" \ 88 " <audiofile channel=\"SnareTop2\" file=\"2-Snare-4.wav\"/>\n" \ 89 " </sample>\n" \ 90 " </samples>\n" \ 91 " <velocities>\n" \ 92 " <velocity lower=\"0\" upper=\"0.6\">\n" \ 93 " <sampleref probability=\"0.6\" name=\"Snare-1\"/>\n" \ 94 " <sampleref probability=\"0.4\" name=\"Snare-2\"/>\n" \ 95 " </velocity>" \ 96 " <velocity lower=\"0.6\" upper=\"1.0\">" \ 97 " <sampleref probability=\"0.4\" name=\"Snare-2\"/>" \ 98 " <sampleref probability=\"0.6\" name=\"Snare-1\"/>" \ 99 " </velocity>" \ 100 " </velocities>" \ 101 "</instrument>"); 102 103 ScopedFile scoped_file( 104 std::string( 105 "<?xml version='1.0' encoding='UTF-8'?>\n" \ 106 "<drumkit samplerate=\"48000\" version=\"2.0.0\">\n" \ 107 " <channels>\n" \ 108 " <channel name=\"AmbLeft\"/>\n" \ 109 " <channel name=\"AmbRight\"/>\n" \ 110 " <channel name=\"SnareTop\"/>\n" \ 111 " <channel name=\"SnareBottom\"/>\n" \ 112 " </channels>\n" \ 113 " <instruments>\n" \ 114 " <instrument name=\"Snare1\" file=\"") + getFile(scoped_instrument_file1.filename()) + std::string("\">\n" \ 115 " <channelmap in=\"AmbLeft\" out=\"AmbLeft\" main=\"true\"/>\n" \ 116 " <channelmap in=\"AmbRight\" out=\"AmbRight\" main=\"true\"/>\n" \ 117 " <channelmap in=\"SnareTop\" out=\"SnareTop\"/>\n" \ 118 " <channelmap in=\"SnareBottom\" out=\"SnareBottom\"/>\n" \ 119 " </instrument>\n" \ 120 " <instrument name=\"Snare2\" file=\"") + getFile(scoped_instrument_file2.filename()) + std::string("\">\n" \ 121 " <channelmap in=\"AmbLeft2\" out=\"AmbLeft\" main=\"true\"/>\n" \ 122 " <channelmap in=\"AmbRight2\" out=\"AmbRight\" main=\"true\"/>\n" \ 123 " <channelmap in=\"SnareTop2\" out=\"SnareTop\"/>\n" \ 124 " <channelmap in=\"SnareBottom2\" out=\"SnareBottom\"/>\n" \ 125 " </instrument>\n" \ 126 " </instruments>\n" \ 127 "</drumkit>")); 128 129 DrumKit drumkit; 130 131 DrumkitDOM drumkitdom; 132 std::vector<InstrumentDOM> instrumentdoms; 133 uUNIT_ASSERT(parseDrumkitFile(scoped_file.filename(), drumkitdom)); 134 auto basepath = getPath(scoped_file.filename()); 135 for(const auto& ref: drumkitdom.instruments) 136 { 137 instrumentdoms.emplace_back(); 138 uUNIT_ASSERT(parseInstrumentFile(basepath + "/" + ref.file, instrumentdoms.back())); 139 } 140 141 DOMLoader domloader(settings, random); 142 uUNIT_ASSERT(domloader.loadDom(basepath, drumkitdom, instrumentdoms, drumkit)); 143 144 // 145 // Drumkit: 146 // 147 148 uUNIT_ASSERT_EQUAL(std::size_t(2), drumkit.instruments.size()); 149 uUNIT_ASSERT_EQUAL(std::size_t(4), drumkit.channels.size()); 150 151 uUNIT_ASSERT_EQUAL(std::string("AmbLeft"), drumkit.channels[0].name); 152 uUNIT_ASSERT_EQUAL(std::string("AmbRight"), drumkit.channels[1].name); 153 uUNIT_ASSERT_EQUAL(std::string("SnareTop"), drumkit.channels[2].name); 154 uUNIT_ASSERT_EQUAL(std::string("SnareBottom"), drumkit.channels[3].name); 155 156 uUNIT_ASSERT_EQUAL(48000.0f, drumkit.metadata._samplerate); 157 158 uUNIT_ASSERT(VersionStr("2.0.0") == drumkit.metadata._version); 159 160 // 161 // Instrument1 'Snare1': 162 // 163 { 164 auto& instrument = *drumkit.instruments[0]; 165 uUNIT_ASSERT_EQUAL(std::string(""), instrument._group); 166 uUNIT_ASSERT_EQUAL(std::string("Snare1"), instrument._name); 167 uUNIT_ASSERT_EQUAL(std::string(""), instrument._description); 168 169 uUNIT_ASSERT(VersionStr("2.0.0") == instrument.version); 170 171 // NOTE: instrument.samples are the sample map belonging to version 1.0 172 uUNIT_ASSERT_EQUAL(std::size_t(2), instrument.samplelist.size()); 173 { 174 const auto& sample = *instrument.samplelist[0]; 175 uUNIT_ASSERT_EQUAL(std::string("Snare-1"), sample.name); 176 uUNIT_ASSERT_EQUAL(0.00985718f, sample.power); 177 uUNIT_ASSERT_EQUAL(std::size_t(4), sample.audiofiles.size()); 178 for(const auto& audiofile : sample.audiofiles) 179 { 180 uUNIT_ASSERT_EQUAL(std::string("/tmp/1-Snare.wav"), audiofile.second->filename); 181 switch(audiofile.second->filechannel) 182 { 183 // NOTE: Channel numbers are zero based - they are 1 based in the xml 184 case 0: 185 uUNIT_ASSERT_EQUAL(std::string("AmbLeft"), 186 audiofile.second->instrument_channel->name); 187 break; 188 case 1: 189 uUNIT_ASSERT_EQUAL(std::string("AmbRight"), 190 audiofile.second->instrument_channel->name); 191 break; 192 case 11: 193 uUNIT_ASSERT_EQUAL(std::string("SnareBottom"), 194 audiofile.second->instrument_channel->name); 195 break; 196 case 12: 197 uUNIT_ASSERT_EQUAL(std::string("SnareTop"), 198 audiofile.second->instrument_channel->name); 199 break; 200 default: 201 uUNIT_ASSERT(false); 202 break; 203 } 204 } 205 } 206 207 { 208 const auto& sample = *instrument.samplelist[1]; 209 uUNIT_ASSERT_EQUAL(std::string("Snare-2"), sample.name); 210 uUNIT_ASSERT_EQUAL(0.0124808f, sample.power); 211 uUNIT_ASSERT_EQUAL(std::size_t(4), sample.audiofiles.size()); 212 for(const auto& audiofile : sample.audiofiles) 213 { 214 uUNIT_ASSERT_EQUAL(std::string("/tmp/2-Snare.wav"), audiofile.second->filename); 215 switch(audiofile.second->filechannel) 216 { 217 // NOTE: Channel numbers are zero based - they are 1 based in the xml 218 case 0: 219 uUNIT_ASSERT_EQUAL(std::string("AmbLeft"), 220 audiofile.second->instrument_channel->name); 221 break; 222 case 1: 223 uUNIT_ASSERT_EQUAL(std::string("AmbRight"), 224 audiofile.second->instrument_channel->name); 225 break; 226 case 11: 227 uUNIT_ASSERT_EQUAL(std::string("SnareBottom"), 228 audiofile.second->instrument_channel->name); 229 break; 230 case 12: 231 uUNIT_ASSERT_EQUAL(std::string("SnareTop"), 232 audiofile.second->instrument_channel->name); 233 break; 234 default: 235 uUNIT_ASSERT(false); 236 break; 237 } 238 } 239 } 240 } 241 242 // 243 // Instrument2 'Snare2' (version 1.0 instrument): 244 // 245 246 { 247 auto& instrument = *drumkit.instruments[1]; 248 uUNIT_ASSERT_EQUAL(std::string(""), instrument._group); 249 uUNIT_ASSERT_EQUAL(std::string("Snare2"), instrument._name); 250 uUNIT_ASSERT_EQUAL(std::string(""), instrument._description); 251 252 uUNIT_ASSERT(VersionStr("1.0.0") == instrument.version); 253 254 // NOTE: instrument.samples are the sample map belonging to version 1.0 255 uUNIT_ASSERT_EQUAL(std::size_t(2), instrument.samplelist.size()); 256 { 257 const auto& sample = *instrument.samplelist[0]; 258 uUNIT_ASSERT_EQUAL(std::string("Snare-1"), sample.name); 259 uUNIT_ASSERT_EQUAL(std::size_t(4), sample.audiofiles.size()); 260 auto afile = sample.audiofiles.begin(); 261 uUNIT_ASSERT_EQUAL(std::string("/tmp/1-Snare-1.wav"), afile->second->filename); 262 uUNIT_ASSERT_EQUAL(std::string("AmbLeft"), afile->second->instrument_channel->name); 263 ++afile; 264 uUNIT_ASSERT_EQUAL(std::string("/tmp/1-Snare-2.wav"), afile->second->filename); 265 uUNIT_ASSERT_EQUAL(std::string("AmbRight"), afile->second->instrument_channel->name); 266 ++afile; 267 uUNIT_ASSERT_EQUAL(std::string("/tmp/1-Snare-3.wav"), afile->second->filename); 268 uUNIT_ASSERT_EQUAL(std::string("SnareBottom"), afile->second->instrument_channel->name); 269 ++afile; 270 uUNIT_ASSERT_EQUAL(std::string("/tmp/1-Snare-4.wav"), afile->second->filename); 271 uUNIT_ASSERT_EQUAL(std::string("SnareTop"), afile->second->instrument_channel->name); 272 } 273 274 { 275 const auto& sample = *instrument.samplelist[1]; 276 uUNIT_ASSERT_EQUAL(std::string("Snare-2"), sample.name); 277 uUNIT_ASSERT_EQUAL(std::size_t(4), sample.audiofiles.size()); 278 auto afile = sample.audiofiles.begin(); 279 uUNIT_ASSERT_EQUAL(std::string("/tmp/2-Snare-1.wav"), afile->second->filename); 280 uUNIT_ASSERT_EQUAL(std::string("AmbLeft"), afile->second->instrument_channel->name); 281 ++afile; 282 uUNIT_ASSERT_EQUAL(std::string("/tmp/2-Snare-2.wav"), afile->second->filename); 283 uUNIT_ASSERT_EQUAL(std::string("AmbRight"), afile->second->instrument_channel->name); 284 ++afile; 285 uUNIT_ASSERT_EQUAL(std::string("/tmp/2-Snare-3.wav"), afile->second->filename); 286 uUNIT_ASSERT_EQUAL(std::string("SnareBottom"), afile->second->instrument_channel->name); 287 ++afile; 288 uUNIT_ASSERT_EQUAL(std::string("/tmp/2-Snare-4.wav"), afile->second->filename); 289 uUNIT_ASSERT_EQUAL(std::string("SnareTop"), afile->second->instrument_channel->name); 290 } 291 292 uUNIT_ASSERT_EQUAL(std::size_t(4), instrument.samples.values.size()); 293 auto value = instrument.samples.values.begin(); 294 uUNIT_ASSERT_EQUAL(0.0, value->first.first); // lower 295 uUNIT_ASSERT_EQUAL(0.6, value->first.second); // upper 296 uUNIT_ASSERT_EQUAL(std::string("Snare-1"), value->second->name); 297 ++value; 298 uUNIT_ASSERT_EQUAL(0.0, value->first.first); // lower 299 uUNIT_ASSERT_EQUAL(0.6, value->first.second); // upper 300 uUNIT_ASSERT_EQUAL(std::string("Snare-2"), value->second->name); 301 ++value; 302 uUNIT_ASSERT_EQUAL(0.6, value->first.first); // lower 303 uUNIT_ASSERT_EQUAL(1.0, value->first.second); // upper 304 uUNIT_ASSERT_EQUAL(std::string("Snare-2"), value->second->name); 305 ++value; 306 uUNIT_ASSERT_EQUAL(0.6, value->first.first); // lower 307 uUNIT_ASSERT_EQUAL(1.0, value->first.second); // upper 308 uUNIT_ASSERT_EQUAL(std::string("Snare-1"), value->second->name); 309 } 310 } 311 }; 312 313 // Registers the fixture into the 'registry' 314 static DOMLoaderTest test; 315