1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /*************************************************************************** 3 * lv2.cc 4 * 5 * Thu Feb 12 14:55:41 CET 2015 6 * Copyright 2015 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 <config.h> 30 31 #include <thread> 32 #include <chrono> 33 #include <memory.h> 34 #include <stdio.h> 35 #include <arpa/inet.h> 36 37 #include "drumkit_creator.h" 38 #include "lv2_test_host.h" 39 40 #define DG_URI "http://drumgizmo.org/lv2" 41 42 enum class Ports { 43 FreeWheel = 0, 44 Latency, 45 MidiPort, 46 AudioPortOffset, 47 }; 48 49 /** 50 * Tests that should be performed: 51 * ------------------------------- 52 * - Run without port connects (shouldn't crash) 53 * - Run without output ports connects (shouldn't crash) 54 * - Run with buffer size 0 55 * - Run with VERY LARGE buffer size (>1MB?) 56 * - Run with buffer size a prime number (and thereby not power of 2) 57 * - Run with HUGE number of midi events in one buffer (10000) 58 */ 59 class test_lv2 : public uUnit 60 { 61 public: test_lv2()62 test_lv2() 63 { 64 uUNIT_TEST(test_lv2::open_and_verify); 65 uUNIT_TEST(test_lv2::run_no_ports_connected); 66 uUNIT_TEST(test_lv2::run_no_output_ports_connected); 67 uUNIT_TEST(test_lv2::test1); 68 } 69 70 DrumkitCreator drumkit_creator; 71 open_and_verify()72 void open_and_verify() 73 { 74 int res; 75 76 LV2TestHost h(LV2_PATH); 77 78 res = h.open(DG_URI); 79 uUNIT_ASSERT_EQUAL(0, res); 80 81 res = h.verify(); 82 uUNIT_ASSERT_EQUAL(0, res); 83 84 res = h.close(); 85 uUNIT_ASSERT_EQUAL(0, res); 86 } 87 run_no_ports_connected()88 void run_no_ports_connected() 89 { 90 int res; 91 92 LV2TestHost h(LV2_PATH); 93 94 res = h.open(DG_URI); 95 uUNIT_ASSERT_EQUAL(0, res); 96 97 res = h.verify(); 98 uUNIT_ASSERT_EQUAL(0, res); 99 100 res = h.createInstance(44100); 101 uUNIT_ASSERT_EQUAL(0, res); 102 103 const char config_fmt[] = 104 "<config>\n" 105 " <value name=\"drumkitfile\">%s</value>\n" 106 " <value name=\"midimapfile\">%s</value>\n" 107 " <value name=\"enable_velocity_modifier\">%s</value>\n" 108 " <value name=\"velocity_modifier_falloff\">%f</value>\n" 109 " <value name=\"velocity_modifier_weight\">%f</value>\n" 110 " <value name=\"enable_velocity_randomiser\">%s</value>\n" 111 " <value name=\"velocity_randomiser_weight\">%f</value>\n" 112 " <value name=\"enable_resampling\">%s</value>\n" 113 " <value name=\"enable_resampling\">%s</value>\n" 114 " <value name=\"disk_cache_upper_limit\">%d</value>\n" 115 " <value name=\"disk_cache_chunk_size\">%d</value>\n" 116 " <value name=\"disk_cache_enable\">%s</value>\n" 117 " <value name=\"enable_bleed_control\">%s</value>\n" 118 " <value name=\"master_bleed\">%f</value>\n" 119 " <value name=\"enable_latency_modifier\">%s</value>\n" 120 " <value name=\"latency_max\">%d</value>\n" 121 " <value name=\"latency_laid_back\">%d</value>\n" 122 " <value name=\"latency_stddev\">%f</value>\n" 123 " <value name=\"latency_regain\">%f</value>\n" 124 "</config>"; 125 126 // Create drumkit 127 auto kit1_file = drumkit_creator.createStdKit("kit1"); 128 129 auto midimapfile = drumkit_creator.createStdMidimap("midimap"); 130 bool enable_velocity_modifier = true; 131 float velocity_modifier_falloff = 0.5; 132 float velocity_modifier_weight = 0.25; 133 bool enable_velocity_randomiser = false; 134 float velocity_randomiser_weight = 0.1; 135 bool enable_resampling = false; 136 int disk_cache_upper_limit = 1024 * 1024; 137 int disk_cache_chunk_size = 1024 * 1024 * 1024; 138 bool disk_cache_enable = true; 139 bool enable_bleed_control = false; 140 float master_bleed = 1.0f; 141 bool enable_latency_modifier = false; 142 int latency_max = 0u; 143 int latency_laid_back = 0u; 144 float latency_stddev = 100.0f; 145 float latency_regain = 0.9f; 146 147 char config[sizeof(config_fmt) * 2]; 148 sprintf(config, config_fmt, 149 kit1_file.c_str(), 150 midimapfile.c_str(), 151 enable_velocity_modifier?"true":"false", 152 velocity_modifier_falloff, 153 velocity_modifier_weight, 154 enable_velocity_randomiser?"true":"false", 155 velocity_randomiser_weight, 156 enable_resampling?"true":"false", 157 enable_resampling?"true":"false", 158 disk_cache_upper_limit, 159 disk_cache_chunk_size, 160 disk_cache_enable?"true":"false", 161 enable_bleed_control?"true":"false", 162 master_bleed, 163 enable_latency_modifier?"true":"false", 164 latency_max, 165 latency_laid_back, 166 latency_stddev, 167 latency_regain); 168 169 res = h.loadConfig(config, strlen(config)); 170 uUNIT_ASSERT_EQUAL(0, res); 171 172 // run for 1 samples to trigger kit loading 173 res = h.run(1); 174 uUNIT_ASSERT_EQUAL(0, res); 175 std::this_thread::sleep_for(std::chrono::milliseconds(1)); // wait for kit to get loaded (async), 176 177 res = h.run(100); 178 uUNIT_ASSERT_EQUAL(0, res); 179 180 res = h.destroyInstance(); 181 uUNIT_ASSERT_EQUAL(0, res); 182 183 res = h.close(); 184 uUNIT_ASSERT_EQUAL(0, res); 185 } 186 run_no_output_ports_connected()187 void run_no_output_ports_connected() 188 { 189 int res; 190 191 LV2TestHost h(LV2_PATH); 192 193 res = h.open(DG_URI); 194 uUNIT_ASSERT_EQUAL(0, res); 195 196 res = h.verify(); 197 uUNIT_ASSERT_EQUAL(0, res); 198 199 res = h.createInstance(44100); 200 uUNIT_ASSERT_EQUAL(0, res); 201 202 const char config_fmt[] = 203 "<config>\n" 204 " <value name=\"drumkitfile\">%s</value>\n" 205 " <value name=\"midimapfile\">%s</value>\n" 206 " <value name=\"enable_velocity_modifier\">%s</value>\n" 207 " <value name=\"velocity_modifier_falloff\">%f</value>\n" 208 " <value name=\"velocity_modifier_weight\">%f</value>\n" 209 " <value name=\"enable_velocity_randomiser\">%s</value>\n" 210 " <value name=\"velocity_randomiser_weight\">%f</value>\n" 211 " <value name=\"enable_resampling\">%s</value>\n" 212 " <value name=\"enable_resampling\">%s</value>\n" 213 " <value name=\"disk_cache_upper_limit\">%d</value>\n" 214 " <value name=\"disk_cache_chunk_size\">%d</value>\n" 215 " <value name=\"disk_cache_enable\">%s</value>\n" 216 " <value name=\"enable_bleed_control\">%s</value>\n" 217 " <value name=\"master_bleed\">%f</value>\n" 218 " <value name=\"enable_latency_modifier\">%s</value>\n" 219 " <value name=\"latency_max\">%d</value>\n" 220 " <value name=\"latency_laid_back\">%d</value>\n" 221 " <value name=\"latency_stddev\">%f</value>\n" 222 " <value name=\"latency_regain\">%f</value>\n" 223 "</config>"; 224 225 // Create drumkit 226 auto kit1_file = drumkit_creator.createStdKit("kit1"); 227 228 auto midimapfile = drumkit_creator.createStdMidimap("midimap"); 229 bool enable_velocity_modifier = true; 230 float velocity_modifier_falloff = 0.5; 231 float velocity_modifier_weight = 0.25; 232 bool enable_velocity_randomiser = false; 233 float velocity_randomiser_weight = 0.1; 234 bool enable_resampling = false; 235 int disk_cache_upper_limit = 1024 * 1024; 236 int disk_cache_chunk_size = 1024 * 1024 * 1024; 237 bool disk_cache_enable = true; 238 bool enable_bleed_control = false; 239 float master_bleed = 1.0f; 240 bool enable_latency_modifier = false; 241 int latency_max = 0u; 242 int latency_laid_back = 0u; 243 float latency_stddev = 100.0f; 244 float latency_regain = 0.9f; 245 246 char config[sizeof(config_fmt) * 2]; 247 sprintf(config, config_fmt, 248 kit1_file.c_str(), 249 midimapfile.c_str(), 250 enable_velocity_modifier?"true":"false", 251 velocity_modifier_falloff, 252 velocity_modifier_weight, 253 enable_velocity_randomiser?"true":"false", 254 velocity_randomiser_weight, 255 enable_resampling?"true":"false", 256 enable_resampling?"true":"false", 257 disk_cache_upper_limit, 258 disk_cache_chunk_size, 259 disk_cache_enable?"true":"false", 260 enable_bleed_control?"true":"false", 261 master_bleed, 262 enable_latency_modifier?"true":"false", 263 latency_max, 264 latency_laid_back, 265 latency_stddev, 266 latency_regain); 267 268 res = h.loadConfig(config, strlen(config)); 269 uUNIT_ASSERT_EQUAL(0, res); 270 271 // Port buffers: 272 char sequence_buffer[4096]; 273 bool freeWheel = false; 274 275 // Free wheel port 276 res = h.connectPort((int)Ports::FreeWheel, (void*)&freeWheel); 277 278 LV2TestHost::Sequence seq(sequence_buffer, sizeof(sequence_buffer)); 279 res = h.connectPort((int)Ports::MidiPort, seq.data()); 280 uUNIT_ASSERT_EQUAL(0, res); 281 282 // run for 1 samples to trigger kit loading 283 res = h.run(1); 284 uUNIT_ASSERT_EQUAL(0, res); 285 std::this_thread::sleep_for(std::chrono::milliseconds(1)); // wait for kit to get loaded (async), 286 287 seq.addMidiNote(5, 1, 127); 288 res = h.run(100); 289 uUNIT_ASSERT_EQUAL(0, res); 290 291 res = h.destroyInstance(); 292 uUNIT_ASSERT_EQUAL(0, res); 293 294 res = h.close(); 295 uUNIT_ASSERT_EQUAL(0, res); 296 } 297 test1()298 void test1() 299 { 300 int res; 301 302 LV2TestHost h(LV2_PATH); 303 304 res = h.open(DG_URI); 305 uUNIT_ASSERT_EQUAL(0, res); 306 307 res = h.verify(); 308 uUNIT_ASSERT_EQUAL(0, res); 309 310 res = h.createInstance(44100); 311 uUNIT_ASSERT_EQUAL(0, res); 312 313 const char config_fmt[] = 314 "<config>\n" 315 " <value name=\"drumkitfile\">%s</value>\n" 316 " <value name=\"midimapfile\">%s</value>\n" 317 " <value name=\"enable_velocity_modifier\">%s</value>\n" 318 " <value name=\"velocity_modifier_falloff\">%f</value>\n" 319 " <value name=\"velocity_modifier_weight\">%f</value>\n" 320 " <value name=\"enable_velocity_randomiser\">%s</value>\n" 321 " <value name=\"velocity_randomiser_weight\">%f</value>\n" 322 " <value name=\"enable_resampling\">%s</value>\n" 323 " <value name=\"enable_resampling\">%s</value>\n" 324 " <value name=\"disk_cache_upper_limit\">%d</value>\n" 325 " <value name=\"disk_cache_chunk_size\">%d</value>\n" 326 " <value name=\"disk_cache_enable\">%s</value>\n" 327 " <value name=\"enable_bleed_control\">%s</value>\n" 328 " <value name=\"master_bleed\">%f</value>\n" 329 " <value name=\"enable_latency_modifier\">%s</value>\n" 330 " <value name=\"latency_max\">%d</value>\n" 331 " <value name=\"latency_laid_back\">%d</value>\n" 332 " <value name=\"latency_stddev\">%f</value>\n" 333 " <value name=\"latency_regain\">%f</value>\n" 334 "</config>"; 335 336 // Create drumkit 337 auto kit1_file = drumkit_creator.createStdKit("kit1"); 338 339 auto midimapfile = drumkit_creator.createStdMidimap("midimap"); 340 bool enable_velocity_modifier = true; 341 float velocity_modifier_falloff = 0.5; 342 float velocity_modifier_weight = 0.25; 343 bool enable_velocity_randomiser = false; 344 float velocity_randomiser_weight = 0.1; 345 bool enable_resampling = false; 346 int disk_cache_upper_limit = 1024 * 1024; 347 int disk_cache_chunk_size = 1024 * 1024 * 1024; 348 bool disk_cache_enable = true; 349 bool enable_bleed_control = false; 350 float master_bleed = 1.0f; 351 bool enable_latency_modifier = false; 352 int latency_max = 0u; 353 int latency_laid_back = 0u; 354 float latency_stddev = 100.0f; 355 float latency_regain = 0.9f; 356 357 char config[sizeof(config_fmt) * 2]; 358 sprintf(config, config_fmt, 359 kit1_file.c_str(), 360 midimapfile.c_str(), 361 enable_velocity_modifier?"true":"false", 362 velocity_modifier_falloff, 363 velocity_modifier_weight, 364 enable_velocity_randomiser?"true":"false", 365 velocity_randomiser_weight, 366 enable_resampling?"true":"false", 367 enable_resampling?"true":"false", 368 disk_cache_upper_limit, 369 disk_cache_chunk_size, 370 disk_cache_enable?"true":"false", 371 enable_bleed_control?"true":"false", 372 master_bleed, 373 enable_latency_modifier?"true":"false", 374 latency_max, 375 latency_laid_back, 376 latency_stddev, 377 latency_regain); 378 379 res = h.loadConfig(config, strlen(config)); 380 uUNIT_ASSERT_EQUAL(0, res); 381 382 // Port buffers: 383 char sequence_buffer[4096]; 384 float pcm_buffer[NUM_CHANNELS][10]; 385 bool freeWheel = true; 386 387 // Free wheel port 388 res = h.connectPort((int)Ports::FreeWheel, (void*)&freeWheel); 389 390 LV2TestHost::Sequence seq(sequence_buffer, sizeof(sequence_buffer)); 391 res = h.connectPort((int)Ports::MidiPort, seq.data()); 392 uUNIT_ASSERT_EQUAL(0, res); 393 394 for(int i = 0; i < NUM_CHANNELS; ++i) 395 { 396 for(int j = 0; j < 10; ++j) 397 { 398 pcm_buffer[i][j] = 0.42; 399 } 400 res += h.connectPort((int)Ports::AudioPortOffset + i, pcm_buffer[i]); 401 } 402 uUNIT_ASSERT_EQUAL(0, res); 403 404 // run for 1 samples to trigger kit loading 405 res = h.run(1); 406 uUNIT_ASSERT_EQUAL(0, res); 407 std::this_thread::sleep_for(std::chrono::seconds(1)); // wait for kit to get loaded (async), 408 409 seq.addMidiNote(5, 1, 127); 410 for(int i = 0; i < 10; i++) 411 { 412 res = h.run(10); 413 std::this_thread::sleep_for(std::chrono::milliseconds(1)); 414 uUNIT_ASSERT_EQUAL(0, res); 415 416 //printf("Iteration:\n"); 417 //for(int k = 0; k < 16; k++) { 418 // printf("#%d ", k); 419 // for(int j = 0; j < 10; j++) printf("[%f]", pcm_buffer[k][j]); 420 // printf("\n"); 421 //} 422 //printf("\n"); 423 424 seq.clear(); 425 } 426 427 428 seq.addMidiNote(5, 1, 127); 429 res = h.run(10); 430 std::this_thread::sleep_for(std::chrono::milliseconds(1)); 431 uUNIT_ASSERT_EQUAL(0, res); 432 433 /* 434 printf("Iteration:\n"); 435 for(int k = 0; k < 4; k++) { 436 printf("#%d ", k); 437 for(int j = 0; j < 10; j++) printf("[%f]", pcm_buffer[k][j]); 438 printf("\n"); 439 } 440 printf("\n"); 441 */ 442 443 union { 444 float f; 445 unsigned int u; 446 } comp_val; 447 448 comp_val.u = 1040744448; // floating point value 0.133301.... 449 450 for(int k = 0; k < 4; k++) 451 { 452 for(int j = 0; j < 10; j++) 453 { 454 uUNIT_ASSERT_EQUAL(((j==5)?comp_val.f:0), pcm_buffer[k][j]); 455 } 456 } 457 seq.clear(); 458 459 res = h.destroyInstance(); 460 uUNIT_ASSERT_EQUAL(0, res); 461 462 res = h.close(); 463 uUNIT_ASSERT_EQUAL(0, res); 464 } 465 }; 466 467 // Registers the fixture into the 'registry' 468 static test_lv2 test; 469