diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/Makefile.am | 61 | ||||
| -rw-r--r-- | test/audiocacheeventhandlertest.cc | 52 | ||||
| -rw-r--r-- | test/audiocachefiletest.cc | 240 | ||||
| -rw-r--r-- | test/audiocacheidmanagertest.cc | 101 | ||||
| -rw-r--r-- | test/audiocachetest.cc | 180 | ||||
| -rw-r--r-- | test/engine.cc | 1 | ||||
| -rw-r--r-- | test/kit/ride-multi-channel.wav | bin | 0 -> 28591492 bytes | |||
| -rw-r--r-- | test/kit/ride-single-channel.wav | bin | 0 -> 694144 bytes | |||
| -rw-r--r-- | test/lv2.cc | 67 | ||||
| -rw-r--r-- | test/lv2_test_host.cc | 178 | ||||
| -rw-r--r-- | test/lv2_test_host.h | 61 | 
11 files changed, 816 insertions, 125 deletions
| diff --git a/test/Makefile.am b/test/Makefile.am index 29ab4b1..8a746a6 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,7 +1,8 @@  # Rules for the test code (use `make check` to execute)  include $(top_srcdir)/src/Makefile.am.drumgizmo -TESTS = resource engine gui resampler lv2 configfile +TESTS = resource engine gui resampler lv2 configfile audiocache \ +	audiocachefile audiocacheidmanager audiocacheeventhandler  check_PROGRAMS = $(TESTS) @@ -15,9 +16,65 @@ resource_SOURCES = \  	test.cc \  	resource_test.cc +audiocache_CXXFLAGS = -DOUTPUT=\"audiocache\" $(CPPUNIT_CFLAGS) \ +	-I$(top_srcdir)/src -I$(top_srcdir)/include \ +	-I$(top_srcdir)/hugin -DDISABLE_HUGIN $(PTHREAD_CFLAGS) $(SNDFILE_CFLAGS) +audiocache_LDFLAGS = $(PTHREAD_LIBS) $(CPPUNIT_LIBS) $(SNDFILE_LIBS) +audiocache_SOURCES = \ +	$(top_srcdir)/src/audiocache.cc \ +	$(top_srcdir)/src/audiocacheeventhandler.cc \ +	$(top_srcdir)/src/audiocachefile.cc \ +	$(top_srcdir)/src/audiocacheidmanager.cc \ +	$(top_srcdir)/src/thread.cc \ +	$(top_srcdir)/src/mutex.cc \ +	$(top_srcdir)/src/semaphore.cc \ +	$(top_srcdir)/src/configuration.cc \ +	$(top_srcdir)/src/audiofile.cc \ +	test.cc \ +	audiocachetest.cc + +audiocachefile_CXXFLAGS = -DOUTPUT=\"audiocachefile\" $(CPPUNIT_CFLAGS) \ +	-I$(top_srcdir)/src -I$(top_srcdir)/include \ +	-I$(top_srcdir)/hugin -DDISABLE_HUGIN $(PTHREAD_CFLAGS) $(SNDFILE_CFLAGS) +audiocachefile_LDFLAGS = $(PTHREAD_LIBS) $(CPPUNIT_LIBS) $(SNDFILE_LIBS) +audiocachefile_SOURCES = \ +	$(top_srcdir)/src/audiocachefile.cc \ +	$(top_srcdir)/src/thread.cc \ +	$(top_srcdir)/src/mutex.cc \ +	$(top_srcdir)/src/semaphore.cc \ +	$(top_srcdir)/src/configuration.cc \ +	$(top_srcdir)/src/audiofile.cc \ +	test.cc \ +	audiocachefiletest.cc + +audiocacheidmanager_CXXFLAGS = -DOUTPUT=\"audiocacheidmanager\" \ +	$(CPPUNIT_CFLAGS) \ +	-I$(top_srcdir)/src -I$(top_srcdir)/include \ +	-I$(top_srcdir)/hugin -DDISABLE_HUGIN $(SNDFILE_CFLAGS) +audiocacheidmanager_LDFLAGS = $(CPPUNIT_LIBS) $(SNDFILE_LIBS) +audiocacheidmanager_SOURCES = \ +	$(top_srcdir)/src/audiocacheidmanager.cc \ +	test.cc \ +	audiocacheidmanagertest.cc + +audiocacheeventhandler_CXXFLAGS = -DOUTPUT=\"audiocacheeventhandler\" \ +	$(CPPUNIT_CFLAGS) \ +	-I$(top_srcdir)/src -I$(top_srcdir)/include \ +	-I$(top_srcdir)/hugin -DDISABLE_HUGIN $(PTHREAD_CFLAGS) $(SNDFILE_CFLAGS) +audiocacheeventhandler_LDFLAGS = $(PTHREAD_LIBS) $(CPPUNIT_LIBS) $(SNDFILE_LIBS) +audiocacheeventhandler_SOURCES = \ +	$(top_srcdir)/src/audiocacheeventhandler.cc \ +	$(top_srcdir)/src/audiocacheidmanager.cc \ +	$(top_srcdir)/src/audiocachefile.cc \ +	$(top_srcdir)/src/mutex.cc \ +	$(top_srcdir)/src/thread.cc \ +	$(top_srcdir)/src/semaphore.cc \ +	test.cc \ +	audiocacheeventhandlertest.cc +  engine_CXXFLAGS = -DOUTPUT=\"engine\" $(CPPUNIT_CFLAGS) \  	-I$(top_srcdir)/src -I$(top_srcdir)/include \ -	-I$(top_srcdir)/hugin -DDISABLE_HUGIN +	-I$(top_srcdir)/hugin -DDISABLE_HUGIN $(PTHREAD_CFLAGS)  engine_CFLAGS = -DDISABLE_HUGIN  engine_LDFLAGS = $(CPPUNIT_LIBS) $(DRUMGIZMO_LIBS) $(PTHREAD_LIBS)  engine_SOURCES = \ diff --git a/test/audiocacheeventhandlertest.cc b/test/audiocacheeventhandlertest.cc new file mode 100644 index 0000000..5f30d2e --- /dev/null +++ b/test/audiocacheeventhandlertest.cc @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            audiocacheeventhandlertest.cc + * + *  Thu Jan  7 15:44:14 CET 2016 + *  Copyright 2016 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of DrumGizmo. + * + *  DrumGizmo is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  DrumGizmo is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with DrumGizmo; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <cppunit/extensions/HelperMacros.h> + +#include <audiocacheeventhandler.h> + +class AudioCacheEventHandlerTest +	: public CppUnit::TestFixture +{ +	CPPUNIT_TEST_SUITE(AudioCacheEventHandlerTest); +	CPPUNIT_TEST(threadedTest); +	CPPUNIT_TEST_SUITE_END(); + +public: +	void setUp() {} +	void tearDown() {} + +	void threadedTest() +	{ +		AudioCacheIDManager id_manager; +		id_manager.init(10); + +		AudioCacheEventHandler event_handler(id_manager); +	} +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(AudioCacheEventHandlerTest); diff --git a/test/audiocachefiletest.cc b/test/audiocachefiletest.cc new file mode 100644 index 0000000..98b7ab5 --- /dev/null +++ b/test/audiocachefiletest.cc @@ -0,0 +1,240 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            audiocachefiletest.cc + * + *  Thu Jan  7 15:43:12 CET 2016 + *  Copyright 2016 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of DrumGizmo. + * + *  DrumGizmo is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  DrumGizmo is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with DrumGizmo; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <cppunit/extensions/HelperMacros.h> + +#include <cstring> + +#include <audiocachefile.h> +#include <audiofile.h> + +class TestableAudioCacheFiles +	: public AudioCacheFiles +{ +public: +	//CacheAudioFile& getAudioFile(const std::string& filename); +	//void release(const std::string& filename); +	int getRef(const std::string& filename) +	{ +		if(audiofiles.find(filename) == audiofiles.end()) +		{ +			return -1; +		} + +		return audiofiles[filename]->ref; +	} +}; + +class AudioCacheFileTest +	: public CppUnit::TestFixture +{ +	CPPUNIT_TEST_SUITE(AudioCacheFileTest); +	CPPUNIT_TEST(refTest); +	CPPUNIT_TEST(readTest); +	CPPUNIT_TEST(noFileTest); +	CPPUNIT_TEST_SUITE_END(); + +public: +	void setUp() {} +	void tearDown() {} + +	void refTest() +	{ +		TestableAudioCacheFiles audiofiles; +		std::string filename = "kit/ride-single-channel.wav"; +		CPPUNIT_ASSERT_EQUAL(-1, audiofiles.getRef(filename)); + +		audiofiles.getFile(filename); +		CPPUNIT_ASSERT_EQUAL(1, audiofiles.getRef(filename)); + +		audiofiles.getFile(filename); +		CPPUNIT_ASSERT_EQUAL(2, audiofiles.getRef(filename)); + +		audiofiles.releaseFile(filename); +		CPPUNIT_ASSERT_EQUAL(1, audiofiles.getRef(filename)); + +		audiofiles.releaseFile(filename); +		CPPUNIT_ASSERT_EQUAL(-1, audiofiles.getRef(filename)); +	} + +	void readTestHelper(size_t buffer_size) +	{ +		printf("Test buffer size: %d samples\n", (int)buffer_size); + +		std::string filename = "kit/ride-multi-channel.wav"; +		AudioFile* ref_file[13]; +		for(size_t c = 0; c < 13; ++c) +		{ +			ref_file[c] = new AudioFile(filename, c); +			ref_file[c]->load(); +		} + +		AudioCacheFile file(filename); +		CPPUNIT_ASSERT_EQUAL(filename, file.getFilename()); +		CPPUNIT_ASSERT_EQUAL(13, (int)file.getChannelCount()); // Sanity check + +		CacheChannels channels; + +		sample_t samples[13][buffer_size]; +		volatile bool ready[13]; +		for(size_t c = 0; c < 13; ++c) +		{ +			for(size_t i = 0; i < buffer_size; ++i) +			{ +				samples[c][i] = 42; +			} + +			channels.push_back( +				{ +					c, // channel +					samples[c], // samples +					buffer_size, // max_num_samples +					&ready[c] // ready +				} +			); +		} + +		for(size_t offset = 0; offset < file.getSize(); offset += buffer_size) +		{ +			for(size_t c = 0; c < 13; ++c) +			{ +				ready[c] = false; +			} + +			size_t read_size = file.getSize() - offset; +			if(read_size > buffer_size) +			{ +				read_size = buffer_size; +			} +			else +			{ +				printf("Last read: %d samples\n", (int)read_size); +			} + +			file.readChunk(channels, offset, read_size); + +			for(size_t c = 0; c < 13; ++c) +			{ +				CPPUNIT_ASSERT_EQUAL(true, ready[c]?true:false); +			} + +			sample_t diff[13] = {0.0}; +			for(size_t c = 0; c < 13; ++c) +			{ +				for(size_t i = 0; i < read_size; ++i) +				{ +					diff[c] += abs(ref_file[c]->data[i + offset] - samples[c][i]); +				} +			} + +			for(int c = 0; c < 13; ++c) +			{ +				CPPUNIT_ASSERT_EQUAL((sample_t)0.0, diff[c]); +			} +		} + +		for(size_t c = 0; c < 13; ++c) +		{ +			delete ref_file[c]; +		} +	} + +	void readTest() +	{ +		// Exhaustive test for 1...64 +		for(size_t buffer_size = 1; buffer_size < 64; ++buffer_size) +		{ +			readTestHelper(buffer_size); +		} + +		// Binary test for 64 .. 4096 +		for(size_t buffer_size = 64; buffer_size < 4096; buffer_size *= 2) +		{ +			readTestHelper(buffer_size); +		} + +		// And some sporadic tests for some "wierd" sizes. +		for(size_t buffer_size = 65; buffer_size < 4096; buffer_size *= 1.1) +		{ +			readTestHelper(buffer_size); +		} +	} + +	void noFileTest() +	{ +		size_t buffer_size = 64; +		std::string filename = "kits/no-such-file.wav"; + +		AudioCacheFile file(filename); +		CPPUNIT_ASSERT_EQUAL(filename, file.getFilename()); +		CPPUNIT_ASSERT_EQUAL(0u, (unsigned int)file.getSize()); +		CPPUNIT_ASSERT_EQUAL(0u, (unsigned int)file.getChannelCount()); + +		CacheChannels channels; + +		sample_t samples[13][buffer_size]; +		volatile bool ready[13]; +		for(size_t c = 0; c < 13; ++c) +		{ +			for(size_t i = 0; i < buffer_size; ++i) +			{ +				samples[c][i] = 42.0f; +			} + +			channels.push_back( +				{ +					c, // channel +					samples[c], // samples +					buffer_size, // max_num_samples +					&ready[c] // ready +				} +			); +		} + +		for(size_t c = 0; c < 13; ++c) +		{ +			ready[c] = false; +		} + +		file.readChunk(channels, 0, buffer_size); + +		for(size_t c = 0; c < 13; ++c) +		{ +			CPPUNIT_ASSERT_EQUAL(false, ready[c]?true:false); +		} + +		for(size_t c = 0; c < 13; ++c) +		{ +			for(size_t i = 0; i < buffer_size; ++i) +			{ +				CPPUNIT_ASSERT_EQUAL(42.0f, samples[c][i]); +			} +		} +	} +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(AudioCacheFileTest); diff --git a/test/audiocacheidmanagertest.cc b/test/audiocacheidmanagertest.cc new file mode 100644 index 0000000..a9cc878 --- /dev/null +++ b/test/audiocacheidmanagertest.cc @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            audiocacheidmanagertest.cc + * + *  Thu Jan  7 15:42:31 CET 2016 + *  Copyright 2016 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of DrumGizmo. + * + *  DrumGizmo is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  DrumGizmo is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with DrumGizmo; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <cppunit/extensions/HelperMacros.h> + +#include <audiocacheidmanager.h> + +class TestableAudioCacheIDManager +	: public AudioCacheIDManager +{ +public: +	int getAvailableIDs() +	{ +		return availableids.size(); +	} +}; + +class AudioCacheIDManagerTest +	: public CppUnit::TestFixture +{ +	CPPUNIT_TEST_SUITE(AudioCacheIDManagerTest); +	CPPUNIT_TEST(registerReleaseTest); +	CPPUNIT_TEST_SUITE_END(); + +public: +	void setUp() {} +	void tearDown() {} + +	void registerReleaseTest() +	{ +		TestableAudioCacheIDManager manager; +		manager.init(2); + +		cache_t c1; c1.afile = (AudioCacheFile*)1; +		auto id1 = manager.registerID(c1); +		CPPUNIT_ASSERT(id1 != CACHE_DUMMYID); +		CPPUNIT_ASSERT(id1 != CACHE_NOID); +		CPPUNIT_ASSERT_EQUAL(1, manager.getAvailableIDs()); + +		cache_t c2; c2.afile = (AudioCacheFile*)2; +		auto id2 = manager.registerID(c2); +		CPPUNIT_ASSERT(id2 != CACHE_DUMMYID); +		CPPUNIT_ASSERT(id2 != CACHE_NOID); +		CPPUNIT_ASSERT_EQUAL(0, manager.getAvailableIDs()); + +		cache_t c3; c3.afile = (AudioCacheFile*)3; +		auto id3 = manager.registerID(c3); +		CPPUNIT_ASSERT(id3 == CACHE_DUMMYID); +		CPPUNIT_ASSERT_EQUAL(0, manager.getAvailableIDs()); + +		cache_t& tc1 = manager.getCache(id1); +		CPPUNIT_ASSERT_EQUAL(c1.afile, tc1.afile); + +		cache_t& tc2 = manager.getCache(id2); +		CPPUNIT_ASSERT_EQUAL(c2.afile, tc2.afile); + +		manager.releaseID(id1); +		CPPUNIT_ASSERT_EQUAL(1, manager.getAvailableIDs()); + +		cache_t c4; c4.afile = (AudioCacheFile*)4; +		auto id4 = manager.registerID(c4); +		CPPUNIT_ASSERT(id4 != CACHE_DUMMYID); +		CPPUNIT_ASSERT(id4 != CACHE_NOID); +		CPPUNIT_ASSERT_EQUAL(0, manager.getAvailableIDs()); + +		cache_t& tc4 = manager.getCache(id4); +		CPPUNIT_ASSERT_EQUAL(c4.afile, tc4.afile); + +		manager.releaseID(id2); +		CPPUNIT_ASSERT_EQUAL(1, manager.getAvailableIDs()); + +		manager.releaseID(id4); +		CPPUNIT_ASSERT_EQUAL(2, manager.getAvailableIDs()); +	} +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(AudioCacheIDManagerTest); diff --git a/test/audiocachetest.cc b/test/audiocachetest.cc new file mode 100644 index 0000000..5db5940 --- /dev/null +++ b/test/audiocachetest.cc @@ -0,0 +1,180 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            cachemanagertest.cc + * + *  Sun Apr 19 10:15:59 CEST 2015 + *  Copyright 2015 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of DrumGizmo. + * + *  DrumGizmo is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  DrumGizmo is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with DrumGizmo; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <cppunit/extensions/HelperMacros.h> + +#include <audiofile.h> +#include <audiocache.h> +#include <unistd.h> + +#define FRAMESIZE 64 + +class AudioCacheTest +	: public CppUnit::TestFixture +{ +	CPPUNIT_TEST_SUITE(AudioCacheTest); +	CPPUNIT_TEST(singleChannelNonThreaded); +	CPPUNIT_TEST(singleChannelThreaded); +	CPPUNIT_TEST(multiChannelNonThreaded); +	CPPUNIT_TEST(multiChannelThreaded); +	CPPUNIT_TEST_SUITE_END(); + +public: +	void setUp() {} +	void tearDown() {} + +	//! Test runner. +	//! \param filename The name of the file to read. +	//! \param channel The channel number to do comparison on. +	//! \param thread Control if this test is running in threaded mode or not. +	//! \param framesize The initial framesize to use. +	void testHelper(const char* filename, int channel, bool threaded, +	                int framesize) +	{ +		// Reference file: +		AudioFile audio_file_ref(filename, channel); +		printf("audio_file_ref.load\n"); +		audio_file_ref.load(ALL_SAMPLES); + +		// Input file: +		AudioFile audio_file(filename, channel); +		printf("audio_file.load\n"); +		audio_file.load(4096); + +		AudioCache audio_cache; +		printf("audio_cache.init\n"); +		audio_cache.init(100); +		audio_cache.setAsyncMode(threaded); + +		// Set initial (upper limit) framesize +		audio_cache.setFrameSize(framesize); + +		cacheid_t id; + +		for(size_t initial_samples_needed = 0; +		    initial_samples_needed < (size_t)(framesize + 1); +		    ++initial_samples_needed) +		{ + +			printf("open: initial_samples_needed: %d\n", (int)initial_samples_needed); +			sample_t *samples = +				audio_cache.open(&audio_file, initial_samples_needed, channel, id); +			size_t size = initial_samples_needed; +			size_t offset = 0; + +			// Test pre cache: +			for(size_t i = 0; i < size; ++i) +			{ +				CPPUNIT_ASSERT_EQUAL(audio_file_ref.data[offset], samples[i]); +				++offset; +			} + +			// Test the rest +			while(offset < audio_file_ref.size) +			{ +				if(threaded) +				{ +					// Wait until we are finished reading +					int timeout = 1000; +					while(!audio_cache.isReady(id)) +					{ +						usleep(1000); +						if(--timeout == 0) +						{ +							CPPUNIT_ASSERT(false); // timeout +						} +					} +				} + +				samples = audio_cache.next(id, size); + +				CPPUNIT_ASSERT_EQUAL(0, (int)audio_cache.getNumberOfUnderruns()); + +				for(size_t i = 0; (i < size) && (offset < audio_file_ref.size); ++i) +				{ +					if(audio_file_ref.data[offset] != samples[i]) +					{ +						printf("-----> offset: %d, size: %d, diff: %d," +						       " i: %d, size: %d, block-diff: %d\n", +						       (int)offset, (int)audio_file_ref.size, +						       (int)(audio_file_ref.size - offset), +						       (int)i, (int)size, (int)(size - i)); +					} +					CPPUNIT_ASSERT_EQUAL(audio_file_ref.data[offset], samples[i]); +					++offset; +				} +			} + +			audio_cache.close(id); +		} + +		printf("done\n"); +	} + +	void singleChannelNonThreaded() +	{ +		printf("\nsinglechannel_nonthreaded()\n"); +		const char filename[] = "kit/ride-single-channel.wav"; +		int channel = 0; +		bool threaded = false; +		testHelper(filename, channel, threaded, FRAMESIZE); +	} + +	void singleChannelThreaded() +	{ +		printf("\nsinglechannel_threaded()\n"); +		const char filename[] = "kit/ride-single-channel.wav"; +		int channel = 0; +		bool threaded = true; +		testHelper(filename, channel, threaded, FRAMESIZE); +	} + +	void multiChannelNonThreaded() +	{ +		printf("\nmultichannel_nonthreaded()\n"); +		const char filename[] = "kit/ride-multi-channel.wav"; +		int channel = 0; +		bool threaded = false; +		testHelper(filename, channel, threaded, FRAMESIZE); +		++channel; +		testHelper(filename, channel, threaded, FRAMESIZE); +	} + +	void multiChannelThreaded() +	{ +		printf("\nmultichannel_threaded()\n"); +		const char filename[] = "kit/ride-multi-channel.wav"; +		int channel = 0; +		bool threaded = true; +		testHelper(filename, channel, threaded, FRAMESIZE); +		++channel; +		testHelper(filename, channel, threaded, FRAMESIZE); +	} + +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(AudioCacheTest); diff --git a/test/engine.cc b/test/engine.cc index 69d2a37..4c49a6c 100644 --- a/test/engine.cc +++ b/test/engine.cc @@ -43,6 +43,7 @@ public:      AudioOutputEngine *oe = NULL;      AudioInputEngine *ie = NULL;      DrumGizmo dg(oe, ie); +    dg.setFrameSize(100);      // Switch kits emmidiately with giving the loader time to work:      for(int i = 0; i < 100; i++) { diff --git a/test/kit/ride-multi-channel.wav b/test/kit/ride-multi-channel.wavBinary files differ new file mode 100644 index 0000000..3dec8a9 --- /dev/null +++ b/test/kit/ride-multi-channel.wav diff --git a/test/kit/ride-single-channel.wav b/test/kit/ride-single-channel.wavBinary files differ new file mode 100644 index 0000000..1760697 --- /dev/null +++ b/test/kit/ride-single-channel.wav diff --git a/test/lv2.cc b/test/lv2.cc index 32d896c..0ecf178 100644 --- a/test/lv2.cc +++ b/test/lv2.cc @@ -35,6 +35,12 @@  #define DG_URI "http://drumgizmo.org/lv2" +enum class Ports { +	FreeWheel = 0, +	MidiPort, +	AudioPortOffset, +}; +  /**   * Tests that should be performed:   * ------------------------------- @@ -86,7 +92,7 @@ public:  		res = h.verify();  		CPPUNIT_ASSERT_EQUAL(0, res); -		res = h.createInstance(); +		res = h.createInstance(44100);  		CPPUNIT_ASSERT_EQUAL(0, res);  		const char config_fmt[] = @@ -127,7 +133,7 @@ public:  		// run for 1 samples to trigger kit loading  		res = h.run(1);  		CPPUNIT_ASSERT_EQUAL(0, res); -		sleep(1); // wait for kit to get loaded (async), +		usleep(1000); // wait for kit to get loaded (async),  		res = h.run(100);  		CPPUNIT_ASSERT_EQUAL(0, res); @@ -151,7 +157,7 @@ public:  		res = h.verify();  		CPPUNIT_ASSERT_EQUAL(0, res); -		res = h.createInstance(); +		res = h.createInstance(44100);  		CPPUNIT_ASSERT_EQUAL(0, res);  		const char config_fmt[] = @@ -191,15 +197,19 @@ public:  		// Port buffers:  		char sequence_buffer[4096]; +		bool freeWheel = false; + +		// Free wheel port +		res = h.connectPort((int)Ports::FreeWheel, (void*)&freeWheel);  		LV2TestHost::Sequence seq(sequence_buffer, sizeof(sequence_buffer)); -		res = h.connectPort(0, seq.data()); +		res = h.connectPort((int)Ports::MidiPort, seq.data());  		CPPUNIT_ASSERT_EQUAL(0, res);  		// run for 1 samples to trigger kit loading  		res = h.run(1);  		CPPUNIT_ASSERT_EQUAL(0, res); -		sleep(1); // wait for kit to get loaded (async), +		usleep(1000); // wait for kit to get loaded (async),  		seq.addMidiNote(5, 1, 127);  		res = h.run(100); @@ -224,7 +234,7 @@ public:  		res = h.verify();  		CPPUNIT_ASSERT_EQUAL(0, res); -		res = h.createInstance(); +		res = h.createInstance(44100);  		CPPUNIT_ASSERT_EQUAL(0, res);  		const char config_fmt[] = @@ -265,14 +275,22 @@ public:  		// Port buffers:  		char sequence_buffer[4096];  		float pcm_buffer[16][10]; +		bool freeWheel = true; + +		// Free wheel port +		res = h.connectPort((int)Ports::FreeWheel, (void*)&freeWheel);  		LV2TestHost::Sequence seq(sequence_buffer, sizeof(sequence_buffer)); -		res = h.connectPort(0, seq.data()); +		res = h.connectPort((int)Ports::MidiPort, seq.data());  		CPPUNIT_ASSERT_EQUAL(0, res); -		for(int i = 1; i <= 16; i++) { -			memset(pcm_buffer, 1, sizeof(pcm_buffer)); -			res += h.connectPort(i, pcm_buffer[i-1]); +		for(int i = 0; i < 16; ++i) +		{ +			for(int j = 0; j < 10; ++j) +			{ +				pcm_buffer[i][j] = 0.42; +			} +			res += h.connectPort((int)Ports::AudioPortOffset + i, pcm_buffer[i]);  		}  		CPPUNIT_ASSERT_EQUAL(0, res); @@ -282,19 +300,19 @@ public:  		sleep(1); // wait for kit to get loaded (async),  		seq.addMidiNote(5, 1, 127); -		for(int i = 0; i < 10; i++) { +		for(int i = 0; i < 10; i++) +		{  			res = h.run(10); +			usleep(1000);  			CPPUNIT_ASSERT_EQUAL(0, res); -			/* -			printf("Iteration:\n"); -			for(int k = 0; k < 4; k++) { -				printf("#%d ", k); -				for(int j = 0; j < 10; j++) printf("[%f]", pcm_buffer[k][j]); -				printf("\n"); -			} -			printf("\n"); -			*/ +			//printf("Iteration:\n"); +			//for(int k = 0; k < 16; k++) { +			//	printf("#%d ", k); +			//	for(int j = 0; j < 10; j++) printf("[%f]", pcm_buffer[k][j]); +			//	printf("\n"); +			//} +			//printf("\n");  			seq.clear();  		} @@ -302,6 +320,7 @@ public:  		seq.addMidiNote(5, 1, 127);  		res = h.run(10); +		usleep(1000);  		CPPUNIT_ASSERT_EQUAL(0, res);  		/* @@ -321,9 +340,11 @@ public:  		comp_val.u = 1040744448; // floating point value 0.133301.... -		for(int k = 0; k < 4; k++) { -			for(int j = 0; j < 10; j++) { -	      CPPUNIT_ASSERT_EQUAL(((j==0)?comp_val.f:0), pcm_buffer[k][j]); +		for(int k = 0; k < 4; k++) +		{ +			for(int j = 0; j < 10; j++) +			{ +				CPPUNIT_ASSERT_EQUAL(((j==5)?comp_val.f:0), pcm_buffer[k][j]);  			}  		}  		seq.clear(); diff --git a/test/lv2_test_host.cc b/test/lv2_test_host.cc index 375ae40..9b4fc7a 100644 --- a/test/lv2_test_host.cc +++ b/test/lv2_test_host.cc @@ -42,6 +42,7 @@  #include <openssl/err.h>  #include <openssl/evp.h>  #include <string> +  class Base64 {  public:  	Base64() @@ -64,36 +65,44 @@ public:  	std::string write(const char *in, size_t size)  	{  		std::string out; -		 +  		BIO_write((BIO*)bio, in, size);  		size_t osize = BIO_ctrl_pending((BIO*)mbio);  		char *outbuf = (char*)malloc(osize);  		int len = BIO_read((BIO*)mbio, outbuf, osize); -		if(len < 1) return ""; +		if(len < 1) +		{ +			return ""; +		} +  		out.append(outbuf, len);  		free(outbuf); -		 +  		return out;  	} -	 +  	std::string flush()  	{  		std::string out; -		 +  		(void)BIO_flush((BIO*)bio);  		size_t size = BIO_ctrl_pending((BIO*)mbio);  		char *outbuf = (char*)malloc(size);  		int len = BIO_read((BIO*)mbio, outbuf, size); -		if(len < 1) return ""; +		if(len < 1) +		{ +			return ""; +		} +  		out.append(outbuf, len);  		free(outbuf); -		 +  		return out;  	} @@ -107,13 +116,15 @@ private:  // TODO: Use map<int, std::string> instead -static char** uris = NULL; +static char** uris = nullptr;  static size_t n_uris = 0;  static LV2_URID map_uri(LV2_URID_Map_Handle handle, const char* uri)  { -	for(size_t i = 0; i < n_uris; ++i) { -		if(!strcmp(uris[i], uri)) { +	for(size_t i = 0; i < n_uris; ++i) +	{ +		if(!strcmp(uris[i], uri)) +		{  			return i + 1;  		}  	} @@ -126,22 +137,23 @@ static LV2_URID map_uri(LV2_URID_Map_Handle handle, const char* uri)  static const char* unmap_uri(LV2_URID_Map_Handle handle, LV2_URID urid)  { -	if(urid > 0 && urid <= n_uris) { +	if((urid > 0) && (urid <= n_uris)) +	{  		return uris[urid - 1];  	} -	return NULL; +	return nullptr;  } -LV2_URID_Map       map           = { NULL, map_uri }; +LV2_URID_Map       map           = { nullptr, map_uri };  LV2_Feature        map_feature   = { LV2_URID_MAP_URI, &map }; -LV2_URID_Unmap     unmap         = { NULL, unmap_uri }; +LV2_URID_Unmap     unmap         = { nullptr, unmap_uri };  LV2_Feature        unmap_feature = { LV2_URID_UNMAP_URI, &unmap }; -const LV2_Feature* features[]    = { &map_feature, &unmap_feature, NULL }; +const LV2_Feature* features[]    = { &map_feature, &unmap_feature, nullptr };  LV2TestHost::Sequence::Sequence(void *buffer, size_t buffer_size)  { -  this->buffer = buffer; -  this->buffer_size = buffer_size; +	this->buffer = buffer; +	this->buffer_size = buffer_size;  	seq = (LV2_Atom_Sequence *)buffer; @@ -152,15 +164,14 @@ LV2TestHost::Sequence::Sequence(void *buffer, size_t buffer_size)  }  // Keep this to support atom extension from lv2 < 1.10 -static inline void -_lv2_atom_sequence_clear(LV2_Atom_Sequence* seq) +static inline void _lv2_atom_sequence_clear(LV2_Atom_Sequence* seq)  { -  seq->atom.size = sizeof(LV2_Atom_Sequence_Body); +	seq->atom.size = sizeof(LV2_Atom_Sequence_Body);  }  void LV2TestHost::Sequence::clear()  { -  _lv2_atom_sequence_clear(seq); +	_lv2_atom_sequence_clear(seq);  }  // Keep this to support atom extension from lv2 < 1.10 @@ -169,18 +180,19 @@ _lv2_atom_sequence_append_event(LV2_Atom_Sequence*    seq,                                  uint32_t              capacity,                                  const LV2_Atom_Event* event)  { -  const uint32_t total_size = (uint32_t)sizeof(*event) + event->body.size; - -  if (capacity - seq->atom.size < total_size) { -    return NULL; -  } - -  LV2_Atom_Event* e = lv2_atom_sequence_end(&seq->body, seq->atom.size); -  memcpy(e, event, total_size); -   -  seq->atom.size += lv2_atom_pad_size(total_size); -   -  return e; +	const uint32_t total_size = (uint32_t)sizeof(*event) + event->body.size; + +	if(capacity - seq->atom.size < total_size) +	{ +	  return nullptr; +	} + +	LV2_Atom_Event* e = lv2_atom_sequence_end(&seq->body, seq->atom.size); +	memcpy(e, event, total_size); + +	seq->atom.size += lv2_atom_pad_size(total_size); + +	return e;  }  void LV2TestHost::Sequence::addMidiNote(uint64_t pos, @@ -197,66 +209,88 @@ void LV2TestHost::Sequence::addMidiNote(uint64_t pos,  	ev.event.time.frames = pos;// sample position  	ev.event.body.type = map.map(map.handle, LV2_MIDI__MidiEvent);  	ev.event.body.size = sizeof(ev.msg); -  +  	ev.msg[0] = note_on;  	ev.msg[1] = key;  	ev.msg[2] = velocity;  	LV2_Atom_Event *e =  		_lv2_atom_sequence_append_event(seq, this->buffer_size, &ev.event); -  (void)e; +	(void)e;  }  void *LV2TestHost::Sequence::data()  { -  return buffer; +	return buffer;  }  LV2TestHost::LV2TestHost(const char *lv2_path)  { -	if(lv2_path) { -    setenv("LV2_PATH", lv2_path, 1); -  } +	if(lv2_path) +	{ +		setenv("LV2_PATH", lv2_path, 1); +	}  	world = lilv_world_new(); -  if(world == NULL) return; +	if(world == nullptr) +	{ +		return; +	}  	lilv_world_load_all(world);  }  LV2TestHost::~LV2TestHost()  { -	if(world) lilv_world_free(world); +	if(world) +	{ +		lilv_world_free(world); +	}  }  int LV2TestHost::open(const char *plugin_uri)  { -  if(world == NULL) return 1; +	if(world == nullptr) +	{ +		return 1; +	}  	plugins = lilv_world_get_all_plugins(world); -  if(plugins == NULL) return 2; +	if(plugins == nullptr) +	{ +		return 2; +	}  	uri = lilv_new_uri(world, plugin_uri); -	if(uri == NULL) return 3; +	if(uri == nullptr) +	{ +		return 3; +	}  	plugin = lilv_plugins_get_by_uri(plugins, uri); -  if(plugin == NULL) return 4; - +	if(plugin == nullptr) +	{ +		return 4; +	} -  return 0; +	return 0;  }  int LV2TestHost::verify()  {  	bool verify = lilv_plugin_verify(plugin); -  if(!verify) return 1; -  return 0; +	if(!verify) +	{ +		return 1; +	} + +	return 0;  }  int LV2TestHost::close()  { -  // plugin is a const pointer; nothing to close here. -  return 0; +	// plugin is a const pointer; nothing to close here. +	return 0;  }  /* // Get metadata @@ -330,29 +364,37 @@ int LV2TestHost::getPorts()  	}  }  */ -int LV2TestHost::createInstance() +int LV2TestHost::createInstance(size_t samplerate)  { -	instance = lilv_plugin_instantiate(plugin, 48000, features); -  if(instance == NULL) return 1; -  return 0; +	instance = lilv_plugin_instantiate(plugin, samplerate, features); +	if(instance == nullptr) +	{ +		return 1; +	} + +	return 0;  }  int LV2TestHost::destroyInstance()  { -  if(instance) lilv_instance_free(instance); -  return 0; +	if(instance) +	{ +		lilv_instance_free(instance); +	} + +	return 0;  }  int LV2TestHost::activate()  {  	lilv_instance_activate(instance); -  return 0; +	return 0;  }  int LV2TestHost::deactivate()  {  	lilv_instance_deactivate(instance); -  return 0; +	return 0;  }  int LV2TestHost::loadConfig(const char *config, size_t size) @@ -379,26 +421,26 @@ int LV2TestHost::loadConfig(const char *config, size_t size)  	{  		LilvState* restore_state =  			lilv_state_new_from_string(world, &map, ttl_config); -		 -		lilv_state_restore(restore_state, instance, NULL, NULL, -											 LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE, -											 features); + +		lilv_state_restore(restore_state, instance, nullptr, nullptr, +		                   LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE, +		                   features);  	} -  return 0; +	return 0;  }  int LV2TestHost::connectPort(int port, void *portdata)  { -  //  if(lilv_port_is_a(p, port, lv2_ControlPort)) ... +	//  if(lilv_port_is_a(p, port, lv2_ControlPort)) ...  	lilv_instance_connect_port(instance, port, portdata); -  return 0; +	return 0;  }  int LV2TestHost::run(int num_samples)  { -  lilv_instance_run(instance, num_samples); -  return 0; +	lilv_instance_run(instance, num_samples); +	return 0;  } diff --git a/test/lv2_test_host.h b/test/lv2_test_host.h index f0677c7..81aa413 100644 --- a/test/lv2_test_host.h +++ b/test/lv2_test_host.h @@ -24,56 +24,53 @@   *  along with DrumGizmo; if not, write to the Free Software   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.   */ -#ifndef __DRUMGIZMO_LV2_TEST_HOST_H__ -#define __DRUMGIZMO_LV2_TEST_HOST_H__ +#pragma once  #include <lilv/lilv.h>  #include <lv2/lv2plug.in/ns/ext/atom/atom.h>  class LV2TestHost {  public: -  class Sequence { -  public: -    Sequence(void *buffer, size_t buffer_size); -    void clear(); -    void addMidiNote(uint64_t pos, uint8_t key, int8_t velocity); -    void *data(); +	class Sequence { +	public: +		Sequence(void *buffer, size_t buffer_size); +		void clear(); +		void addMidiNote(uint64_t pos, uint8_t key, int8_t velocity); +		void *data(); -  private: -    void *buffer; -    size_t buffer_size; -    LV2_Atom_Sequence *seq; -  }; +	private: +		void *buffer; +		size_t buffer_size; +		LV2_Atom_Sequence *seq; +	}; -  LV2TestHost(const char *lv2_path); -  ~LV2TestHost(); +	LV2TestHost(const char *lv2_path); +	~LV2TestHost(); -  int open(const char *plugin_uri); -  int close(); +	int open(const char *plugin_uri); +	int close(); -  int verify(); +	int verify(); -  //void getMetadata(); -  //int getPorts(); +	//void getMetadata(); +	//int getPorts(); -  int createInstance(); -  int destroyInstance(); +	int createInstance(size_t samplerate); +	int destroyInstance(); -  int connectPort(int port, void *portdata); +	int connectPort(int port, void *portdata); -  int activate(); -  int deactivate(); +	int activate(); +	int deactivate(); -  int loadConfig(const char *config, size_t size); -  int run(int num_samples); +	int loadConfig(const char *config, size_t size); +	int run(int num_samples);  private: -  LilvWorld* world; -  const LilvPlugins* plugins;   +	LilvWorld* world; +	const LilvPlugins* plugins;  	LilvNode* uri;  	const LilvPlugin* plugin; -  LilvInstance* instance; +	LilvInstance* instance;  }; - -#endif/*__DRUMGIZMO_LV2_TEST_HOST_H__*/ | 
